您的位置:首页 > 移动开发 > Android开发

Android 多进程通讯之 AIDL

2016-07-19 18:38 543 查看
下午闲来无事,学习了下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 statements

interface 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的稳定性
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: