Android进程通信分为:
AIDL(Android Interface definition language)服务
广播(Broadcast)
Content Provider 内容提供者(通过数据库通信)
Intent访问其他应用程序的Activity
一.AIDL服务实现进程通信
简述:翻译过来是接口定义语言,顾名思义是通过定义接口的方式实现两个应用的通信,两个应用,一个我就叫它Service端,另一个叫它Client端.
Service端 需要做的:
1.创建接口
2.创建service 在service中实现接口方法,将接口返回的ibinder对象暴露给客户端使用
3.清单文件中注册并配置serviceClient端需要做的:
1.创建和Service端相同的aidl文件,文件夹,报名也都要相同,copy过去即可。
2.bindService
3.通过bindService获得到的接口对象调用方法,最终获得结果
下面就来一步一步实现
服务端:
1.项目下创建aidl文件夹,接着创建一个interface , 后缀名为.aidl,在该接口中定义方法(直接new AIDL即可,Android studio 会帮我们自动生成),如下图所示:
2.创建Service ,在Service中实现接口方法,写好对应的业务逻辑(为了简洁记录,这里直接返回a+b了)
注:在我们定义好aidl文件的时候,Android studio会自动帮我们生成对应同名的.java文件,如果不生成(调用方法的时候找不到),就去检查下.aidl文件是否写错,然后clean project即可重新生成。
在onBind方法中,直接将binder对象返回,暴露给客户端使用。如下图所示:
3.别忘了在清单文件中注册service 并配置:
注:
android:exported=”true”是否支持其他应用调用当前组件
android:process=”:remote” 如果我们需要让一个服务在一个远端进程中运行(而不是标准的它所在的apk的进程中运行)注意:这里选择”remote”这个名字是随意主观的,你能用其他名字来让这个服务在另外的进程中运行。冒号’:’这个前缀将把这个名字附加到你的包所运行的标准进程名字的后面作为新的进程名称。
<service
android:name=".service.IRemoteService"
android:exported="true"
android:process=":helloaidl">
<intent-filter>
<action android:name="android.intent.action.AIDLService" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
4.在MainActivity中startService
客户端:
1.首先要建一个跟服务端一模一样的aidl文件夹 ,包名,文件名都相同,接口里的方法也一模一样。复制即可,必要时clean project
2.创建ServiceConnection
private ServiceConnection serviceConnection = new ServiceConnection() {
/**
* 服务绑定成功后调用
* @param componentName
* @param iBinder 服务端返回的binder对象
*/
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
//获取服务端接口
iMyAidlInterface = IMyAidlInterface.Stub.asInterface(iBinder);
}
/**
* 解绑后调用
* @param componentName
*/
@Override
public void onServiceDisconnected(ComponentName componentName) {
iMyAidlInterface = null;
}
};
3.bindService
Intent intent = new Intent("android.intent.action.AIDLService");
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
4.调用方法
iMyAidlInterface.add(num1,num2)
5.记得解绑
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(serviceConnection);
}
二. 广播(Broadcast)
广播是一种被动跨进程通讯的方式。当某个程序向系统发送广播时,其他的应用程序只能被动地接收广播数据。这就象电台进行广播一样,听众只能被动地收听,而不能主动与电台进行沟通。在应用程序中发送广播比较简单。只需要调用sendBroadcast方法即可。该方法需要一个Intent对象。通过Intent对象可以发送需要广播的数据。
1.在应用A中发送广播,不需要注册,通过Intent指定广播的action
@Override
public void onClick(View v) {
String text = et.getText().toString();
Intent intent = new Intent("com.example.broadcast.test");
intent.putExtra("text",text);
sendBroadcast(intent);
}
2.在应用B中,创建广播 ,并在清单文件中注册广播
判断action 值 “com.example.broadcast.test”
public class CallReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (!TextUtils.isEmpty(action) && action.equals("com.example.broadcast.test")){
Bundle bundle = intent.getExtras();
if (bundle != null){
String text = bundle.getString("text");
Toast.makeText(context,"success:"+text,Toast.LENGTH_SHORT).show();
}
}
}
}
注册广播指定action
<receiver android:name=".CallReceiver">
<intent-filter>
<action android:name="com.example.broadcast.test" />
</intent-filter>
</receiver>
在应用A中点击按钮,会发送全局广播,应用B的CallReceiver 类中onReceive方法接收到 ,弹出消息提示。
三.Content Provider
Android应用程序可以使用文件或SqlLite数据库来存储数据。Content Provider提供了一种在多个应用程序之间数据共享的方式(跨进程共享数据)。应用程序可以利用Content Provider完成下面的工作
1. 查询数据
2. 修改数据
3. 添加数据
4. 删除数据
虽然Content Provider也可以在同一个应用程序中被访问,但这么做并没有什么意义。Content Provider存在的目的向其他应用程序共享数据和允许其他应用程序对数据进行增、删、改操作。
Android系统本身提供了很多Content Provider,例如,音频、视频、联系人信息等等。我们可以通过这些Content Provider获得相关信息的列表。这些列表数据将以Cursor对象返回。因此,从Content Provider返回的数据是二维表的形式。
四.Intent
1.利用compnent方式访问其他apk的(主activity),无需设置androidmanifest.xml
public void method1() {
// 这些代码是启动另外的一个应用程序的主Activity
ComponentName componetName = new ComponentName(
// 这个是另外一个应用程序的包名 ,androidmanifest.xml中的package值!!!
"com.amaker.test",
// 这个参数是要启动的Activity (主activity)
"com.amaker.test.MainActivity");
try {
Intent intent = new Intent();
intent.setComponent(componetName);
startActivity(intent);
} catch (Exception e) {
Toast.makeText(getApplicationContext(),"没有找到应用程序!!!", 0).show();
}
}
2.利用compnent方式访问其他apk的(非主activity)
/*
* 2.利用compnent方式访问其他apk的(非主activity),需要设置AndroidManifest.xml中非主activity的exported属性,具体如下:
* 被访问的activity是"com.amaker.ch03.drawable.TestBitmapActivity" 则需要设置的是:<activity android:name="com.amaker.ch03.drawable.TestBitmapActivity" android:exported="true"/>
*/
public void method2() {
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.amaker.test","com.amaker.ch03.drawable.TestBitmapActivity"));
//"com.amaker.ch03.string.TestStringActivity"));
//intent.setAction("android.intent.action.VIEW");
startActivity(intent);
}
3.设置androidmanifest.xml访问其他apk的(非主activity)
3.设置androidmanifest.xml访问其他apk的(非主activity)
注意:使用这种方式的时候需要在被调用的apk的androidmanifest.xml里做如下设置(访问非主activity)
<activity
<intent-filter>
<action android:name="android.intent.action.xml" />
<data android:scheme="info" />
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
public void method3() {
Intent intent = new Intent("android.intent.action.xml",
Uri.parse("info://调用其他应用程序的Activity"));
startActivity(intent);
}