IPC进程间通信方式

提到进程间通信首先想到就是aidl方式,本文除了介绍该方式外还会介绍通过Messenger实现,看到Messenger很容易想到Message(Messenger核心是通过Message和Handler进程通信),下面分别介绍这两种方式

一、Messenger方式

1、服务端创建Handler,来处理客户端发来的消息

2、通过Handler实例创建Messenger实例

3、在onBind(Intent intent)方法中返回messenger获得的IBinder实例

4、客户端绑定服务回调onServiceConnected方法通过IBinder获得服务端的Messenger实例

5、客户端通过messenger发送消息到服务端

(1)服务端主要代码:

public class MyService extends Service {

    private Messenger messenger;
    private Handler mHandler = new Handler() {
        @Override public void handleMessage(Message msg) {
            super.handleMessage(msg);
            Log.i("aa", "**收到消息");
            Toast.makeText(MyService.this, "收到消息!", Toast.LENGTH_SHORT).show();
        }
    };


    public MyService() {

    }

    @Override
    public IBinder onBind(Intent intent) {
        messenger = new Messenger(mHandler);
        return messenger.getBinder();
    }

}

(2)客户端主要代码:

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    private Messenger messenger;
    private ServiceConnection connection = new ServiceConnection() {
        @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            messenger = new Messenger(iBinder);
        }


        @Override public void onServiceDisconnected(ComponentName componentName) {
            messenger = null;
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button bt1 = (Button)findViewById(R.id.act_bt1);
        Button bt2 = (Button)findViewById(R.id.act_bt2);
        bt1.setOnClickListener(this);
        bt2.setOnClickListener(this);
    }


    @Override public void onClick(View view) {
        switch (view.getId()){
            case R.id.act_bt1:
                Intent intent = new Intent();
                intent.setAction("com.huizhong.service");
                intent.setPackage("com.huizhong.onedemo");//不设置包名会报异常
                bindService(intent, connection, Context.BIND_AUTO_CREATE);
                break;
            case R.id.act_bt2:
                if (messenger == null){
                    Toast.makeText(MainActivity.this, "请先绑定服务", Toast.LENGTH_SHORT).show();
                }else {
                    try {
                        Message message = new Message();
                        messenger.send(message);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
                break;
        }
    }
}

注意事项:

a.首先要开启服务端的服务再用客户端绑定。

b.客户端绑定服务要setPackage(String pack)设置服务端服务的包名

二、AIDL方式(双进程保活案例)

1、新建GuardAidl.aidl文件(注意目录结构为aidl/包名/*.aidl),然后clean工程

2、创建本地服务WindowService和新进程服务KeepLiveService

注:android:process值以:开头表示私有进程,以字母开头表示全局进程

3、修改WindowService服务

(1)定义内部类MyBinder继承GuardAidl.Stub,并在onBinder方法中返回该实例

(2)创建ServiceConnection实例,重写onServiceDisconnected方法,在其中开启并绑定保活服务

(3)重写onStartCommand方法,在其中开启并绑定保活服务

4、修改KeepLiveService服务

(1)定义内部类MyBinder继承GuardAidl.Stub,并在onBinder方法中返回该实例

(2)创建ServiceConnection实例,重写onServiceDisconnected方法,在其中开启并绑定本地服务

(3)重写onStartCommand方法,在其中绑定本地服务

三、aidl(不同APP通信案例)

1、服务端

(1)定义.aidl文件(目录main/aidl/包名【可自定义,但服务端与客户端必须一样】/.aidl)

package com.lpf.myapplication;

interface IMyAidlInterface {

    int test(int a, int b);
}

(2)rebuild项目,定义类继承IMyAidlInterface.Stub

public class MyAidlBinder extends IMyAidlInterface.Stub {
    @Override
    public int test(int a, int b) {
        try {
            Thread.sleep(20000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return a + b;
    }
}

(3)定义service服务

class MyService : Service() {
    var aa = ""//这是intent传参

    override fun onBind(intent: Intent): IBinder? {
        aa = intent.getStringExtra("aa")
        Log.e("aa", "********onBind:" + intent.getStringExtra("aa"))
        return MyAidlBinder()
    }
}
<service
     android:name=".MyService"
     android:enabled="true"
     android:exported="true" >
     <intent-filter>
         <action android:name="com.lpf.myapplication.MyService" />

         <category android:name="android.intent.category.DEFAULT" />
     </intent-filter>
</service>

2、客户端

(1)拷贝服务端aidl目录(aidl/包名/.aidl)

(2)rebuild项目

(3)绑定服务

    private IMyAidlInterface mMyAidlImpl;

    private ServiceConnection mConnect = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //此处service是代理对象,需要以下方法获取aidl接口对象
            mMyAidlImpl = IMyAidlInterface.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mMyAidlImpl = null;
        }
    };
    
    //绑定远程服务
    private void bindAidlService(){
        Intent intent = new Intent("com.hualala.xiaoding.myapplication.MyService");
        intent.setPackage("com.hualala.xiaoding.myapplication");
        intent.putExtra("aa", "这是传参");
        getActivity().bindService(intent, mConnect, Context.BIND_AUTO_CREATE);
    }

    //和服务端通讯
    private void sendMessage(){
        if (mMyAidlImpl != null){
            new Thread(() -> {
                try {
                    int result = mMyAidlImpl.test(1, 8);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }).start();
        }else {
            Log.e("aa", "********先绑定服务")
        }
    }

注:

【1】由于服务端test(int a, int b)方法运行线程依赖于客户端调用该方法的线程,案例模拟耗时操作,而sendMessage()在主线程调用需要开启子线程。

【2】客户端可以执行多次绑定操作(只会创建一个,且不影响生命周期),客户端退出,服务端service自动销毁

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值