Android实现进程间通信

1.Intent

当service在xml中注册时使用到属性android:process时,是不属于当前应用内进程的,此时如果activity启动该service属于进程间通信。

2.AIDL

  1. 创建 .aidl 文件
  2. 实现 .aidl 文件中定义的接口
  3. 向客户端曝露接口
生成对应的.java文件,在下图目录下可以找到

还是使用service,Binder改成.aidl生成.java文件中的Stub类。该类继承了android.os.Binder类

public class AiDlBinder extends IMyAidlInterface.Stub {
    private MyService myService;

    public AiDlBinder(MyService myService) {
        this.myService = myService;
    }

    @Override
    public void toUpCaseString(String text) throws RemoteException {
        myService.toUpCaseString(text);
    }

    @Override
    public void printString(String text) throws RemoteException {
        myService.printString(text);
    }
}
对应的Service

public class MyService extends Service {
    private AiDlBinder myBinder = new AiDlBinder(this);
    

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i("ytt", "MyService onCreate");
        /*try {
            Thread.sleep(60000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }*/
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.i("ytt", "MyService onUnbind");
        return super.onUnbind(intent);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("ytt", "MyService onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        Log.i("ytt", "MyService onDestroy");
        super.onDestroy();
    }

    @Override
    public void onRebind(Intent intent) {
        Log.i("ytt", "MyService onRebind");
        super.onRebind(intent);
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.i("ytt", "MyService onBind");
        return myBinder;
        // TODO: Return the communication channel to the service.
        //  throw new UnsupportedOperationException("Not yet implemented");
    }

    public void testFun(String text) {
        Log.i("yttt", "testFun:" + text);
    }

    public void toUpCaseString(String text) {
        Log.i("ytt", "MyService toUpCaseString"+text);
    }

    public void printString(String text) {
        Log.i("ytt", "MyService printString"+text);

    }
}
说到Service有两种启动方式

1.startService--stopService

::使用这种start方式启动的Service的生命周期如下:
onCreate()--->onStartCommand()(onStart()方法已过时) ---> onDestory()

说明:如果服务已经开启,不会重复的执行onCreate(), 而是会调用onStart()和onStartCommand()。
服务停止的时候调用 onDestory()。服务只会被停止一次。

特点:一旦服务开启跟调用者(开启者)就没有任何关系了。
开启者退出了,开启者挂了,服务还在后台长期的运行。
开启者不能调用服务里面的方法。


2.bindService--unbindServie

采用bind的方式开启服务

使用Service的步骤:

    1.定义一个类继承Service
    2.在Manifest.xml文件中配置该Service
    3.使用Context的bindService(Intent, ServiceConnection, int)方法启动该Service
    4.不再使用时,调用unbindService(ServiceConnection)方法停止该服务

使用这种start方式启动的Service的生命周期如下:
onCreate() --->onBind()--->onunbind()--->onDestory()

注意:绑定服务不会调用onstart()或者onstartcommand()方法

特点:bind的方式开启服务,绑定服务,调用者挂了,服务也会跟着挂掉。
绑定者可以调用服务里面的方法。


所以activity与service通信我们使用bindService

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
  /*  private IMyAidlInterface aidlInterface;

    private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            aidlInterface = IMyAidlInterface.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };*/

    private Intent intent;

    private IMyAidlInterface  myBinder;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        intent = new Intent(this, MyService.class);
        findViewById(R.id.start).setOnClickListener(this);
        findViewById(R.id.stop).setOnClickListener(this);
        findViewById(R.id.bind).setOnClickListener(this);
        findViewById(R.id.unbind).setOnClickListener(this);
        findViewById(R.id.toUpCaseString).setOnClickListener(this);
        findViewById(R.id.printString).setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.start:
                startService(intent);
                break;
            case R.id.stop:
                stopService(intent);
                break;
            case R.id.bind:
                bindService(intent, serviceConnection, BIND_AUTO_CREATE);
                break;
            case R.id.unbind:
                unbindService(serviceConnection);
                break;
            case R.id.toUpCaseString:
                try {
                    myBinder.toUpCaseString("啦啦啦,我是toUpCaseString");
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                break;
            case R.id.printString:
                try {
                    myBinder.toUpCaseString("啦啦啦,我是printString");
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                break;
        }
    }


    private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            myBinder =IMyAidlInterface.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };
}
这样实现了一个应用中两个进程间的通信并不是我们需要的,我们想要两个应用之间通信的话应该怎么做呢?

重新新建一个应用,把前一个应用中的.aidl文件拷贝过去,包名必须一样,那新应用中没有MyService,我们就不能使用显示调用,会报找不到该类,所以需要使用隐式调用,现在前一个的demo中给Myservice添加一个action


在客户端隐式调用

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private IMyAidlInterface aidlInterface;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.bind).setOnClickListener(this);
        findViewById(R.id.toUpCaseString).setOnClickListener(this);
        findViewById(R.id.printString).setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.bind:
                Intent intent = new Intent();
                intent.setAction("com.gradle.plugin.mydemo.MyAIDLService");
                //服务端demo的包名,不是客户端的,android5.0之后必须指定包名
                intent.setPackage("com.gradle.plugin.mydemo");
                bindService(intent, serviceConnection, BIND_AUTO_CREATE);
                break;
            case R.id.toUpCaseString:
                try {
                    aidlInterface.toUpCaseString("我是新的哎,MyUserDemo给你的 ");
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                break;
            case R.id.printString:
                try {
                    aidlInterface.printString("我是新的哎,MyUserDemo给你的 ");
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                break;
        }

    }

    private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            aidlInterface = IMyAidlInterface.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };
}
好啦好啦,可以通信啦,可以传递自定义的对象,必须要实现序列化

3.Messenger

展开阅读全文

没有更多推荐了,返回首页