由于Android系统中应用程序之间不能共享内存。在不同应用程序之间交互数据(跨进程通讯),Android SDK提供了4种跨进程通讯的方式。这4种方式正好对应Android系统中4种应用程序组件:Activity
、ContentProvider
、Broadcast
和 Service
。
**
Activity
可以跨进程调用其它应用程序的Activity
;ContentProvider
可以跨进程访问其他应用程序中的数据(以Cursor
对象形式返回),也可以对其他应用程序的数据进行增、删、改操作;Broadcast
可以向Android系统中所有应用程序发送广播,而需要跨进程通讯应用程序可以监听这些广播;Service
和ContentProvider
类似,也可以访问其他应用程序中的数据,但不同的是,ContentProvider
返回的是Cursor
对象,而Service
返回的是Java
对象,这种可以跨进程的服务叫AIDL
服务;**
一、Activity
Activity
的跨进程访问与进程内访问有所不同;虽然他们都需要Intent 对象,但跨进程访问并不需要指定Context
对象和Activity
的Class 对象,而需要指定要访问Activity
所对应的Action
(一个字符串)。有些Activity
还需要指定一个Uri
(通过Intent构造方法的第2个参数指定)。
在Android 系统中很多应用程序提供了可以跨进程访问的Activity
,例如,直接调用拨打电话的Activity。
//进程内访
Intent intent = new Intent(this , Test.class );
startActivity(intent);
//跨进程访问
Intent callIntent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:13512345678");
startActivity(callIntent);
如何将应用程序的Activity共享出去
- 在
AndroidManifest.xml
文件中指定action
; - 在
AndroidManifest.xml
文件中指定访问协议;指定Uri
是需要访问协议,访问协议需要使用<data android:scheme="info" />
来指定。如果属性的值是info
,那么Uri
就应该是“info://Uri的主体部分”
,也就是说:访问 协议是Uri
的开头部分。 - 通过
getIntent().getData().getHost()
获取到协议后的Uri主体部分; - 从
bundle
对象中获得其他应用程序传过来的数据; - 这一步是获得数据后根据需求做处理;
首先创建一个A工程,打开AndroidManifest.xml
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<!--指定action,自定义动作-->
<action android:name="net.csdn.MYACTION" />
<!--指定Uri-->
<data android:scheme="info" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
public class MainActivity extends AppCompatActivity {
private EditText edittext;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
edittext = (EditText) findViewById(R.id.edittext);
Button button =(Button) findViewById(R.id.button);
//获取其他应用程序传递过来的数据
if (getIntent().getData() != null) {
//获取Host,(info://后面的内容)
String host = getIntent().getData().getHost();
Bundle bundle = getIntent().getExtras();
//其他的应用程序会传递过来一个value值
String value = bundle.getString("value");
edittext.setText(host + ":" + value);
}
}
}
创建B工程
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("net.csdn.MYACTION", Uri.parse("info://调用其他应用程序的Activity"));
intent.putExtra("value","调用成功");
startActivity(intent);
}
});
这样B程序就可以调用A程序的Activity了
B程序也可以使用startActivityForResult
来启动A程序,这样可以得到A程序的返回值。
修改B程序
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("net.csdn.MYACTION", Uri.parse("info://调用其他应用程序的Activity"));
intent.putExtra("value","调用成功");
startActivityForResult(intent,1);
}
});
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
Toast.makeText(this, "返回值:" + data.getExtras().getString("result"),
Toast.LENGTH_LONG).show();
}
修改A程序
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
//设置返回的属性值
intent.putExtra("result",edittext.getText().toString());
//设置返回码和Intent对象
setResult(2,intent);
//关闭Actiivty
finish();
}
});
点击A程序的按钮后,B程序回Toast显示A的返回值。
跨进程访问Activity
(访问其他应用程序的Activity)主要是通过一个action
来完成的,还需要指定一个Uri
。传递数据也可以通过Intent
来完成。传递数据的过程是可以双向的。如果想从调用的Activity
中返回数据,就需要使用startActivityForResult
方法启动Activity
。
二、ContentProvider
Android 应用程序可以使用文件或SqlLite 数据库来存储数据。ContentProvider
提供了一种在多个应用程序之间数据共享的方式(跨进程共享数据)。应用程序利用ContentProvider
完成下面的工作
- 查询数据
- 修改数据
- 添加数据
- 删除数据
虽然ContentProvider
也可以在同一个应用程序中被访问,但这么做没有意义;ContentProvider
存在的作用是向其他应用程序共享数据和允许其他应用程序对数据进行增、删、改操作。
Android 系统本身提供了很多ContentProvider
,例如:音频、视频、通讯录等;可以通过这些ContentProvider
获取相关的信息列表。这些列表数据将以Cursor
对象返回;所以,从ContentProvider
返回的数据是二维表的形式。
关于ContentProvider
的更多内容,请查看我的另一篇文章:Android四大组件之ContentProvider
三、Broadcast
广播是一种被动跨进程通讯的方式。当某个程序向系统发送广播时,其他的应用程序只能被动地接收广播数据。这种象电台进行广播一样,听众只能被动的收听,而不能主动与电台进行沟通。
在应用程序中发送广播比较简单,只需要调用sendBrodcast
方法即可;改方法需要一个Intent
对象,通过ntent
对象可以发送需要广播的数据。
关于Broadcast
的更多内容,请查看我的另一篇文章:Android四大组件之BroadcastReceiver
四、Service
Service
和Broadcast
相比而言,虽然实现上稍微麻烦了一点,但它的优势不会像广播那样在手机中的广播较多时会有明显的延时,甚至有广播发送不成功的情况出现。
但是普通的Service
并不能实现跨进程操作,因为普通的Service
和它所在的应用处于同一个进程中,而且它不会专门开一条新的线程,所以如果在普通的Service中
实现耗时操作,需要新开线程。
要实现跨进程通信,需要借助AIDL
(Android Interface Definition Language)。Android 中的跨进程服务其实采用C/S 的架构,因而AIDL目的是实现通信接口。
客户端每调用一次Content.startService(Intent)
,Service
就会重新执行一次onStartCommand-->onStart
;
但是使用AIDL
的话,绑定服务之后,不会重复执行onStart,显然后者的代价更小。
Service:前台Service,像我们经常用的天气、音乐其实利用了前台 Service 来实现。
关于Service
和AIDL
的更多内容,请查看我的另一篇文章:Android四大组件之Service