Android 多进程通讯之 AIDL

来源:互联网 发布:java 线程池 编辑:程序博客网 时间:2024/06/01 07:19

下午闲来无事,学习了下Android应用层开发的多进程通讯方式之AIDL。

    AIDL是Android Interface Definition Language(安卓接口定义语言)。android应用的多进程通讯的一实现方式,当然,你也可以通过发送广播的方式等等。

   这里,只是来介绍AIDL的使用方式。


这个demo主要是来实现,主进程操作service,实现音乐的播放和停止。

1. 首先,新建一个aidl文件,IRemoteService.aidl.

   

package com.playerserver;// Declare any non-default types here with import statementsinterface IRemoteService {    /**     * Demonstrates some basic types that you can use as parameters     * and return values in AIDL.     */    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,            double aDouble, String aString);    //vnbo add    void play();    void stop();    //vnbo end}
 这个文件,主要是用来主进程和服务进程通讯接口。

aidl文件,在编译的时候,apt会产生相应的java文件。且里面的接口不能使用public关键字。

2.  创建服务进程代码逻辑。

  新建类:PlayerService(com.player.playerserver.PlayerService),继承Service。

  这里贴出其代码:

package com.player.playerserver;import android.app.Service;import android.content.Intent;import android.media.MediaPlayer;import android.os.IBinder;import android.os.RemoteException;import android.util.Log;import com.playerserver.IRemoteService;import com.player.R;import java.io.FileDescriptor;public class PlayerService extends Service {    private MediaPlayer mPlayer;    public PlayerService() {    }   //Service的接口    @Override    public IBinder onBind(Intent intent) {        Log.e("vnbo","vnbo PlayerService onBind");        if(mPlayer == null){            mPlayer = new MediaPlayer();            try{                FileDescriptor fd = getResources().openRawResourceFd(R.raw.test).getFileDescriptor();                // 获取音乐数据源,在raw文件夹下,放一个test.mp3的音乐文件。                mPlayer.setDataSource(fd); // 设置数据源            } catch (Exception e) {                e.printStackTrace();            }            mPlayer.setLooping(true);        }        return mBinder;    }   //使用之前创建的aidl接口。    private IBinder mBinder = new IRemoteService.Stub() {      //自定义逻辑接口       @Override        public void stop() throws RemoteException {            Log.e("vnbo","vnbo PlayerService stop");            try {                if (mPlayer.isPlaying()) {                    mPlayer.stop();                }            } catch (Exception e) {                e.printStackTrace();            }        }        //自定义逻辑接口         @Override        public void play() throws RemoteException {            try {                Log.e("vnbo","vnbo PlayerService play");                if (mPlayer.isPlaying()) {                    return;                }                mPlayer.prepare();                mPlayer.start();            } catch (Exception e) {                // TODO: handle exception                e.printStackTrace();            }        }        @Override        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,                        double aDouble, String aString){            Log.e("vnbo","vnbo PlayerService basicTypes");        }    };   //Service的接口    @Override    public boolean onUnbind(Intent intent) {        Log.e("vnbo","vnbo PlayerService onUnbind");        if (mPlayer != null) {            mPlayer.release();        }        return super.onUnbind(intent);    }}
3. 在AndroidManifest.xml文件对Service声明。
 

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.player" >    <application        android:allowBackup="true"        android:icon="@mipmap/ic_launcher"        android:label="@string/app_name"        android:supportsRtl="true"        android:theme="@style/AppTheme" >        <activity            android:name="com.player.MainActivity"            android:label="@string/app_name"            android:theme="@style/AppTheme.NoActionBar" >            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>        <service            android:name="com.player.playerserver.PlayerService"            android:process=":remote"            android:enabled="true"            android:exported="true" >            <intent-filter>                <action android:name="com.player.playerserver.PlayerService" />            </intent-filter>        </service>    </application></manifest>

4. 在我们的Activity中,进行与此Service进行通讯。

package com.player;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.content.ServiceConnection;import android.os.Bundle;import android.os.IBinder;import android.os.RemoteException;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.view.View;import android.view.Menu;import android.view.MenuItem;import android.widget.Button;import com.playerserver.IRemoteService;public class MainActivity extends AppCompatActivity {    public static final String ACTION = "com.player.playerserver.PlayerService";    private Button mPlayBtn, mStopBtn;    private IRemoteService mService;    private boolean isBinded = false;   //主进程与服务进程连接的回调接口    private ServiceConnection conn = new ServiceConnection() {        @Override        public void onServiceDisconnected(ComponentName name) {            Log.e("vnbo","vnbo MainAcitvity onServiceDisconnected");            isBinded = false;            mService = null;        }        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            Log.e("vnbo","vnbo MainAcitvity onServiceConnected");            mService = IRemoteService.Stub.asInterface(service);            isBinded = true;        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        doBind();        initViews();    }    private void initViews() {        mPlayBtn = (Button) findViewById(R.id.button_play);        mStopBtn = (Button) findViewById(R.id.button_stop);        mPlayBtn.setOnClickListener(clickListener);        mStopBtn.setOnClickListener(clickListener);    }     //与服务进程建立联系    public void doBind() {        Intent intent = new Intent(ACTION);        intent.setPackage(getPackageName());//android5.0之后,intent要显示声明。如果这个service在另一个应用中,则需要setComponent。        bindService(intent, conn, Context.BIND_AUTO_CREATE);    }    public void doUnbind() {        if (isBinded) {            unbindService(conn);            mService = null;            isBinded = false;        }    }    private View.OnClickListener clickListener = new View.OnClickListener() {        @Override        public void onClick(View v) {            if (v.getId() == mPlayBtn.getId()) {                // play                try {                    mService.play(); //调用播放逻辑接口                } catch (RemoteException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }            } else {                // stop                try {                    mService.stop();//调用暂停逻辑接口                } catch (RemoteException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }            }        }    };    @Override    public boolean onCreateOptionsMenu(Menu menu) {        // Inflate the menu; this adds items to the action bar if it is present.        getMenuInflater().inflate(R.menu.menu_main, menu);        return true;    }    @Override    public boolean onOptionsItemSelected(MenuItem item) {        // Handle action bar item clicks here. The action bar will        // automatically handle clicks on the Home/Up button, so long        // as you specify a parent activity in AndroidManifest.xml.        int id = item.getItemId();        //noinspection SimplifiableIfStatement        if (id == R.id.action_settings) {            return true;        }        return super.onOptionsItemSelected(item);    }}

这里贴一下,布局文件:

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent"    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    android:paddingBottom="@dimen/activity_vertical_margin"    app:layout_behavior="@string/appbar_scrolling_view_behavior"    tools:showIn="@layout/activity_main" tools:context=".MainActivity">    <Button        android:id="@+id/button_play"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="play" />    <Button        android:id="@+id/button_stop"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_below="@id/button_play"        android:layout_marginTop="20dp"        android:text="stop" /></RelativeLayout>


这样,我们可以通过这种方式,可以跟第三方的sdk或者apk通讯了。这样可以增加自己APP的稳定性








0 0