之前写过一篇关于绑定前台Service实现APP安装包下载的文章
http://blog.csdn.net/androidmsky/article/details/53407925
今天自己也是温习了一下,确实普通应用开发Service用的比较少,不过他又是四大组件中仅次于Activity的家伙,所以决定再探Service。
设想场景,我们可以在一个独立进程的Service中进行复杂的计算,或者多媒体音乐的播放等。开启一个独立进程的优势主要就是系统会给我开启独立的内存空间从而突破一个程序(准确说是一个进程)的最大内存限制。当然对于多进程又有很多弊端,最大的弊端想必就是原来很方便的事变得复杂,原本同一进程的绑定方法的Binder将不可用。那么我们就可以通过AIDL来辅助进行绑定,从而实现Activity跨进程操作Service也就是本文的目标。
开发
1.先把Service放到另一个进程中:
<service android:name=".MyService1"
android:process=":message"
>
</service>
好如果我们用普通的绑定方法,来绑定这个Service是可以成功绑定并启动的,但是
@Override
public void onServiceConnected(ComponentName arg0, IBinder service)
中的Service并不能强制转换成Service中的binder程序会报错,所以我们必须借助AIDL
2.创建一个AIDL文件并写随意两个方法
// IMyAidlService.aidl
package com.air.service;
// Declare any non-default types here with import statements
interface IMyAidlService {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void play(int i);
int add(int i);
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
}
写完之后rebulid一下项目,Android Studio 会帮我们自动生成相关的Java文件。
3.在Service中引用并实现相关方法。
private MyBinder mBinder = new MyBinder();
class MyBinder extends IMyAidlService.Stub {
@Override
public void play(int i) throws RemoteException {
}
@Override
public int add(int i) throws RemoteException {
return ++i;
}
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
}
}
4.在Activity中绑定:
class MyServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName arg0, IBinder service) {
Log.d("MyService123", "Service Connection Success");
mMyBinder = IMyAidlService.Stub.asInterface(service);
try {
Log.d("MyService123", "" + mMyBinder.add(10));
} catch (RemoteException e) {
e.printStackTrace();
}
//同一进程的获取方法
//mMyBinder = (MyService1.MyBinder) service;
}
5.提供停止,解绑,开启,绑定四个方法
public void stop(View v) {
Intent stopIntent = new Intent(this, MyService1.class);
stopService(stopIntent);
}
//解绑
public void stop2(View v) {
unbindService(myServiceConnection);
}
public void start(View v) {
Intent startIntent = new Intent(this, MyService1.class);
startService(startIntent
}
public void bind(View v) {
Intent intent = new Intent(this, MyService1.class);
bindService(intent, myServiceConnection, Context.BIND_AUTO_CREATE);
}
6.我们自定一个Application来看它的创建情况
public class A extends Application {
@Override
public void onCreate() {
super.onCreate();
Log.d("MyService123","create");
}
}
测试
好我们点击绑定按钮:
主进程输出日志:
06-27 15:26:33.367 26110-26110/com.air.service D/MyService123: create
06-27 15:26:35.458 26110-26110/com.air.service D/MyService123: Service Connection Success
06-27 15:26:35.460 26110-26110/com.air.service D/MyService123: 11
message进程输出日志:
06-27 15:35:53.947 32013-32013/com.air.service:message D/MyService123: create
06-27 15:35:53.949 32013-32013/com.air.service:message D/MyService123: onCreate() executed
可见我们成功使用了Service的add方法,得出数值11,Application也被两个进程分别创建了一次。
我们点击解除绑定按钮:
06-27 15:37:25.885 32013-32013/com.air.service:message D/MyService123: onDestroy() executed
Service成功被销毁。
如果我们先startService再绑定,再解绑会怎样?
我们会发现Service没有被销毁,如果再点击stop来停止Service,
06-27 15:39:39.156 32013-32013/com.air.service:message D/MyService123: onDestroy() executed
Service被成功销毁。
如果我们先startService再绑定,再停止Service会怎样?
其实是一样的Service没有被销毁,如果再点击stopService成功销毁。
总结
1.如果Service跨进程我们可以轻松的调起Service
2.如果Service跨进程我们可以绑定但不能通过原来的方法获取Binder实例
3.通过AIDL可以解决获取Binder实例的问题
4.如果Service即被绑定,又被开启,解绑和停止必须都执行才能正确的杀死Service。
5.Service放在独立进程中Application会被重复创建
本文代码链接:
https://github.com/AndroidMsky/AIDLBindService
哪里可以找到我:
我的Github: https://github.com/AndroidMsky
我的博客主页: http://blog.csdn.net/androidmsky
欢迎加作者自营安卓开发交流群: 308372687