本文主要寫在同一個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;
}
}
}