目录
一、基础回顾
- 定义特点
- 注意事项
- 应用场景举例
- 类型
二、生命周期
startService
bindService
三、使用方法
1、通过startService方式定义一个Service(继承Service类)
2、通过startService方式定义一个Service(继承IntentService类)
3、通过bindService方式定义一个Service:(使用Bind Service完成Service和Activity之间的通信)
4、bindService和startService混合使用
四、startService、bindService区别大总结
五、在AndroidManifest.xml里Service元素常见选项
六、扩展:进程间通信及小例子
一、基础回顾
- 定义、特点:
Service是可以在后台执行长时间(长生命周期)而又不与用户产生UI交互(没有用户界面)的操作。
- 注意事项:
1、只能在后台运行,即便用户切换了其他应用,启动的Service仍可在后台运行。
2、可以和其他组件进行Service绑定并与之交互,甚至是跨进程通信(IPC)。
3、不能运行在一个独立的进程当中,而是依赖与创建服务时所在的应用组件进程。
4、服务不会自动开启线程,我们需要在服务的内部手动创建子线程,并在这里执行具体的任务。
- 应用场景举例:
音乐播放:播放多媒体的时候用户启动了其他Activity,此时要在后台继续播放。
记录检测:比如检测SD卡上文件的变化;在后台记录你的地理信息位置的改变等。
其他操作:网络请求、执行文件读写操作或者与 content provider交互。
-
类型:
本地服务与远程服务本地服务依附在主进程上,在一定程度上节约了资源。本地服务因为是在同一进程,因此不需要IPC,也不需要AIDL。相应bindService会方便很多。缺点是主进程被kill后,服务变会终止。
远程服务是独立的进程,对应进程名格式为所在包名加上你指定的android:process字符串。由于是独立的进程,因此在Activity所在进程被kill的是偶,该服务依然在运行。缺点是该服务是独立的进程,会占用一定资源,并且使用AIDL进行IPC稍微麻烦一点。本文第六部分将会简单的讲述这一进程间通信方式。
对于startService来说,不管是本地服务还是远程服务,我们需要做的工作都一样简单。
二、生命周期
从Service的启动到销毁,有两种路径(两种生命周期):
startService、bindService
三、使用方法
1、通过startService方式定义一个Service(继承Service类):
- 核心步骤和代码:创建一个类继承android.app.Service类,实现抽象方法onBind(),重写onCreate()、onStartCommand()、onDestry()。
public class MyService extends Service {
public static final String TAG = "MyService";
//创建服务时调用
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate");
}
//服务执行的操作
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
//销毁服务时调用
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy");
}
//onBind()方法是Service中唯一的一个抽象方法,所以必须要在子类里实现。
//Service有两种启动方式:一种是startService(),另一种是bindService()。第二种启动方式才会用到onBind()方法。
//我们这先用第一种方式定义Service,所以暂时忽略onBind()方法。
@Override
public IBinder onBind(Intent intent) {
return null;
}
- 在清单文件中配置Service,和Activity标签并列。
请注意:为了保证应用的安全,请使用显式Intent启动或绑定一个Service,请不要在
- 在Activity组件中通过onCreate()声明“启动Service和停止Service”代码。
public class MainActivity extends Activity implements OnClickListener {
private Button button1_start_service;
private Button button2_stop_service;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button1_start_service = (Button)findViewById(R.id.button1_start_service);
button2_stop_service = (Button)findViewById(R.id.button2_stop_service);
button1_start_service.setOnClickListener(this);
button2_stop_service.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button1_start_service:
Intent startIntent = new Intent(this, MyService.class);
startService(startIntent);
break;
case R.id.button2_stop_service:
Intent stopIntent = new Intent(this, MyService.class);
stopService(stopIntent);
break;
default:
break;
}
}
}
-
启动和停止服务:
startService()和stopService()方法都是定义在Context类当中的,所以可以在MainActivity中直接调用这两个方法。
运行上面的程序,点击button1_start_service按钮,通过Intent实现启动服务,后台打印日志如下:
说明服务启动成功。
那么如果我再连续点三次button1_start_service按钮,后台增加的日志如下:
onCreate()方法只会在Service第一次被创建的时候调用,而onStartCommand()方法在每次启动服务的时候都会调用。我们还可以在正在“设置--应用---运行”中找到这个服务,如下图所示:
如果我们再点击button2_stop_service按钮或者点击上图中的“Stop”,MyService服务就停止掉了(多次点击stop不会再产生日志):
-
通过startService方式(继承Service类) 总结
1、启动服务对象多次启动同时只会产生一个,onCreate()方法只会在Service第一次被创建的时候调用,多次点击启动会执行多次onStartCommand()方法,onDestroy()方法只会在Service第一次被停止的时候调用,多次点击停止不会报异常,也不再执行onDestroy()方法。2、一旦启动,Service将一直运行在后台(run in the background indefinitely)即便启动Service的组件已被destroy。
3、停止一个started服务有两种方法:
(1)在外部使用stopService()手动停止。
(2)在服务内部(onStartCommand方法内部)使用stopSelf()方法,使服务执行完毕后自动停止。比如说,一个start的Service执行在后台下载或上传一个文件的操作,完成之后,Service应自己停止。
4、onStartCommand方法的返回值:
onStartCommand方法执行时,返回的是一个int型。这个整型可以有三个返回值:START_NOT_STICKY、START_STICKY、START_REDELIVER_INTENT
START_NOT_STICKY:“非粘性的”。使用这个返回值时,如果在执行完onStartCommand方法后,服务被异常kill掉,系统不会自动重启该服务。
START_STICKY:如果Service进程被kill掉,保留Service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试重新创建Service,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到Service,那么参数Intent将为null。
START_REDELIVER_INTENT:重传Intent。使用这个返回值时,系统会自动重启该服务,并将Intent的值传入。
** 5、默认情况下,一个started的Service与启动他的组件在同一个线程中。上面的实例中,服务就是在主线程中运行的,如果是在服务中完成耗时操作的话,容易造成主线程阻塞。所以我们可以在服务中开启一个子线程来完成耗时操作。**
2、通过startService方式定义一个Service(继承IntentService类):
- 为什么要通过继承IntentService来定义:
我们在基础回顾的注意事项3、4中就已经了解,服务中的代码默认运行在主线程中,如果直接在服务里执行一些安卓不允许的耗时操作,容易造成主线程ANR(Application Not Responding)异常,所以就需要用到多线程的知识了,需要在服务的内部手动创建子线程。所以一个比较标准的服务可以这样写:
public class MyService extends Service {
public static final String TAG = "MyService";
//服务执行的操作
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread(new Runnable() {
public void run() {
//在子线程中处理具体的逻辑
//在这里我们只做打印子线程id的操作
Log.i("MyService",Thread.currentThread().getId()+"");
stopSelf(); //服务执行完毕后自动停止
}
}).start();
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
在MainActivity中启动Service代码
public class MainActivity extends Activity implements OnClickListener {
private Button button1_start_service;
private Button button2_stop_service;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button1_start_service = (Button)findViewById(R.id.button1_start_service);
button2_stop_service = (Button)findViewById(R.id.button2_stop_service);
button1_start_service.setOnClickListener(this);
button2_stop_service.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button1_start_service:
Log.i("Main",Thread.currentThread().getId()+"");
Intent startIntent = new Intent(this, MyService.class);
startService(startIntent);
break;
case R.id.button2_stop_service:
Intent stopIntent = new Intent(this, MyService.class);
stopService(stopIntent);
break;
default:
break;
}
}
}
注册Service步骤不再赘述,当开启Service后打印日志如下:
如果我们不手动开启线程,I/MyService: 177将会变成它依赖的主线程1,这就不能做耗时操作了。虽说上面的这种写法并不复杂,但总会有一些程序猿忘记开启线程,或者忘记调用stopSelf()方法。
为了可以简单地创建一个可开启单独线程、会自动停止的服务,Android专门提供了一个IntentService类,这个类就很好的解决了上面所提到的两种尴尬。
- IntentService的作用:
当我们需要这样一次性完成的任务时,就可以使用IntentService来完成。 - IntentService的用法:
1)新建一个MyIntentService类,继承自IntentService,并重写父类的onHandleIntent()方法,代码如下:
public class MyIntentService extends IntentService{
public MyIntentService() {
//第一步:重写父类的onHandleIntent()方法,这里首先要提供一个无参的构造方法,
//并且必须在其内部调用父类的有参构造方法,这里我们手动给服务起个名字为:MyIntentService
super("MyIntentService");
}
//第二步:重写父类的onHandleIntent()方法,该方法在会在一个单独的线程中执行,
//来完成工作任务。任务结束后,该Service自动停止
@Override
protected void onHandleIntent(Intent intent) {
for(int i = 0;i<3;i++) {
//Service要执行的逻辑
//这里我们只打印当前线程的id
Log.d("MyIntentService","IntentService线程的id是:"+Thread.currentThread().getId());
try {
//线程睡眠一秒钟
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d("MyIntentService","onDestroy");
}
}
2)在清单文件中对服务进行注册服务:
3)在MainActivity里面加入启动IntentService的逻辑,核心代码如下:
case R.id.button3_stop_intentservice:
Log.d("MainActivity","主线程的id是:"+Thread.currentThread().getId());
Intent intentService = new Intent(this,MyIntentService.class);
startService(intentService);
运行程序,日志显示如下:
-
通过startService方式(继承IntentService类) 总结
1、启动一个IntentService和启动一个普通的Service,步骤是相似的。
2、与直接继承Service不同在于:通过继承IntentService运行,自动开启了单独线程,而且完成任务后自动销毁了Service。【补充】Service和Thread的关系:
不少Android初学者都可能会有这样的疑惑,Service和Thread到底有什么关系呢?什么时候应该用Service,什么时候又应该用Thread?答案可能会有点让你吃惊,因为Service和Thread之间没有任何关系!
之所以有不少人会把它们联系起来,主要就是因为Service的后台概念。Android的后台就是指,它的运行是完全不依赖UI的。即使Activity被销毁,或者程序被关闭,只要进程还在,Service就可以继续运行。Thread我们大家都知道,是用于开启一个子线程,在这里去执行一些耗时操作就不会阻塞主线程的运行。而Service我们最初理解的时候,总会觉得它是用来处理一些后台任务的,一些比较耗时的操作也可以放在这里运行,这就会让人产生混淆了。但是,Service其实是运行在主线程里的,一些比较耗时的操作需要开启单独线程。
3、通过bindService方式定义一个Service:(使用Bind Service完成Service和Activity之间的通信):
Bind Service的引入:
有没有什么办法能让Service与组件的关联更多一些呢?比如说在Activity中指挥Service去干什么,Service就去干什么。当然可以,只需要让Activity和Service建立关联就好了。这时我们就可以通过bindService方式定义一个Service。Bind Service的实现原理:
应用程序组件(客户端)通过调用bindService()方法能够绑定服务,然后Android系统会调用服务的onBind()回调方法,则个方法会返回一个跟服务器端交互的Binder对象。
bindService()方法立即返回,并且不给客户端返回IBinder对象。要接收IBinder对象,客户端必须创建一个ServiceConnection类的实例,并且把这个实例传递给bindService()方法。ServiceConnection对象包含了一个系统调用的传递IBinder对象的回调方法。
- Bind Service实现流程:
1)一直有一个onBind()方法我们都没有使用到,这个方法其实就是用于和Activity建立关联的,修改MyService中的代码,如下所示:
public class MyBindService01 extends Service {
public static final String TAG = "MyBindService01";
private MyBinder mBinder = new MyBinder();
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate");
}
@Override
public IBinder onBind(Intent intent) {
return mBinder; //在这里返回新建的MyBinder类
}
@Override
public boolean onUnbind(Intent intent) {
Log.d(TAG, "onUnbind");
return super.onUnbind(intent);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy");
}
//MyBinder类,继承Binder:让里面的方法执行下载任务,并获取下载进度
class MyBinder extends Binder {
public void startDownload() {
Log.d("TAG", "startDownload() executed");
// 执行具体的下载任务
}
public int getProgress(){
Log.d("TAG", "getProgress() executed");
return 0;
}
}
}
- 新建一个MyBinder类,继承Binder:让里面的方法执行下载任务,并获取下载进度。当然,这里只是两个模拟方法,并没有实现真正的功能,我们通过打印日志的形式来体现。
- 接着创建MyBinder的实例,然后在onBind()方法里返回这个实例。返回这个mBinder,是一个IBinder类型,就可以把这个IBinder类型传递到MainActivity中,从而调用Service里面的方法。
2)检查清单文件,是否已经对Service进行注册:
3)让我们修改MainActivity和MyBindService01之间建立关联
public class MainActivity extends Activity implements OnClickListener {
private Button button1_bind_service;
private Button button2_unbind_service;
private MyBindService01.MyBinder myBinder;
boolean mBound = false; //一开始,并没有和Service绑定.这个参数是用来显示绑定状态
//匿名内部类:服务连接对象
private ServiceConnection connection = new ServiceConnection() {
//当服务异常终止时会调用。注意,解除绑定服务时不会调用
@Override
public void onServiceDisconnected(ComponentName name) {
mBound = false; //服务异常终止时,状态为未绑定
//解决了多次执行unbindService()方法引发的异常问题
}
//和服务绑定成功后,服务会回调该方法
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
myBinder = (MyBindService01.MyBinder) service;
//在Activity中调用Service里面的方法
myBinder.startDownload();
myBinder.getProgress();
mBound = true; //true说明是绑定状态
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button1_bind_service = (Button) findViewById(R.id.button1_bind_service);
button2_unbind_service = (Button) findViewById(R.id.button2_unbind_service);
button1_bind_service.setOnClickListener(this);
button2_unbind_service.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button1_bind_service:
Intent bindIntent = new Intent(this, MyService.class);
bindService(bindIntent, connection, BIND_AUTO_CREATE);
//这里传入BIND_AUTO_CREATE表示在Activity和Service建立关联后会自动创建Service(即使之前没有创建
//Service也没有关系),这会使得MyService中的onCreate()方法得到执行,但onStartCommand()方法不会执行。
break;
case R.id.button2_unbind_service:
//如果和Service是绑定的状态,就解除绑定。
if(mBound){
unbindService(connection);
mBound=false;
}
break;
default:
break;
}
}
}
说明:这里我们首先创建了一个ServiceConnection的匿名类,在里面重写了onServiceConnected()方法和onServiceDisconnected()方法,如果当前Activity与服务连接成功后,服务会回调onServiceConnected()方法
在onServiceConnected()方法中,我们又通过向下转型得到了MyBinder的实例,有了这个实例,Activity和Service之间的关系就变得非常紧密了。现在我们可以在Activity中根据具体的场景来调用MyBinder中的任何public方法,即实现了Activity指挥Service干什么Service就去干什么的功能。
4)执行bindService()方法。
5)解除Activity和Service之间的关联。执行unbindService()。
-
通过bindService方式 总结
1、onCreate()、onBind()方法只会在Service第一次被创建的时候调用,多次点击绑定启动不会执行任何方法,onUnbind()、onDestroy()方法会在调用者执行unbindService()方法时执行或者Activity退出时自动执行。2、如果我们既通过startService()开启Service,又用通过bindService开启,必要unbindService()和stopService()都执行一次(没有先后顺序),Service才会被销毁。
3、如果多次执行unbinsService()方法,程序会异常退出,我们需要在代码中加一个判断是否绑定的标记mBound来解决此问题,上面代码中有说明。
case R.id.button4_unbind_service:
//如果和Service是绑定的状态,就解除绑定。
if(mBound){
unbindService(connection);
mBound=false;
}
break;
**4、当在旋转手机屏幕的时候,当手机屏幕在“横”“竖”变换时,此时如果你的 Activity 如果会自动旋转的话,旋转其实是 Activity 的重新创建,因此旋转之前的使用 bindService 建立的连接便会断开(Context 不存在了)。**
**5、只有Activity、Service、Content Provider能够绑定服务;BroadcastReceiver广播接收器不能绑定服务。**
4、bindService和startService混合使用:
** 如果先startService,再bindService:
在bind的Activity退出的时候,Service会执行unBind方法而不执行其onDestory方法,因为有startService方法调用过,
所以Activity与Service解除绑定后会有一个与调用者没有关连的Service存在。**如果先bindService,再startService,再调用Context.stopService
Service的onDestory方法不会立刻执行,因为有一个与Service绑定的Activity,但是在Activity退出的时候,会执行其(Service的)onDestory方法,如果要立刻执行stopService,就得先解除绑定。如果先是bind了,那么start的时候就直接运行Service的onStartCommand()方法,如果先是start,那么bind的时候就直接运行onBind()方法。
当一个服务没被onDestory()销毁之前,只有第一个启动它的客户端能调用它的onBind()和onUnbind()。
四、startService、bindService区别大总结
1、生命周期不同。(详见二)
2、多次启动,前者会多次执行onStartCommand()方法,后者什么都不执行。多次停止,前者只会执行一次onDestroy()方法,后者报异常信息。
3、当启动Service的组件已被Destroy的时候,前者不停止,后者会停止。
4、前者停止直接执行onDestroy()方法(Service中的),后者则先解除绑onUnbind()定再执行onDestroy()方法(Service中的)。
5、当手机屏幕在“横”“竖”变换时,前者创建的Service不会停止,后者会随着Activity的重建而停止。
6、后者的onBind回调方法将返回给客户端一个IBinder接口实例,IBinder允许客户端回调服务的方法,比如得到Service运行的状态或其他操作。而这些操作前者启动的Service是没有的。
五、在AndroidManifest.xml里Service元素常见选项
android:name -- 服务类名
android:label -- 服务的名字,如果此项不设置,那么默认显示的服务名则为类名
android:icon -- 服务的图标
android:permission -- 申明此服务的权限,这意味着只有提供了该权限的应用才能控制或连接此服务
android:process -- 表示该服务是否运行在另外一个进程,如果设置了此项,那么将会在包名后面加上这段字符串表示另一进程的名字
android:enabled --表示是否能被系统实例化,为true表示可以,为false表示不可以,默认为true
android:exported -- 表示该服务是否能够被其他应用程序所控制或连接,不设置默认此项为 false
六、扩展:进程间通信。
调用者和Service如果不在一个进程内, 就需要使用android中的远程Service调用机制.
android使用AIDL定义进程间的通信接口. AIDL的语法与java接口类似, 需要注意以下几点:
- AIDL文件必须以.aidl作为后缀名.
- AIDL接口中用到的数据类型, 除了基本类型, String, List, Map, CharSequence之外, 其他类型都需要导包, 即使两种在同一个包内. List和Map中的元素类型必须是AIDL支持的类型.
- 接口名需要和文件名相同.
- 方法的参数或返回值是自定义类型时, 该自定义的类型必须实现了Parcelable接口.
- 所有非java基本类型参数都需要加上in, out, inout标记, 以表明参数是输入参数, 输出参数, 还是输入输出参数.
- 接口和方法前不能使用访问修饰符和static, final等修饰.
【远程通信扩展小例子】
- 远程service
要在service中注册信息中加上 android:process=”:remote”
**远程service有什么用呢? **
远程service的作用只是重新建立一个新进程执行,可以独立出去。其他app可以调用这个service。因为是一个新的进程,所以也不能用bindService来建立关联了。可以用新的方式来建立关系就是下面要讲的aidl技术。-
AIDL实现
1.首先我建立2个app工程,通过aidl实现一个app调用另一个app的service
目录结构如下:
service提供端app
利用aidl调用service的app
2.在两个app中都建立一个文件 IPerson.aidl注意 包名 要相同
IPerson.aidl只是一个接口文件,用来aidl交互的,建立好之后在Studio中点Build-->Rebuild会自动创建需要的java文件。
IPerson.aidl代码
package mangues.com.aidl;
interface IPerson {
String greet(String someone);
}
3.在aidl_service 中建立AIDLService
这个IPerson.Stub 就是通过IPerson.aidl 自动生成的binder 文件,你实现下,然后在onBind()中 return出去就好了,就和Android Service实现和activity交互一样。
代码:
public class AIDLService extends Service {
private static final String TAG = "AIDLService";
IPerson.Stub stub = new IPerson.Stub() {
@Override
public String greet(String someone) throws RemoteException {
Log.i(TAG, "greet() called");
return "hello, " + someone;
}
};
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate() called");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onBind() onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind() called");
return stub;
}
@Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, "onUnbind() called");
return true;
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "onDestroy() called");
}
}
4.aidl_service MainActivity 中启动这个service
简单点就不写关闭什么的了;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent startIntent = new Intent(this, AIDLService.class);
startService(startIntent);
}
在AndroidManifest.xml注册
作用就是把这个service暴露出去,让别的APP可以利用
android.intent.action.AIDLService 字段隐形绑定这个service,获取数据。
5.aidl_client 中绑定aidl_service service 获取数据
代码:
public class MainActivity extends AppCompatActivity {
private IPerson person;
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i("ServiceConnection", "onServiceConnected() called");
person = IPerson.Stub.asInterface(service);
String retVal = null;
try {
retVal = person.greet("scott");
} catch (RemoteException e) {
e.printStackTrace();
}
Toast.makeText(MainActivity.this, retVal, Toast.LENGTH_SHORT).show();
}
@Override
public void onServiceDisconnected(ComponentName name) {
//This is called when the connection with the service has been unexpectedly disconnected,
//that is, its process crashed. Because it is running in our same process, we should never see this happen.
Log.i("ServiceConnection", "onServiceDisconnected() called");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent mIntent = new Intent();
mIntent.setAction("android.intent.action.AIDLService");
Intent eintent = new Intent(getExplicitIntent(this,mIntent));
bindService(eintent, conn, Context.BIND_AUTO_CREATE);
}
public static Intent getExplicitIntent(Context context, Intent implicitIntent) {
// Retrieve all services that can match the given intent
PackageManager pm = context.getPackageManager();
List resolveInfo = pm.queryIntentServices(implicitIntent, 0);
// Make sure only one match was found
if (resolveInfo == null || resolveInfo.size() != 1) {
return null;
}
// Get component info and create ComponentName
ResolveInfo serviceInfo = resolveInfo.get(0);
String packageName = serviceInfo.serviceInfo.packageName;
String className = serviceInfo.serviceInfo.name;
ComponentName component = new ComponentName(packageName, className);
// Create a new intent. Use the old one for extras and such reuse
Intent explicitIntent = new Intent(implicitIntent);
// Set the component to be explicit
explicitIntent.setComponent(component);
return explicitIntent;
}
}
和Android Service 中学习的调用MyBinder获取service中数据一样,这边只是吧MyBinder 改成了aidl定义的接口IPerson 本质上还是一个Binder。
因为android 5.0 不允许隐形启用service 所有用getExplicitIntent转一下
整理作者:汪博
少壮不努力,老大徒悲伤。
本文为Android学习规划打造,如有不好的地方请多多指教。