Android 进程与进程之间的通讯 详解及实现步骤 -- 两个app实现


分两个app -- 客户端为:jinc1application、服务端为:jinc2application

在这里插入图片描述

一、Intent

这是 Android 中最常用的通讯方式,主要用于启动 Activity、Service 等

  • 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","没有找到对应文件---------------");
        }
  • 注意:要启动的目标包名和包名+类名如下:
  • 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。

  • 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());
            }
        }

    }
  • 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代码,我们无需自己去写这段繁杂的代码,只需要在需要的时候调用即可,通过这种方式我们就可以完成进程间的通信工作。

2、使用步骤详情

  • 服务端步骤代码

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调用
    在这里插入图片描述
    服务端结束

  • 客户端步骤代码

  • 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中接受广播

  • 1、在 jinc1application 创建一个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);
    }
}
  • 3、在 jinc1application 在java代码中发送广播,发送的action与jinc2application中接受到的action要一致,代码如下:
 // 通过Intent类的构造方法指定广播的ID
        Intent intent = new Intent("com.example.jinc2application.MyBoradCast" );//测试接收到广播
        // 将要广播的数据添加到Intent对象中
        intent.putExtra("text", "测试发送广播");
        // 发送广播
        sendBroadcast(intent);

猜你喜欢

转载自blog.csdn.net/afufufufu/article/details/131643277