徐州市政工程招标信息,企业网站优化多少钱,县区网站建设运行汇报,dedecms对比wordpress该系列文章总纲链接#xff1a;专题总纲目录 Android Framework 总纲 本章关键点总结 说明#xff1a; 说明#xff1a;本章节主要解读应用层service组件启动的2种方式startService和bindService#xff0c;以及从APP层到AMS调用之间的打通。关注思维导图中左侧部分即…该系列文章总纲链接专题总纲目录 Android Framework 总纲 本章关键点总结 说明 说明本章节主要解读应用层service组件启动的2种方式startService和bindService以及从APP层到AMS调用之间的打通。关注思维导图中左侧部分即可。
有了前面startActivity流程分析的基础接下来我们来分析service组件启动的流程。
在Android中startService和bindService是两种不同的服务Service启动方式它们在应用中的作用和使用场景有所不同。下面我将通过两个demo来说明它们之间的区别。
1 startService VS bindService
1.1 startService解读及应用
startService用于启动一个服务该服务会在后台运行即使启动它的组件已经不存在服务也会继续运行。这种服务适合执行一些不需要与用户交互的任务比如下载文件、播放音乐等。
假设我们有一个音乐播放器应用用户可以在应用界面选择播放音乐然后即使用户切换到其他应用或者锁屏音乐仍然可以继续播放。
// MusicService.java
public class MusicService extends Service {private MediaPlayer mediaPlayer;Overridepublic int onStartCommand(Intent intent, int flags, int startId) {mediaPlayer MediaPlayer.create(this, R.raw.music_file);mediaPlayer.start();return START_STICKY;}Overridepublic void onDestroy() {super.onDestroy();if (mediaPlayer ! null) {mediaPlayer.stop();mediaPlayer.release();}}NullableOverridepublic IBinder onBind(Intent intent) {return null;}
}// MainActivity.java
public class MainActivity extends AppCompatActivity {Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button playButton findViewById(R.id.play_button);playButton.setOnClickListener(new View.OnClickListener() {Overridepublic void onClick(View v) {Intent intent new Intent(MainActivity.this, MusicService.class);startService(intent);}});}
}
在这个案例中我们通过startService启动了MusicService服务即使用户离开了MainActivity音乐仍然可以继续播放。
1.2 bindService解读及应用
bindService用于绑定一个服务这样可以允许组件与服务进行交互比如请求服务执行某些操作或者获取服务提供的数据。这种服务适合需要与用户交互或者需要组件与服务进行通信的场景。
假设我们有一个应用需要从网络加载数据并且需要在多个Activity之间共享这些数据。
// DataLoadingService.java
public class DataLoadingService extends Service {private ListString data;private final IBinder binder new LocalBinder();public class LocalBinder extends Binder {DataLoadingService getService() {return DataLoadingService.this;}}public ListString getData() {return data;}Overridepublic IBinder onBind(Intent intent) {return binder;}Overridepublic boolean onUnbind(Intent intent) {// 可以在这里处理解绑逻辑return super.onUnbind(intent);}
}// MainActivity.java
public class MainActivity extends AppCompatActivity {private DataLoadingService dataLoadingService;private boolean isBound false;Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Intent intent new Intent(this, DataLoadingService.class);bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);}private ServiceConnection serviceConnection new ServiceConnection() {Overridepublic void onServiceConnected(ComponentName className, IBinder service) {DataLoadingService.LocalBinder binder (DataLoadingService.LocalBinder) service;dataLoadingService binder.getService();isBound true;// 可以在这里请求服务加载数据}Overridepublic void onServiceDisconnected(ComponentName arg0) {isBound false;}};Overrideprotected void onDestroy() {super.onDestroy();if (isBound) {unbindService(serviceConnection);isBound false;}}
}
在这个案例中我们通过bindService绑定了DataLoadingService服务这样MainActivity就可以与服务进行交互比如请求服务加载数据。最后总结下
startService适合执行不需要与用户交互的后台任务服务一旦启动即使启动它的组件不存在服务也会继续运行。bindService适合需要与用户交互或者需要组件与服务进行通信的场景服务的生命周期与绑定它的组件相关联。
接下来我们开始以activity场景中的startService和bindService为入口开始分析。
2 从activity场景到AMS调用的流程
2.1 从activity.startService到AMS.startService
activity.startService方法是从Context中的startService开始调用的接口代码实现如下
//Context
public abstract ComponentName startService(Intent service);
其真正的实现是在ContextImpl中代码实现如下
//ContextImpl//关键流程step1Overridepublic ComponentName startService(Intent service) {warnIfCallingFromSystemProcess();return startServiceCommon(service, mUser);}//关键流程step2private ComponentName startServiceCommon(Intent service, UserHandle user) {try {validateServiceIntent(service);service.prepareToLeaveProcess();//关键方法调用AMS的startService方法ComponentName cn ActivityManagerNative.getDefault().startService(mMainThread.getApplicationThread(), service,service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());//...return cn;} catch (RemoteException e) {return null;}}
这里直接调用到ActivityManagerNative.getDefault().startService实际上最终就是调用到AMS的startService方法中。这一部分参考binder系列文章即可有了或者基础分析起来就较为简单了。系列文章链接为专题分纲目录 android 系统核心机制 binder尤其是这2篇偏实操的
android 系统核心机制binder11binder java层 TestServer分析
android 系统核心机制binder12binder java层 TestClient 分析
2.2 从activity.bindService到AMS.bindService
activity.bindService方法是从Context中的bindService开始调用的接口代码实现如下
//Context public abstract boolean bindService(Intent service, NonNull ServiceConnection conn,BindServiceFlags int flags);
其真正的实现是在ContextImpl中代码实现如下
//ContextImpl//关键流程step1Overridepublic boolean bindService(Intent service, ServiceConnection conn,int flags) {warnIfCallingFromSystemProcess();return bindServiceCommon(service, conn, flags, Process.myUserHandle());}//关键流程step2private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,UserHandle user) {IServiceConnection sd;//...if (mPackageInfo ! null) {sd mPackageInfo.getServiceDispatcher(conn, getOuterContext(),mMainThread.getHandler(), flags);} else {throw new RuntimeException(Not supported in system context);}validateServiceIntent(service);try {IBinder token getActivityToken();if (token null (flagsBIND_AUTO_CREATE) 0 mPackageInfo ! null mPackageInfo.getApplicationInfo().targetSdkVersion android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {flags | BIND_WAIVE_PRIORITY;}service.prepareToLeaveProcess();//关键方法调用AMS的bindService方法int res ActivityManagerNative.getDefault().bindService(mMainThread.getApplicationThread(), getActivityToken(),service, service.resolveTypeIfNeeded(getContentResolver()),sd, flags, user.getIdentifier());if (res 0) {throw new SecurityException(Not allowed to bind to service service);}return res ! 0;} catch (RemoteException e) {return false;}
这里直接调用到ActivityManagerNative.getDefault().bindService实际上最终就是调用到AMS的bindService方法中。其中过程参考2.1节即可。
有了这些基础接下来的2个章节我们开始分析从AMS.startService和AMS.bindService到最终回调的流程。