项目GitHub地址
Service基础回顾
- **主要要用到的就是启动Service和绑定Service两种方式,
大概的流程这里就不赘述了,
可以参考一下这篇博文:学习笔记| AS入门(十) 组件篇之Service**
这里主要强调几点:
- **
startService
和bindService
都可以启动服务,
- **
但是其影响Service的生命周期不同,
而且bindService
可以是Activity能同Service交互通信,监控
Service任务的情况;**
- **`startService`和`bindService`两种方式都调用之后,
必须同时使用stopService
和unbindService
,
才能销毁服务;**
- **换句话说,
startService
被调用之后,如果没有调用stopService
,
则无论调用多少次bindService
和unbindService
,
都无法销毁服务;**
IPC实战
跨进程启动服务
**现在我们看一下这两个实战项目,
一个[AIDLTest项目](),
还有一个[AIDLDemo项目](),AIDLTest项目
可以
单独用于测试同一个进程内的Service基础运作,
当然这里咱们要表演一个IPC(进程间通信)过程,
即,
从AIDLDemo项目
中,
访问到AIDLTest项目
的MyService
;
【即跨APP、跨进程通信访问】
下面是AIDLTest项目
的AndroidManifest
,
我们给MyService一个action标签
,
以及记下来AIDLTest项目
的包名,待会儿需要用到!AIDLTest项目
的MyService代码:**
public class MyService extends Service {
....
@Override
public void onCreate() {
super.onCreate();
Log.e("MyService","服务创建了");
...
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("MyService","服务启动了");
return super.onStartCommand(intent, flags, startId);
}
...
@Override
public IBinder onBind(Intent intent) {
Log.e("MyService","服务绑定了");
return mb;
}
...
@Override
public boolean onUnbind(Intent intent) {
Log.e("MyService","服务解绑了");
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.e("MyService","服务销毁了");
}
}
**AIDLDemo项目
中,
指定访问我们刚刚提到的AIDLTest项目
的包名
以及MyService的action标签
:**
- **成了,先运行
AIDLTest项目
【提供Service方】,
再运行AIDLDemo项目
【访问方】,
在AIDLDemo项目
中点击按钮,观察logcat,
可以看到我们在AIDLDemo项目
中操作的时候,
成功跨进程开启了
另外一个进程APP【AIDLTest】的Service了!!!**
跨进程绑定服务
AIDL实战开始!!
- **以上的方式只能做到跨进程开启、绑定服务,
但是无法进行通信,监控另一个进程的进度;
所以这里就要使用AIDL了!**
- **AIDL是作为
两个进程间 数据共享的接口!**
一般性步骤
- **创建aidl文件,
【aidl文件用于定义进程间的接口,
进程两端的文件要保持一致】;**
- **创建好了AIDL文件之后,
build一下会自动生成java文件;**
- 使用AIDL;
- **1/3
创建aidl文件,
服务提供方先创建,即 AIDLTest项目
,
在对应的包处 new 一下就好了:
在弹出的窗口处点击Finish后,成功创建,
项目会自动生成一个包:
【刚刚是右键aidltest包创建的AIDL文件,
所以这里生成的包跟aidltest包的完整包名是一致的】
初始生成的AIDL文件 —— IMyAidlInterface.aidl:**
// IMyAidlInterface.aidl
package com.lwp.aidltest;
// Declare any non-default types here with import statements
interface IMyAidlInterface {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
}
- 添加自定义的业务方法【需要提供给其他进程使用的业务】:
...
interface IMyAidlInterface {
...
//定义自己所需要的方法:显示当前服务的进度
void showProgress();
}
- **2/3
build
一下项目:
可以看到项目build/generated/
下生成了aidl相关的包
(generated包表示该包下放着的都是自动生成的代码),
展开之后可以看到自动生成的java文件
:**
**注意这里生成的是java文件
,
我们刚刚自定义的文件是aidl文件
,并不能直接使用
!
稍微浏览一下生成的java文件,
可以看到它首先定义了一个静态抽象类Stub
!!!!!!!!!Stub类 继承
了Binder类
,表明通信作用
(Binder类
是实现IBinder接口
的;public class Binder implements IBinder
;
所以Stub类
也间接实现了IBinder接口
)!!!!!!!
同时它实现了
我们刚刚自定义的aidl文件(接口)
!!!!!!!!!:
我们自定义的aidl文件中的接口方法,
在生成的这个接口中,都会有两个方法对应,
第一个是重写(override)的,第二个是重新生成的声明:
**
**3/3
使用AIDL!!!
调用的核心,就是使用刚刚我们提到静态内部抽象类stub
!!!!
(即,我们最终使用的接口类,!!!!!
是AS自动生成的aidl文件接口
对应的java接口类
!!!!!!!!!)
在AIDLTest项目
中的MyService
的onBind
方法中,
返回刚刚build生成aidl文件接口
对应的java接口类实例
,
以匿名内部类
的形式实现业务方法
!!!!!!!
(非跨进程情况,这里返回的是自定义Service类 内部
的自定义的Binder类
)
下面是使用aidl接口后,
!!!!!!!!!!!!!提供服务
的本线程内
的调用服务方法
的写法!!!!!!!!!!!!!
!!!!!!!!!!!!!:接着运行项目,
点击启动服务,接着点击绑定服务,测试成功:**
接着是另外一个进程
对提供服务进程
的服务
的跨进程调用
的写法
- **上面说了,
IPC两边的进程准备的AIDL文件都需要保持一致
,
所以接下来,
在 AIDLDemo项目
中创建
一个aidl包
,aidl包
再创建
一个包用于存放AIDL文件
,
这个用于存放AIDL文件
的包的包名需要跟
服务提供方【AIDLTest项目
】存放aidl文件的包名保持一致
!!!!!!
接着把 AIDLTest项目
中的AIDL文件
,
直接复制粘贴、覆盖到AIDLDemo项目
中的aidl包下对应的包下:
**
- **Rebuild一下
AIDLDemo项目
,自动生成Java代码,
因为使用的AIDL文件跟AIDLTest项目
的一样,
所以生成的文件也都是一样:**
- 接着使用AIDL接口:
- **运行两个项目,然后在
AIDLDemo项目
的APP上操作,
可以看到AIDLTest项目
是有对应的响应的,
即,实现跨进程调用服务方法:**
- **注意,
这里使用AIDL是可以方便生成IPC所需的接口代码,
但是其实读懂自动生成的Java接口文件,
懂得其中的IPC编程规范,要自己编写而不用AIDL文件也是可以的;AIDL文件
只是方便
我们自动生成代码
的工具
,真正使用
的以及实现跨进程逻辑
的,
是AS根据AIDL文件
去自动生成
的Java接口文件
!!!!**
参考:慕课网