距离上篇文章竟然快一年了。这次是想明确service一些比较重要的点。
至于什么是service,我也不想多去讨论,我只想清晰确认这么几个问题:
1、service的生命周期到底如何?
2、Activity如何让service做事?
3、service与thread之间有没有关系?
4、远程service是什么东西?
5、AIDL的使用?
6、前台service?
一、生命周期
如果需要图,可以百度,好多。我这里直接运行代码打log。
1、startService()启动Service
操作顺序是:
startService(intent),service相应执行的是oncreate() ------> onStartCommand() ------> onStart()。
stopService(intent),service相应执行的是onDestroy()。
startService(intent),service相应执行的是oncreate() ------> onStartCommand() ------> onStart()。
startService(intent),service相应执行的是onStartCommand() ------> onStart()。
stopService(intent),service相应执行的是onDestroy()。
这里可见,onCreate() 只会执行一次,即service第一次被启动的时候,在没有destroy之前,继续启动onCreate()不会再执行。
2、bindService()启动Service
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
DebugLog("onServiceConnected()");
}
};
bindService的原型:
public boolean bindService(Intent service, ServiceConnection conn, int flags)
参数:
public void unbindService(ServiceConnection conn)
二、Activity如何让service服务自己?
1、使用binder类
public class MyBinder extends Binder{
public void startDownload(){
DebugLog("start download...");
}
//获取当前Myservice实例
public MyService getService(){
return MyService.this;
}
}
这个类里面有一个startDownload()方法,模拟下载。
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
DebugLog("onBind()");
return new MyBinder();
}
MyService.MyBinder myBinder = (MyBinder)service;
myBinder.startDownload();
这种方法可以简单的让Activity调用service里面的方法。
2、使用广播
private BroadcastReceiver myReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
String string = intent.getStringExtra("main");
DebugLog("string:"+string);
}
};
在Service 中的onCreate()函数里注册:
IntentFilter filter = new IntentFilter();
filter.addAction("com.fleur.mybroadcast");
registerReceiver(myReceiver, filter);
DebugLog("registerReceiver success");
在service中的onDestroy()函数中反注册:
unregisterReceiver(myReceiver);
动态注册的广播一定不要忘记反注册。
case R.id.button8:
Intent intent5 = new Intent("com.fleur.mybroadcast");
intent5.putExtra("main", "this broadcast is from mainActivity");
sendBroadcast(intent5);
break;
log如下:
3、使用回调
我一直觉得回调是一件很神奇的事情。如果不懂回调可以看一下这篇文章: http://blog.csdn.net/xiaanming/article/details/8703708public interface OnProgressListener {
public void onProgress(int progress);
}
//更新进度的回调接口
private OnProgressListener onProgressListener;
/**
* 注册回调接口的方法
* @param onProgressListener
*/
public void setOnProgressListener(OnProgressListener onProgressListener) {
this.onProgressListener = onProgressListener;
}
然后再Service里面声明一个方法,依然模拟下载:
public void startDownload(){
new Thread(){
@Override
public void run() {
while(progress < MAX_PROGRESS){
progress += 5;
//进度发生变化时告诉调用方
if(onProgressListener!=null){
onProgressListener.onProgress(progress);
}
try {
sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}.start();
}
注意这个是service里面的方法,不是MyBinder类里面的方法。
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
DebugLog("onServiceConnected()");
myBinder = (MyBinder) service;
myService = myBinder.getService();
myService.setOnProgressListener(new OnProgressListener() {
@Override
public void onProgress(int progress) {
// TODO Auto-generated method stub
progressBar.setProgress(progress);
}
});
}
//然后自己写一个button控制,使用得到的MyService对象调用startDownload()方法,实现回调。
myService.startDownload();
对于不同进程间的activity通信,有两种方式,一是使用Messenger,二是使用AIDL。这里先不讲了。
三、service与thread之间有没有关系?
四、远程service是什么东西?
<service android:name="com.fleur.service.MyRemoteService"
android:process=":remote">
<intent-filter >
<action android:name="com.fleur.service.MyRemoteService"/>
</intent-filter>
添加了一句话:android:process=":remote"
五、AIDL的使用?
package com.fleur.service;
interface MyAIDLService{
String toUpperCase(String str);
}
import com.fleur.service.MyAIDLService.Stub;
Stub mBinder = new Stub() {
@Override
public String toUpperCase(String str) throws RemoteException {
// TODO Auto-generated method stub
if(str!=null){
return str.toUpperCase();
}
return null;
}
};
其实stub是aidl文件里的,它继承了Binder实现了我们自己写的接口。
在activity中同样实例serviceConnected接口,声明一个刚才写的接口对象,在onServiceConnected里面得到实例。
private MyAIDLService myAIDLService;
private ServiceConnection conn = new ServiceConnection(
) {
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
myAIDLService = MyAIDLService.Stub.asInterface(service);
try {
String upperStr = myAIDLService.toUpperCase("hello world");
DebugLog("upperStr = "+upperStr);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
这样在去bindService就OK了。实现了不同进程间的通信。
六、前台service
Notification notification = new Notification(R.drawable.ic_launcher, "Android_Component", System.currentTimeMillis());
Intent notificationIntent = new Intent(this,MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, "title of notification", "content of notification", pendingIntent);
startForeground(1, notification);
最最关键的就是最后一句,startForeground()方法。