1.一步步的建立Remote Service
0)创建一个helloworld项目。
1)新建文件 IRemoteService.aidl
为什么要建aidl文件,因为在这里我们使用的是Remote Service,从字面Remote就知道Service和Client是分开的(这里我们为了演示方便,把Service和Client的实现都放在一起,但是要时刻想到它们是不在一起的)。
定义Service的是RemoteService.java,那我们怎么在Client客户端引用(import)和调用RemoteService.java里面的内容呢?
aidl是Android interface description language 的缩写,android接口描述语言,类似于C语言里面的头文件,在这个文件里面只描述了接口,方法的参数、返回值等,我们将aidl文件引入我们的客户端实现后,我们就可以操作RemoteService.java的函数了
a)
b)
c)定义一个空的RemoteService接口,后面我们在RemoteService.java里面实现的函数都需要在这里注册。
只有先定义了IRemoteService.aidl,我们在编写RemoteService.java这个service的时候才会有IRemoteService.Stub.
2)编写RemoteService.java
package com.example.siqi;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.Process;
import android.util.Log;
public class RemoteService extends Service {
/**
* TAG,用于输出Log,在这里,我们把pid,即进程的ID也记录上
* 这样就可以比较Service的进程和Client的进程是否在同一进程
*/
private static final String TAG = "RemoteService, PID=" + Process.myPid();
/**
* 定义RemoteService的Binder,在这个Binder里面,我们实现了一个
* 函数,getCount(),用于计算getCount()函数被调用的次数。
* 这个函数需要到IRemoteService.aidl注册。
*/
private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {
private int mCount = 0;
/**
* 返回函数调用次数,每调用一次,加1
*/
public int getCount() {
mCount++;
Log.d(TAG, TAG + " getCount: " + mCount);
return mCount;
}
};
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return mBinder;
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
Log.d(TAG, TAG + " onCreate()");
super.onCreate();
}
@Override
public void onStart(Intent intent, int startId) {
// TODO Auto-generated method stub
Log.d(TAG, TAG + " onStart()");
super.onStart(intent, startId);
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
Log.d(TAG, TAG + " onDestroy()");
super.onDestroy();
}
}
MainActivity.java
package com.example.siqi;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Process;
import android.util.Log;
import android.view.Menu;
public class MainActivity extends Activity {
private IRemoteService mService = null;
/**
* 用于日志记录,记录PID,与RemoteService比较
*/
private static final String TAG = "MainActivity, PID=" + Process.myPid();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, TAG + " onCreate()");
/**
* 启动Service,让Service在Activity结束后依然存在
*/
startService(new Intent("com.example.siqi.RemoteService"));
/**
* 绑定service
*/
bindService(new Intent("com.example.siqi.RemoteService"), mConn, Context.BIND_AUTO_CREATE);
}
/**
* 定义一个ServiceConnection
*/
private ServiceConnection mConn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
mService = IRemoteService.Stub.asInterface(service);
Log.d(TAG, TAG + " Service Connected.");
try {
mService.getCount();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
mService = null;
Log.d(TAG, TAG + " Service Disconnected.");
}
};
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
unbindService(mConn);
Log.d(TAG, TAG + " onDestroy().");
super.onDestroy();
}
}
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.siqi"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="7"
android:targetSdkVersion="15" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="com.example.siqi.RemoteService" android:process=":remote">
<intent-filter>
<action android:name="com.example.siqi.RemoteService"></action>
</intent-filter>
</service>
</application>
</manifest>
运行的结果:
11-14 13:22:05.751: D/MainActivity, PID=455(455): MainActivity, PID=455 onCreate()
11-14 13:22:06.541: D/RemoteService, PID=462(462): RemoteService, PID=462 onCreate()
11-14 13:22:06.551: D/MainActivity, PID=455(455): MainActivity, PID=455 Service Connected.
11-14 13:22:06.561: D/RemoteService, PID=462(462): RemoteService, PID=462 getCount: 1
11-14 13:22:06.592: D/RemoteService, PID=462(462): RemoteService, PID=462 onStart()
可以看到,MainActivity运行在PID=455的进程中,RemoteService运行在PID=462的进程中。
退出MainActivity后:
11-14 13:25:10.131: D/MainActivity, PID=455(455): MainActivity, PID=455 onDestroy().
只有一条,MainActivity执行了Destory方法,但是Service依然在运行。
再次运行MainActivity:
11-14 13:26:23.271: D/MainActivity, PID=455(455): MainActivity, PID=455 onCreate()
11-14 13:26:23.291: D/RemoteService, PID=462(462): RemoteService, PID=462 onStart()
11-14 13:26:23.302: D/MainActivity, PID=455(455): MainActivity, PID=455 Service Connected.
11-14 13:26:23.311: D/RemoteService, PID=462(462): RemoteService, PID=462 getCount: 2
在startService的时候,由于service已经启动了,所以只是执行了service的OnStart方法,没有执行service的OnCreate方法。再次获取getCount的时候,得到了2,也印证了service是一直在运行的。可以通过下面的代码结束掉service
stopService(new Intent("com.example.siqi.RemoteService"));