分两个app -- 客户端为:jinc1application、服务端为:jinc2application
一、Intent
这是 Android 中最常用的通讯方式,主要用于启动 Activity、Service 等
jinc1application 中的代码
- 1、 jinc1application代码如下:
//通过budle传递数据,可以携带序列化数据
Bundle bundle = new Bundle();
bundle.putInt("intextra", 1);
bundle.putString("stringextra", "测试数据");
Intent intent = new Intent();
//制定要打开的程序的包名(必须写全包名,不然会报错)和地址(activity名)
intent.setComponent(new ComponentName("com.example.jinc2application",
"com.example.jinc2application.MainActivity"));//要启动的目标包名和包名+类名
intent.putExtras(bundle);
try{
startActivity(intent);
}catch(Exception e){
Log.e("TAG","没有找到对应文件---------------");
}
-
注意:要启动的目标包名和包名+类名如下:
jinc2application 中的代码
- 2、jinc2application
public class MainActivity extends AppCompatActivity {
@SuppressLint("MissingInflatedId")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 获取意图对象
Intent intent = getIntent();
//获取传递的值
String stringextra= intent.getStringExtra("stringextra");
int intextra= intent.getIntExtra("intextra",0);
//打印获取的数据
Log.e("TAG","stringextra---------------"+stringextra);
Log.e("TAG","intextra---------------"+intextra);
}
}
二、Messenger
这是基于 Binder 的一种轻量级的 IPC 机制,主要用于跨进程发送 Message。
jinc1application 中的代码
- 1、jinc1application 的代码如下:给一个点击事件
<Button
android:onClick="btn7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Messenger"/>
- MainActivity 的代码实现
private Messenger mService;
@SuppressLint("HandlerLeak")
private Handler mReplyHandler = new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
switch (msg.what) {
case 22:
Log.e("TAG","-------"+msg.getData().get("msg").toString());
break;
}
}
};
private Messenger mClientMessenger= new Messenger(mReplyHandler);
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
mService = new Messenger(iBinder);
//创建消息,通过Bundle传递数据
Message message = Message.obtain(null, 1111);
Bundle bundle = new Bundle();
bundle.putString("msg", "你好我是客户端的数据");
message.setData(bundle);
//如果需要服务器返回消息,则需要将客户端的Messenger对象传递给服务端,如果不需要返回消息,则不用加这一句
message.replyTo = mClientMessenger;
try {
//向服务端发送消息
mService.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
};
public void btn7(View view) {
Intent intent = new Intent();
intent.setAction("com.example.jinc2application.MyService");
intent.addCategory(Intent.CATEGORY_DEFAULT);
PackageManager pm = getPackageManager();
ResolveInfo info = pm.resolveService(intent, 0);
if(info != null){
//如果ResolveInfo不为空,说明我们能通过上面隐式的Intent找到对应的Service
//我们可以获取将要启动的Service的package信息以及类型
String packageName = info.serviceInfo.packageName;
String serviceNmae = info.serviceInfo.name;
ComponentName componentName = new ComponentName(packageName, serviceNmae);
intent.setComponent(componentName);
try{
bindService(intent,mConnection,BIND_AUTO_CREATE);
}catch(Exception e){
e.printStackTrace();
Log.e("DemoLog", e.getMessage());
}
}
}
jinc2application 中的代码
- 2、jinc2application代码如下: 创建 MyService
public class MyService extends Service {
/**
* 处理来自客户端的消息,并用于构建Messenger
*/
private static class MessengerHandler extends Handler {
@Override
public void handleMessage(Message message) {
switch (message.what) {
//客户端建立连接
case 1111://MESSAGE_FROM_CLIENT
Log.e("TAG", "-------" + message.getData().getString("msg"));
//向客户端回传消息
Message msg = Message.obtain(null, 22);//MESSAGE_FROM_SERVICE
Bundle b = new Bundle();
b.putString("msg","你好我是服务端的数据");
msg.setData(b);
try {
//如果服务端需要回复客户端,则需要拿到客户端携带过来的Messenger 对象(即msg.replyTo),通过msg.replyTo.send方法给客户端发送信息
message.replyTo.send(msg);
} catch(RemoteException e){
e.printStackTrace();
}
break;
default:
super.handleMessage(message);
break;
}
}
}
/**
* 构建Messenger对象
*/
private final Messenger mMessenger = new Messenger(new MessengerHandler());
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();
}
}
- 3、在清单文件中注册
<service android:name=".MyService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.example.jinc2application.MyService"></action>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
三、AIDL
点击参考传递对象(类)的例子
这是 Android 提供的一种 IPC 机制,主要用于实现跨进程的接口调用。
AIDL 是Android的进程间通信(IPC)比较常用的一种方式,AIDL 是 Android Interface Definition Language 的缩写,即Android接口定义语言。
1、AIDL优点:
-
1.进程间通信不止有AIDL,我们还有其他选择,例如 BroadcastReceiver , Messenger 等,但是 BroadcastReceiver 存在占用的系统资源比较多和存在延迟问题,在频繁的跨进程通信时是无法满足需求的;Messenger 进行跨进程通信时请求队列是同步进行的,无法并发执行,不能进行多进程通信,局限性比加大,这个时候就需要使用 AIDL 了。
-
2.编译器通过*.aidl文件的描述信息生成符合通信协议的Java代码,我们无需自己去写这段繁杂的代码,只需要在需要的时候调用即可,通过这种方式我们就可以完成进程间的通信工作。
下面是传 String值为例
2、使用步骤详情
jinc2application 中的代码
AIDL的底层是基于Binder实现的,而Binder机制也是一种请求-响应式的通信模型,请求方一般称为Client,响应方称为Server。
- 1、src\main 目录 右键new一个AIDL文件。
- 2、输入自定义AIDL名字,点击OK,即可创建出AIDL接口文件,文件中会默认生出一个basicTypes方法,该方法描述了AIDL中可以使用的基本类型(int, long, boolean, float, double, String)。下面是以String为例:
- 3、定义后需要
Rebuild Project
- 4、创建一个实现类,继承刚才创建的AIDL的名称里的Stub类,并实现接口方法。
public class MyAIDLService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return myBinder;
}
private IBinder myBinder=new IMyAidlInterface.Stub() {
@Override
public String getMessages() throws RemoteException {
return "返回测试数据-------------";
}
};
}
- 5、在清单文件里配置service,android:exported=“true”,必须配置成true,才能被其他app调用
jinc1application 中的代码
- 6、将服务端AIDL文件拷贝到客户端相同包的位置,然后Rebuild Project 重新编译
注意
:客户端和服务端AIDL的文件和路径要一致。
- 7、activity_main.xml 写一个点击事件
<Button
android:onClick="btn8"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="AIDL"/>
- 8、MainActivity 里面的处理
//AIDL
private static IMyAidlInterface sIAidlServiceInterface;
public void btn8(View view) {
Intent intent = new Intent();
intent.setAction("com.example.jinc2application.MyAIDLService");
intent.setPackage("com.example.jinc2application");//包名
bindService(intent, serviceConnection, Service.BIND_AUTO_CREATE);
}
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
sIAidlServiceInterface = IMyAidlInterface.Stub.asInterface(service);
try {
String message = sIAidlServiceInterface.getMessages();
Log.e("TAG", "the message:" + message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.e("TAG", "name:" + name);
}
};
四、广播
这是 Android 中的一种广播机制,可以用于实现跨进程的事件通知。
两个app间发送广播和正常发送广播其实差不多
在jinc1application中发广播,在jinc2application中接受广播
jinc2application 中的代码
- 1、在 jinc2application 创建一个java类继承BroadcastReceiver类,用来在 onReceive()方法中处理获得的广播。
public class MyBoradCast extends BroadcastReceiver {
public static final String BROADCAST_ACTION_TEST = "com.example.jinc2application.MyBoradCast";
@Override
public void onReceive(Context context, Intent intent) {
if (BROADCAST_ACTION_TEST .equals(intent.getAction())){
Bundle bundle = intent.getExtras();
String test = (String) bundle.get("text");
Log.e("测试接收到广播:",test );
}
}
}
- 2、在java代码中动态注册,代码如下:
public class MainActivity extends AppCompatActivity {
private MyBoradCast myReceiver;
@SuppressLint("MissingInflatedId")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("com.cn.broadcast.test.ACTION");
myReceiver = new MyBoradCast();
registerReceiver(myReceiver, intentFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(myReceiver);
}
}
jinc1application 中的代码
- 3、在 jinc1application 在java代码中发送广播,发送的action与jinc2application中接受到的action要一致,代码如下:
// 通过Intent类的构造方法指定广播的ID
Intent intent = new Intent("com.example.jinc2application.MyBoradCast" );//测试接收到广播
// 将要广播的数据添加到Intent对象中
intent.putExtra("text", "测试发送广播");
// 发送广播
sendBroadcast(intent);
五、文件
-
jinc1application 中的代码
文章来源:https://www.toymoban.com/news/detail-549352.html -
页面给个点击事件触发:点击去查询是否有存储权限,如果已授权,直接存数据,否则去获取权限页面,手动赋予文章来源地址https://www.toymoban.com/news/detail-549352.html
<Button
android:onClick="btn11"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="文件"/>
public void btn11(View view) {
// 在你的 Activity 中,查询是否有权限
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
// Permission is not granted
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
111);
}else {//已经授权,写入文件数据
try {
File file = new File(Environment.getExternalStorageDirectory(), "ceshi.txt");
FileWriter writer = new FileWriter(file);
writer.append("我是测试数据");
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@SuppressLint("MissingSuperCall")
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case 111: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted 已授予许可
try {
File file = new File(Environment.getExternalStorageDirectory(), "ceshi.txt");
FileWriter writer = new FileWriter(file);
writer.append("我是测试数据");
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
} else { // permission denied 权限被拒绝
}
return;
}
}
}
-
jinc2application 中的代码
public class MainActivity extends AppCompatActivity {
@SuppressLint("MissingInflatedId")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 在你的 Activity 中
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
// Permission is not granted
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
111);
}else {
//获取文件内容
try {
File file = new File(Environment.getExternalStorageDirectory(), "ceshi.txt");
BufferedReader reader = new BufferedReader(new FileReader(file));
String line = reader.readLine();
while (line != null) {
Log.e("App2", line);
line = reader.readLine();
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@SuppressLint("MissingSuperCall")
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case 111: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted 已授予许可
try {
File file = new File(Environment.getExternalStorageDirectory(), "ceshi.txt");
BufferedReader reader = new BufferedReader(new FileReader(file));
String line = reader.readLine();
while (line != null) {
Log.e("App2", line);
line = reader.readLine();
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
} else {
// permission denied 权限被拒绝
}
return;
}
}
}
}
到了这里,关于Android 进程与进程之间的通讯 详解及实现步骤 -- 两个app实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!