天天看点

Android 跨进程通信AIDL

本文仅用于记录开发过程中遇到的问题及对应的解决方案,如有侵权可立即删除,同时欢迎大家批评与指正!!!
AIDL(Android Interface Definition Language,Android接口定义语言):用于某个远程的Service可以与多个进程进行通信,实现多个进程共享同一个Service的功能。

在多进程进行通信时,存在两种进程角色,服务器端和客户端。

服务器端:

Android 跨进程通信AIDL
  1. 新建AIDL文件夹,定义一个IMyAidlInterfaceaidl,在文件中声明该Service向客户端提供哪些接口;创建完要记得rebuild project
package com.example.test;
    import com.example.test.ICallBack;

	interface IMyAidlInterface {

     void registerCallBack(ICallBack callback);
     void unregisterCallBack(ICallBack callback);
	}
           
  1. 在定义一个ICallBack.aidl,在该文件中声明用于回调的方法;
interface ICallBack {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
     void Play();
     void Pause();
     void Next();
     ...
     }
           
  1. 在Service中实现AIDL中定义的所有接口方法;
package com.example.test;

	public class AidlService extends Service {
    	private final String TAG = "AidlService";

	    @Override
	    public IBinder onBind(Intent intent) {
	        return mBinder;
	    }

	    private IBinder mBinder = new IMyAidlInterface.Stub() {
	        @Override
	        public void registerCallBack(ICallBack callback) throws RemoteException {
	            Log.d(TAG, "registerCallBack: ");
	            callback.play();
	        }

	        @Override
	        public void unregisterCallBack(ICallBack callback) throws RemoteException {
	            Log.d(TAG, "unregisterCallBack: ");
	            callback.pause();
	        }
	    };
	}
           

客户端:

Android 跨进程通信AIDL
  1. 将服务器端的AIDL文件拷贝到客户端的相同目录下;
  2. 通过bindService()绑定远程Service
private void bind() {
        Intent intent = new Intent();
        intent.setComponent(new ComponentName("com.example.test", "com.example.test.AidlService"));
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }
           
  1. 通过Service端的onBind()返回IMyAidlInterface.Stub对象实例,就可以用myAidlInterface 调用接口里的方法;
private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d(TAG, "onServiceConnected :success");
            myAidlInterface = IMyAidlInterface.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d(TAG, "onServiceConnected :failed");
            myAidlInterface = null;
        }
    };

  IMyAidlInterface myAidlInterface;
  ServiceCallBack mICallBack = new ServiceCallBack();
  
  myAidlInterface.registerCallBack(mICallBack);
  myAidlInterface.unregisterCallBack(mICallBack);
           

registerCallBack()、unregisterCallBack()用来注册/解注册回调的对象;

  1. 定义ServiceCallBack ,用于接收注册和接注册回调方法;
//获取AudioManager服务
	mAudioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
    mediaPlayer = new MediaPlayer();
    mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);

    //重写ICallBack中方法
    //本文为播放音乐的例子
	private class ServiceCallBack extends ICallBack.Stub {

        @Override
        public void play() throws RemoteException {
            Log.d(TAG, "回调play");
            //请求声音焦点
            mAudioManager.requestAudioFocus(new AudioManager.OnAudioFocusChangeListener() {
                                                @Override
                                                public void onAudioFocusChange(int focusChange) {
                                                }
                                            },
                    AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
            //播放音乐
            playMusic();
        }

        @Override
        public void pause() throws RemoteException {
            Log.d(TAG, "回调pause");
            mediaPlayer.pause();
        }

        @Override
        public void next() throws RemoteException {
            Log.d(TAG, "回调next");
        }
    }

    
    private void playMusic() {
        Log.d(TAG, "playMusic");
        File file = new File("/mnt/media_rw/udisk2/testMusic/test.mp3");
        mediaPlayer.reset();
        try {
            FileInputStream fileInputStream = new FileInputStream(file);
            mediaPlayer.setDataSource(fileInputStream.getFD());
            mediaPlayer.prepare();
        } catch (IOException e) {
            e.printStackTrace();
        }
        mediaPlayer.start();
    }
           

通过FileInputStream 读U盘资源时要记得在AndroidManifest中声明权限

<uses-permission android:name="android.permission.WRITE_SETTINGS" />

  1. 最后解除绑定服务

    @Override

    protected void onDestroy() {

    super.onDestroy();

    unbindService(mConnection);

    }

继续阅读