(六十九) 探究如何让Service anr?
demo地址:https://github.com/happyjiatai/demo_csdn/tree/master/demo_69_service
参考:
1.(六十五)Android O StartService的 anr timeout 流程分析
2. (七十)Android O Service启动流程梳理——bindService
3. (六十四)Android O Service启动流程梳理——startService
4. Android中bindService的细节之二:从进程的角度分析绑定Service的流程【Service所在进程已存在】
1.起因
最近在看Service的启动源码,涉及anr这块,发生anr是统计了特定方法执行时间,如果超过限定值,则anr,和我之前想的不大一样。简单地让Service anr的做法是在onCreate或者onStartCommand或者onBind或者onUnbind或者onDestroy中执行20s+的操作,则anr,不需要几者累加大于20s,统计是分开统计的,和几者耗时之和没有关系,以上耗时之和可以大于20s。(后台Service是200s)
2.测试demo
写了个demo:
布局:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/buttonStart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="startService"
app:layout_constraintBottom_toTopOf="@+id/buttonBind"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.219" />
<Button
android:id="@+id/buttonBind"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="268dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:text="bindService"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</android.support.constraint.ConstraintLayout>
string
<resources>
<string name="app_name">Demo_69_service</string>
<string name="channel_name">channel_name</string>
<string name="channel_description">channel_description</string>
</resources>
AndroidManifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.demo_69_service">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".MyService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.csdnservice" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
</application>
</manifest>
Activity
package com.example.demo_69_service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "demo69_activity";
private MyService myService;
private boolean isBound = false;
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "onServiceConnected", new RuntimeException());
isBound = true;
MyService.MyBinder binder = (MyService.MyBinder) service;
myService = binder.getService();
}
//client 和service连接意外丢失时,会调用该方法
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "onServiceDisconnected", new RuntimeException());
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Intent serviceIntent = new Intent("android.intent.action.csdnservice");
serviceIntent.setPackage("com.example.demo_69_service");
Button btnForStartService = findViewById(R.id.buttonStart);
btnForStartService.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startForegroundService(serviceIntent);
}
});
Button btnForBindService = findViewById(R.id.buttonBind);
btnForBindService.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
bindService(serviceIntent, conn, BIND_AUTO_CREATE);
}
});
}
}
Service:
package com.example.demo_69_service;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
public class MyService extends Service {
private static final String TAG = "demo69_service";
private MyBinder Ibind = new MyBinder();
public class MyBinder extends Binder {
public MyService getService() {
return MyService.this;
}
}
public MyService() {
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate", new RuntimeException());
createNotificationChannel();
}
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind", new RuntimeException());
return Ibind;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand", new RuntimeException());
return super.onStartCommand(intent, flags, startId);
}
private void createNotificationChannel() {
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// 通知渠道的id
String id = "my_channel_01";
// 用户可以看到的通知渠道的名字.
CharSequence name = getString(R.string.channel_name);
// 用户可以看到的通知渠道的描述
String description = getString(R.string.channel_description);
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel mChannel = new NotificationChannel(id, name, importance);
// 配置通知渠道的属性
mChannel.setDescription(description);
// 设置通知出现时的闪灯(如果 android 设备支持的话)
mChannel.enableLights(true); mChannel.setLightColor(Color.RED);
// 设置通知出现时的震动(如果 android 设备支持的话)
mChannel.enableVibration(true);
mChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
// 最后在notificationmanager中创建该通知渠道 //
mNotificationManager.createNotificationChannel(mChannel);
// 为该通知设置一个id
int notifyID = 1;
// 通知渠道的id
String CHANNEL_ID = "my_channel_01";
// Create a notification and set the notification channel.
Notification notification = new Notification.Builder(this)
.setContentTitle("New Message") .setContentText("You've received new messages.")
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setChannelId(CHANNEL_ID)
.build();
startForeground(1,notification);
}
}
3.测试
3.1 startService
07-13 23:51:43.602 6525-6525/com.example.demo_69_service D/demo69_service: onCreate
java.lang.RuntimeException
at com.example.demo_69_service.MyService.onCreate(MyService.java:31)
at android.app.ActivityThread.handleCreateService(ActivityThread.java:3442)
at android.app.ActivityThread.-wrap4(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1711)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:171)
at android.app.ActivityThread.main(ActivityThread.java:6684)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:246)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)
07-13 23:51:43.616 6525-6525/com.example.demo_69_service D/demo69_service: onStartCommand
java.lang.RuntimeException
at com.example.demo_69_service.MyService.onStartCommand(MyService.java:44)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3577)
at android.app.ActivityThread.-wrap20(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1726)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:171)
at android.app.ActivityThread.main(ActivityThread.java:6684)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:246)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)
3.2 bindService
07-14 13:08:12.852 3992-3992/com.example.demo_69_service D/demo69_service: onCreate
java.lang.RuntimeException
at com.example.demo_69_service.MyService.onCreate(MyService.java:31)
at android.app.ActivityThread.handleCreateService(ActivityThread.java:3442)
at android.app.ActivityThread.-wrap4(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1711)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:171)
at android.app.ActivityThread.main(ActivityThread.java:6684)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:246)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)
07-14 13:08:12.856 3992-3992/com.example.demo_69_service D/demo69_service: onBind
java.lang.RuntimeException
at com.example.demo_69_service.MyService.onBind(MyService.java:38)
at android.app.ActivityThread.handleBindService(ActivityThread.java:3469)
at android.app.ActivityThread.-wrap2(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1716)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:171)
at android.app.ActivityThread.main(ActivityThread.java:6684)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:246)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)
07-14 13:08:12.857 3992-3992/com.example.demo_69_service D/demo69_activity: onServiceConnected
java.lang.RuntimeException
at com.example.demo_69_service.MainActivity$1.onServiceConnected(MainActivity.java:22)
at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1645)
at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1674)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:171)
at android.app.ActivityThread.main(ActivityThread.java:6684)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:246)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)
小米mix只走了了onCreate和onBind方法,onStartCommand是不走的。
3.3 startService+bindService
第一次start Service
07-13 23:51:43.602 6525-6525/com.example.demo_69_service D/demo69_service: onCreate
java.lang.RuntimeException
at com.example.demo_69_service.MyService.onCreate(MyService.java:31)
at android.app.ActivityThread.handleCreateService(ActivityThread.java:3442)
at android.app.ActivityThread.-wrap4(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1711)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:171)
at android.app.ActivityThread.main(ActivityThread.java:6684)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:246)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)
07-13 23:51:43.616 6525-6525/com.example.demo_69_service D/demo69_service: onStartCommand
java.lang.RuntimeException
at com.example.demo_69_service.MyService.onStartCommand(MyService.java:44)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3577)
at android.app.ActivityThread.-wrap20(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1726)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:171)
at android.app.ActivityThread.main(ActivityThread.java:6684)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:246)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)
第一次启动bind Service
07-13 23:52:18.474 6525-6525/com.example.demo_69_service D/demo69_service: onBind
java.lang.RuntimeException
at com.example.demo_69_service.MyService.onBind(MyService.java:38)
at android.app.ActivityThread.handleBindService(ActivityThread.java:3469)
at android.app.ActivityThread.-wrap2(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1716)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:171)
at android.app.ActivityThread.main(ActivityThread.java:6684)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:246)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)
07-13 23:52:18.483 6525-6525/com.example.demo_69_service D/demo69_activity: onServiceConnected
java.lang.RuntimeException
at com.example.demo_69_service.MainActivity$1.onServiceConnected(MainActivity.java:22)
at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1645)
at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1674)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:171)
at android.app.ActivityThread.main(ActivityThread.java:6684)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:246)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)
第二次start Service
07-13 23:58:09.283 6525-6525/com.example.demo_69_service D/demo69_service: onStartCommand
java.lang.RuntimeException
at com.example.demo_69_service.MyService.onStartCommand(MyService.java:44)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3577)
at android.app.ActivityThread.-wrap20(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1726)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:171)
at android.app.ActivityThread.main(ActivityThread.java:6684)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:246)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)
第二次启动bind Service
尴尬,一个log都没有
小米 mix2是不会重复bind的。这里对应原因:
ActiveServices.java
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
boolean execInFg, boolean rebind) throws TransactionTooLargeException {
if (r.app == null || r.app.thread == null) {
// If service is not currently running, can't yet bind.
return false;
}
if (DEBUG_SERVICE) Slog.d(TAG_SERVICE, "requestBind " + i + ": requested=" + i.requested
+ " rebind=" + rebind);
if ((!i.requested || rebind) && i.apps.size() > 0) {
try {
bumpServiceExecutingLocked(r, execInFg, "bind");
r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
r.app.repProcState);
if (!rebind) {
i.requested = true;
}
i.hasBound = true;
i.doRebind = false;
} catch (TransactionTooLargeException e) {
// Keep the executeNesting count accurate.
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while binding " + r, e);
final boolean inDestroying = mDestroyingServices.contains(r);
serviceDoneExecutingLocked(r, inDestroying, inDestroying);
throw e;
} catch (RemoteException e) {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while binding " + r);
// Keep the executeNesting count accurate.
final boolean inDestroying = mDestroyingServices.contains(r);
serviceDoneExecutingLocked(r, inDestroying, inDestroying);
return false;
}
}
return true;
}
i.requested || rebind) && i.apps.size() > 0) {
try {
bumpServiceExecutingLocked(r, execInFg, "bind");
r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
r.app.repProcState);
if (!rebind) {
i.requested = true;
}
i.hasBound = true;
i.doRebind = false;
} catch (TransactionTooLargeException e) {
// Keep the executeNesting count accurate.
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while binding " + r, e);
final boolean inDestroying = mDestroyingServices.contains(r);
serviceDoneExecutingLocked(r, inDestroying, inDestroying);
throw e;
} catch (RemoteException e) {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while binding " + r);
// Keep the executeNesting count accurate.
final boolean inDestroying = mDestroyingServices.contains(r);
serviceDoneExecutingLocked(r, inDestroying, inDestroying);
return false;
}
}
return true;
}
bind过之后b.requested为true就不会再走进去了(IntentBindRecord),rebind传进来的时候就是false。
b.binder = service;
b.requested = true;
b.received = true;
而connect方法是否会重复调用取决于LoadedApk
old = mActiveConnections.get(name);
if (old != null && old.binder == service) {
// Huh, already have this one. Oh well!
return;
}
3.4 second activity bind
修改多启动一个activity然后bind到该Service
log:
07-14 15:19:37.718 10747-10747/com.example.demo_69_service D/demo69_activity: bindService success :
07-14 15:19:37.756 10747-10747/com.example.demo_69_service D/demo69_service: onCreate
java.lang.RuntimeException
at com.example.demo_69_service.MyService.onCreate(MyService.java:31)
at android.app.ActivityThread.handleCreateService(ActivityThread.java:3442)
at android.app.ActivityThread.-wrap4(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1711)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:171)
at android.app.ActivityThread.main(ActivityThread.java:6684)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:246)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)
07-14 15:19:37.771 10747-10747/com.example.demo_69_service D/demo69_service: onBind
java.lang.RuntimeException
at com.example.demo_69_service.MyService.onBind(MyService.java:38)
at android.app.ActivityThread.handleBindService(ActivityThread.java:3469)
at android.app.ActivityThread.-wrap2(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1716)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:171)
at android.app.ActivityThread.main(ActivityThread.java:6684)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:246)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)
07-14 15:19:37.778 10747-10747/com.example.demo_69_service D/demo69_activity: onServiceConnected
java.lang.RuntimeException
at com.example.demo_69_service.MainActivity$1.onServiceConnected(MainActivity.java:22)
at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1645)
at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1674)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:171)
at android.app.ActivityThread.main(ActivityThread.java:6684)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:246)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)
07-14 15:19:42.779 10747-10747/com.example.demo_69_service D/demo69_activity: onServiceConnected 5s later
07-14 15:19:54.264 10747-10747/com.example.demo_69_service D/demo69_activity2: oncreate:
07-14 15:19:58.237 10747-10747/com.example.demo_69_service D/demo69_activity2: bindService success :
07-14 15:19:58.243 10747-10747/com.example.demo_69_service D/demo69_activity2: onServiceConnected
java.lang.RuntimeException
at com.example.demo_69_service.Main2Activity$1.onServiceConnected(Main2Activity.java:22)
at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1645)
at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1674)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:171)
at android.app.ActivityThread.main(ActivityThread.java:6684)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:246)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)
07-14 15:20:03.245 10747-10747/com.example.demo_69_service D/demo69_activity2: onServiceConnected 5s later
从log来看onBind不会被调用第二次,不管是一个activity还是第二个activity。
这个还有结合源码再看一下原因,待续。第四篇参考博客是这么说的
对应代码在ActiveServices.java内
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bind " + s + " with " + b
+ ": received=" + b.intent.received
+ " apps=" + b.intent.apps.size()
+ " doRebind=" + b.intent.doRebind);
if (s.app != null && b.intent.received) {
// Service is already running, so we can immediately
// publish the connection.
try {
c.conn.connected(s.name, b.intent.binder, false);
} catch (Exception e) {
Slog.w(TAG, "Failure sending service " + s.shortName
+ " to connection " + c.conn.asBinder()
+ " (in " + c.binding.client.processName + ")", e);
}
// If this is the first app connected back to this binding,
// and the service had previously asked to be told when
// rebound, then do so.
if (b.intent.apps.size() == 1 && b.intent.doRebind) {
requestServiceBindingLocked(s, b.intent, callerFg, true);
}
} else if (!b.intent.requested) {
requestServiceBindingLocked(s, b.intent, callerFg, false);
}
b.intent.received) {
// Service is already running, so we can immediately
// publish the connection.
try {
c.conn.connected(s.name, b.intent.binder, false);
} catch (Exception e) {
Slog.w(TAG, "Failure sending service " + s.shortName
+ " to connection " + c.conn.asBinder()
+ " (in " + c.binding.client.processName + ")", e);
}
// If this is the first app connected back to this binding,
// and the service had previously asked to be told when
// rebound, then do so.
if (b.intent.apps.size() == 1 && b.intent.doRebind) {
requestServiceBindingLocked(s, b.intent, callerFg, true);
}
} else if (!b.intent.requested) {
requestServiceBindingLocked(s, b.intent, callerFg, false);
}
3.5 多个持续不断的start service
添加一个按钮,startMore
Button btnForStartMore = findViewById(R.id.buttonStartMore);
btnForStartMore.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
for(int i = 0; i< 5; i++) {
Log.d(TAG, "btnForStartMore :" + i);
startService(serviceIntent);
}
}
});
service的onStartCommand睡眠以模拟耗时操作
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand: " + startId, new RuntimeException());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return super.onStartCommand(intent, flags, startId);
}
效果:
log:
07-14 14:37:04.250 7526-7526/com.example.demo_69_service D/demo69_service: onCreate
java.lang.RuntimeException
at com.example.demo_69_service.MyService.onCreate(MyService.java:31)
at android.app.ActivityThread.handleCreateService(ActivityThread.java:3442)
at android.app.ActivityThread.-wrap4(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1711)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:171)
at android.app.ActivityThread.main(ActivityThread.java:6684)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:246)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)
07-14 14:37:04.263 7526-7526/com.example.demo_69_service D/demo69_service: onStartCommand: 1
java.lang.RuntimeException
at com.example.demo_69_service.MyService.onStartCommand(MyService.java:50)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3577)
at android.app.ActivityThread.-wrap20(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1726)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:171)
at android.app.ActivityThread.main(ActivityThread.java:6684)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:246)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)
07-14 14:37:09.323 7526-7526/com.example.demo_69_service D/demo69_activity: btnForStartMore :0
07-14 14:37:09.335 7526-7526/com.example.demo_69_service D/demo69_activity: btnForStartMore :1
07-14 14:37:09.344 7526-7526/com.example.demo_69_service D/demo69_activity: btnForStartMore :2
07-14 14:37:09.352 7526-7526/com.example.demo_69_service D/demo69_activity: btnForStartMore :3
07-14 14:37:09.361 7526-7526/com.example.demo_69_service D/demo69_activity: btnForStartMore :4
07-14 14:37:09.384 7526-7526/com.example.demo_69_service D/demo69_service: onStartCommand: 2
java.lang.RuntimeException
at com.example.demo_69_service.MyService.onStartCommand(MyService.java:50)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3577)
at android.app.ActivityThread.-wrap20(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1726)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:171)
at android.app.ActivityThread.main(ActivityThread.java:6684)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:246)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)
07-14 14:37:14.396 7526-7526/com.example.demo_69_service D/demo69_service: onStartCommand: 3
java.lang.RuntimeException
at com.example.demo_69_service.MyService.onStartCommand(MyService.java:50)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3577)
at android.app.ActivityThread.-wrap20(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1726)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:171)
at android.app.ActivityThread.main(ActivityThread.java:6684)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:246)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)
07-14 14:37:19.411 7526-7526/com.example.demo_69_service D/demo69_service: onStartCommand: 4
java.lang.RuntimeException
at com.example.demo_69_service.MyService.onStartCommand(MyService.java:50)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3577)
at android.app.ActivityThread.-wrap20(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1726)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:171)
at android.app.ActivityThread.main(ActivityThread.java:6684)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:246)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)
07-14 14:37:24.424 7526-7526/com.example.demo_69_service D/demo69_service: onStartCommand: 5
java.lang.RuntimeException
at com.example.demo_69_service.MyService.onStartCommand(MyService.java:50)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3577)
at android.app.ActivityThread.-wrap20(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1726)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:171)
at android.app.ActivityThread.main(ActivityThread.java:6684)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:246)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)
07-14 14:37:29.430 7526-7526/com.example.demo_69_service D/demo69_service: onStartCommand: 6
java.lang.RuntimeException
at com.example.demo_69_service.MyService.onStartCommand(MyService.java:50)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3577)
at android.app.ActivityThread.-wrap20(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1726)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:171)
at android.app.ActivityThread.main(ActivityThread.java:6684)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:246)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)
发现了一个问题,我先点击startService,再点击startMore,但startMore是等5s后再执行的,等了一个onStartCommond的时间,说明:startForegroundService是同步的(阻塞),startService是异步的(命令一次性下发,不阻塞)
anr log
07-14 14:37:36.339 1539-1590/? E/ActivityManager: ANR in com.example.demo_69_service
PID: 7526
Reason: executing service com.example.demo_69_service/.MyService
Load: 0.08 / 0.09 / 0.04
CPU usage from 0ms to 6928ms later (2018-07-14 14:37:29.374 to 2018-07-14 14:37:36.303):
25% 1539/system_server: 14% user + 11% kernel / faults: 1956 minor
2.5% 2256/com.android.phone: 2% user + 0.4% kernel / faults: 245 minor
1.9% 913/media.codec: 0.8% user + 1% kernel / faults: 2128 minor
0.5% 5156/com.sohu.inputmethod.sogou.xiaomi: 0.5% user + 0% kernel / faults: 358 minor
2.6% 4780/kworker/u16:7: 0% user + 2.6% kernel
0.7% 907/media.extractor: 0.3% user + 0.3% kernel / faults: 1786 minor
1.4% 7526/com.example.demo_69_service: 1% user + 0.4% kernel / faults: 867 minor
0.2% 3052/com.android.nfc: 0.1% user + 0.1% kernel / faults: 241 minor
1% 5403/kworker/u16:13: 0% user + 1% kernel
0.8% 564/logd: 0.4% user + 0.4% kernel
0.7% 436/cfinteractive: 0% user + 0.7% kernel
0.5% 773/surfaceflinger: 0.4% user + 0.1% kernel / faults: 366 minor
0.5% 7323/adbd: 0% user + 0.5% kernel / faults: 116 minor
0.4% 743/aaa@qq.com: 0.1% user + 0.2% kernel
0.4% 2563/mcd: 0.1% user + 0.2% kernel
0.4% 8479/com.android.bluetooth: 0.1% user + 0.2% kernel / faults: 108 minor
0.1% 7/rcu_preempt: 0% user + 0.1% kernel
0.2% 81/smem_native_rpm: 0% user + 0.2% kernel
0% 929/tombstoned: 0% user + 0% kernel
0.2% 2979/cnss_diag: 0.1% user + 0.1% kernel
0.2% 6917/kworker/u16:8: 0% user + 0.2% kernel
0.2% 30554/com.tencent.mm:tools: 0.2% user + 0% kernel
0% 1//init: 0% user + 0% kernel
0.1% 3/ksoftirqd/0: 0% user + 0.1% kernel
0% 10/rcuop/0: 0% user + 0% kernel
0.1% 15/ksoftirqd/1: 0% user + 0.1% kernel
0% 53/rcuop/6: 0% user + 0% kernel
0.1% 278/kgsl_worker_thr: 0% user + 0.1% kernel
0% 347/kworker/u17:0: 0% user + 0% kernel
0% 550/jbd2/sda17-8: 0% user + 0% kernel
0% 572/kauditd: 0% user + 0% kernel
0.1% 737/aaa@qq.com: 0.1% user + 0% kernel
0.1% 749/aaa@qq.com: 0% user + 0.1% kernel
0.1% 888/thermal-engine: 0% user + 0.1% kernel
0% 899/audioserver: 0% user + 0% kernel / faults: 31 minor
0% 901/cameraserver: 0% user + 0% kernel / faults: 28 minor
0% 902/drmserver: 0% user + 0% kernel / faults: 38 minor
0% 910/mediaserver: 0% user + 0% kernel / faults: 28 minor
0.1% 993/msm_irqbalance: 0% user + 0.1% kernel
0.1% 1416/kworker/u17:1: 0% user + 0.1% kernel
0.1% 1863/cds_mc_thread: 0% user + 0.1% kernel
0% 3831/kworker/5:3: 0% user + 0% kernel
0.1% 5127/kworker/1:3: 0% user + 0.1% kernel
0.1% 7030/mdss_fb0: 0% user + 0.1% kernel
0.1% 7580/logcat: 0% user + 0.1% kernel
0.1% 30111/com.tencent.mm:exdevice: 0% user + 0.1% kernel
9% TOTAL: 4.8% user + 3.8% kernel + 0.1% iowait + 0% irq + 0.1% softirq
CPU usage from 6347ms to 6873ms later (2018-07-14 14:37:35.721 to 2018-07-14 14:37:36.248) with 99% awake:
7.3% 1539/system_server: 1.8% user + 5.4% kernel
7.3% 1590/ActivityManager: 3.6% user + 3.6% kernel
2.9% 4780/kworker/u16:7: 0% user + 2.9% kernel
1.1% 743/aaa@qq.com: 0% user + 1.1% kernel
1.1% 1829/HwBinder:743_1: 0% user + 1.1% kernel
1.8% TOTAL: 0% user + 1.6% kernel + 0.2% softirq
traces.txt正好打印出了耗时操作,美滋滋
----- pid 7526 at 2018-07-14 14:37:29 -----
Cmd line: com.example.demo_69_service
"main" prio=5 tid=1 Sleeping
| group="main" sCount=1 dsCount=0 flags=1 obj=0x731df7d0 self=0x76efe14c00
| sysTid=7526 nice=-10 cgrp=default sched=0/0 handle=0x76f45d29b0
| state=S schedstat=( 0 0 0 ) utm=48 stm=5 core=0 HZ=100
| stack=0x7fc9d01000-0x7fc9d03000 stackSize=8MB
| held mutexes=
at java.lang.Thread.sleep(Native method)
- sleeping on <0x048da97c> (a java.lang.Object)
at java.lang.Thread.sleep(Thread.java:373)
- locked <0x048da97c> (a java.lang.Object)
at java.lang.Thread.sleep(Thread.java:314)
at com.example.demo_69_service.MyService.onStartCommand(MyService.java:52)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3577)
at android.app.ActivityThread.-wrap20(ActivityThread.java:-1)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1726)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:171)
at android.app.ActivityThread.main(ActivityThread.java:6684)
at java.lang.reflect.Method.invoke(Native method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:246)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)
9s到29s正好20s导致Service anr
结论:Service不可不间断调用onStartCommand工作20s及以上,否则anr,或者说activity不可不间断startService作耗时操作。(完成一个任务是不会remove掉第一个任务刚开始执行的timeout消息的,会判断是否都执行完才remove)
3.6 bind service以后调用Service方法,其中一方法耗时20s+,会不会导致Service anr
修改:
Button btnSomeWork = findViewById(R.id.buttonDoWork);
btnSomeWork.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (myService != null){
myService.doSomeWork();
}
}
});
Service:
public void doSomeWork(){
Log.d(TAG, "doSomeWork begin");
try {
Thread.sleep(25000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d(TAG, "doSomeWork end");
}
log:
07-14 14:49:42.937 8209-8209/com.example.demo_69_service D/demo69_service: doSomeWork begin
07-14 14:50:07.941 8209-8209/com.example.demo_69_service D/demo69_service: doSomeWork end
现象:不会anr,和框架中只监控create、bind、start过程一致。
这只是模拟在monkey或者负载比较高时某些方法比较耗时情况下Service是否会anr,正确做法是耗时操作用IntentService或者另起一个线程。
3.7 onServiceConnected中有耗时20s+操作,是否anr
修改
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "onServiceConnected", new RuntimeException());
try {
Thread.sleep(25000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d(TAG, "onServiceConnected 25s later");
isBound = true;
MyService.MyBinder binder = (MyService.MyBinder) service;
myService = binder.getService();
}
//client 和service连接意外丢失时,会调用该方法
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "onServiceDisconnected", new RuntimeException());
}
};
log:
07-14 14:56:58.922 8920-8920/com.example.demo_69_service D/demo69_service: onCreate
java.lang.RuntimeException
at com.example.demo_69_service.MyService.onCreate(MyService.java:31)
at android.app.ActivityThread.handleCreateService(ActivityThread.java:3442)
at android.app.ActivityThread.-wrap4(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1711)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:171)
at android.app.ActivityThread.main(ActivityThread.java:6684)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:246)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)
07-14 14:56:58.933 8920-8920/com.example.demo_69_service D/demo69_service: onBind
java.lang.RuntimeException
at com.example.demo_69_service.MyService.onBind(MyService.java:38)
at android.app.ActivityThread.handleBindService(ActivityThread.java:3469)
at android.app.ActivityThread.-wrap2(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1716)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:171)
at android.app.ActivityThread.main(ActivityThread.java:6684)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:246)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)
07-14 14:56:58.935 8920-8920/com.example.demo_69_service D/demo69_activity: onServiceConnected
java.lang.RuntimeException
at com.example.demo_69_service.MainActivity$1.onServiceConnected(MainActivity.java:22)
at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1645)
at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1674)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:171)
at android.app.ActivityThread.main(ActivityThread.java:6684)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:246)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)
07-14 14:57:23.940 8920-8920/com.example.demo_69_service D/demo69_activity: onServiceConnected 25s later
结论:不会anr
3.8 bind service是否必须等待onServiceConnected被调用
修改
Button btnForBindService = findViewById(R.id.buttonBind);
btnForBindService.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
bindService(serviceIntent, conn, BIND_AUTO_CREATE);
Log.d(TAG, "bindService success :");
}
});
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "onServiceConnected", new RuntimeException());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d(TAG, "onServiceConnected 5s later");
isBound = true;
MyService.MyBinder binder = (MyService.MyBinder) service;
myService = binder.getService();
}
log:
07-14 15:02:58.042 9315-9315/com.example.demo_69_service D/demo69_activity: bindService success :
07-14 15:02:58.064 9315-9315/com.example.demo_69_service D/demo69_service: onCreate
java.lang.RuntimeException
at com.example.demo_69_service.MyService.onCreate(MyService.java:31)
at android.app.ActivityThread.handleCreateService(ActivityThread.java:3442)
at android.app.ActivityThread.-wrap4(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1711)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:171)
at android.app.ActivityThread.main(ActivityThread.java:6684)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:246)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)
07-14 15:02:58.076 9315-9315/com.example.demo_69_service D/demo69_service: onBind
java.lang.RuntimeException
at com.example.demo_69_service.MyService.onBind(MyService.java:38)
at android.app.ActivityThread.handleBindService(ActivityThread.java:3469)
at android.app.ActivityThread.-wrap2(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1716)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:171)
at android.app.ActivityThread.main(ActivityThread.java:6684)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:246)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)
07-14 15:02:58.083 9315-9315/com.example.demo_69_service D/demo69_activity: onServiceConnected
java.lang.RuntimeException
at com.example.demo_69_service.MainActivity$1.onServiceConnected(MainActivity.java:22)
at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1645)
at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1674)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:171)
at android.app.ActivityThread.main(ActivityThread.java:6684)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:246)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)
07-14 15:03:03.085 9315-9315/com.example.demo_69_service D/demo69_activity: onServiceConnected 5s later
结论:bindService一旦调用是不会等流程结束的,主线程会继续往下走,即不管onServiceConnected有没有被调用都不影响后面逻辑的执行。但是onServiceConnected还是执行在主线程的,不能进行耗时操作,会导致主线程anr。
07-15 11:22:30.029 8808-8808/com.example.demo_69_service D/demo69_activity: onCreateThread[main,5,main]
07-15 11:22:46.761 8808-8808/com.example.demo_69_service D/demo69_activity: bindService success :
07-15 11:22:46.778 8808-8808/com.example.demo_69_service D/demo69_service: onCreateThread[main,5,main]
java.lang.RuntimeException
at com.example.demo_69_service.MyService.onCreate(MyService.java:31)
at android.app.ActivityThread.handleCreateService(ActivityThread.java:3442)
at android.app.ActivityThread.-wrap4(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1711)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:171)
at android.app.ActivityThread.main(ActivityThread.java:6684)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:246)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)
07-15 11:22:46.791 8808-8808/com.example.demo_69_service D/demo69_service: onBindThread[main,5,main]
java.lang.RuntimeException
at com.example.demo_69_service.MyService.onBind(MyService.java:38)
at android.app.ActivityThread.handleBindService(ActivityThread.java:3469)
at android.app.ActivityThread.-wrap2(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1716)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:171)
at android.app.ActivityThread.main(ActivityThread.java:6684)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:246)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)
07-15 11:22:46.795 8808-8808/com.example.demo_69_service D/demo69_activity: onServiceConnectedThread[main,5,main]
java.lang.RuntimeException
at com.example.demo_69_service.MainActivity$1.onServiceConnected(MainActivity.java:22)
at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1645)
at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1674)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:171)
at android.app.ActivityThread.main(ActivityThread.java:6684)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:246)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)
07-15 11:22:51.797 8808-8808/com.example.demo_69_service D/demo69_activity: onServiceConnected 5s later
这里需要再结合源码看一下:
onServiceConnected
public void connected(ComponentName name, IBinder service, boolean dead) {
if (mActivityThread != null) {
mActivityThread.post(new RunConnection(name, service, 0, dead));
} else {
doConnected(name, service, dead);
}
}
从堆栈来看走到mActivityThread.post方法中去了。
可以参考Android中bindService的细节之二:从进程的角度分析绑定Service的流程【Service所在进程已存在】
这篇对线程切换讲的很清楚,也解释了上面的流程现象。
4. 总结
- 在onCreate或者onStartCommand或者onBind或者onUnbind或者onDestroy中执行20s+(200s+)的操作
- 在onStartCommand 持续进行累计20s+(200s+)的操作
- 调用Service的某个耗时方法不会造成anr
ActiveServices.java
requestServiceBindingLocked: bumpServiceExecutingLocked(r, execInFg, "bind");
realStartServiceLocked:bumpServiceExecutingLocked(r, execInFg, "bind");
sendServiceArgsLocked: bumpServiceExecutingLocked(r, execInFg, "start");
bringDownServiceLocked:bumpServiceExecutingLocked(r, false, "bring down unbind");
bringDownServiceLocked:bumpServiceExecutingLocked(r, false, "destroy");
removeConnectionLocked: bumpServiceExecutingLocked(s, false, "unbind");
上一篇: python web学习笔记一----基础的动静态网页
下一篇: 38. Count and Say