本文主要写在同一个module中如何使用不同进程的服务。
- 在测试机的/mnt/sdcard/路径下放一首mp3格式的音乐文件,故音乐文件的路径为/mnt/sdcard/music.mp3。
- 新建项目,使用默认module,在moudle下新建AIDL文件夹,创建一个AIDL文件IPlayServiceAIDL.aidl,并在文件中添加play()与stop()方法,aidl文件中不可使用private,protected,public等关键词,但返回值要标明,创建好之后点击build->make project来编译工程。
package com.mazaiting.aidldemo2;
interface IPlayServiceAIDL {
void play();
void stop();
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
}
- 在项目的java目录下创建PlayService.java类,并继承Service。在PlayService中的onBind方法中返回一个IBinder对象,这个对象可new IPlayServiceAIDL.Stub()来得到,并实现其中的方法,如果哪个方法你不需要,则可以不实现它。
public class PlayService extends Service {
private MediaPlayer mediaPlayer;
public PlayService() {
}
@Override public IBinder onBind(Intent intent) {
try{
mediaPlayer = new MediaPlayer();
String path = Environment.getExternalStorageDirectory()+"/music.mp3";
File file = new File(path);
FileInputStream fis = new FileInputStream(file);
mediaPlayer.setDataSource(fis.getFD());
mediaPlayer.setLooping(true);
}catch (Exception e){
e.printStackTrace();
}
return mBinder;
}
private IBinder mBinder = new IPlayServiceAIDL.Stub(){
@Override public void play() throws RemoteException {
if (mediaPlayer.isPlaying()){
return;
}
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override public void onPrepared(MediaPlayer mp) {
mediaPlayer.start();
}
});
}
@Override public void stop() throws RemoteException {
if (mediaPlayer.isPlaying()){
mediaPlayer.stop();
}
}
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble,
String aString) throws RemoteException { }
};
}
- 接下来在AndroidManifest.xml文件中对PlayService进行配置,首先先配置一个访问内存卡的权限,其次在service节点内配置android:process=":remote",此语句表示运行在remote进程中,最后在service节点下配置intent-filter,并在intent-filter中配置action,action的name属性就配置为PlayService的包名+类型。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".PlayService"
android:enabled="true"
android:exported="true"
android:process=":remote">
<intent-filter>
<action android:name="com.mazaiting.aidldemo2.PlayService" />
</intent-filter>
</service>
</application>
- 简单的编写MainActivity.java的布局文件,两个水平排列的按钮,一个用于播放音乐,一个用于暂停播放。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
>
<Button
android:id="@+id/btn_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="start"
/>
<Button
android:id="@+id/btn_stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="stop"
/>
</LinearLayout>
- 接下来实现MainActivity.java中的代码,按钮的初始化及设置点击事件不再赘述,在onResume方法中调用bindService对服务进行绑定, 此方法有三个参数,第一个参数为Intent,并为其设置Action,第二个参数为ServiceConnection对象,方法中用于获得AIDL远程调用的对象,第三个方法参数为一个int值,一般设置它为 Context.BIND_AUTO_CREATE。在onPause方法中调用unbindService对绑定的服务进行解绑。点击按钮时分别调用start,stop方法来控制音乐的播放与暂停。
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final String ACTION = "com.mazaiting.aidldemo2.PlayService";
private Button btnStart,btnStop;
private IPlayServiceAIDL mBinder;
private ServiceConnection mConncet = new ServiceConnection() {
@Override public void onServiceConnected(ComponentName name, IBinder service) {
mBinder = IPlayServiceAIDL.Stub.asInterface(service);
}
@Override public void onServiceDisconnected(ComponentName name) {
mBinder = null;
}
};
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
@Override protected void onResume() {
super.onResume();
Intent service = new Intent(ACTION);
bindService(service,mConncet, Context.BIND_AUTO_CREATE);
}
@Override protected void onPause() {
super.onPause();
unbindService(mConncet);
}
private void initView() {
btnStart = (Button) findViewById(R.id.btn_start);
btnStop = (Button) findViewById(R.id.btn_stop);
btnStart.setOnClickListener(this);
btnStop.setOnClickListener(this);
}
@Override public void onClick(View v) {
switch (v.getId()){
case R.id.btn_start:
try {
mBinder.play();
} catch (RemoteException e) {
e.printStackTrace();
}
break;
case R.id.btn_stop:
try {
mBinder.stop();
} catch (RemoteException e) {
e.printStackTrace();
}
break;
}
}
}