android SDK提供了Service,用于类似*nix守护进程或者windows的服务。
Service有两种类型:
1.本地服务(Local Service):用于应用程序内部
2.远程服务(Remote Sercie):用于android系统内部的应用程序之间
前者用于实现应用程序自己的一些耗时任务,比如查询升级信息,并不占用应用程序比如Activity所属线程,而是单开线程后台执行,这样用户体验比较好。
后者可被其他应用程序复用,比如天气预报服务,其他应用程序不需要再写这样的服务,调用已有的即可。
package com.easymorse;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class CountService extends Service {
private boolean threadDisable;
private int count;
@Override
public IBinder onBind(Intent intent) {
return null ;
}
@Override
public void onCreate() {
super .onCreate();
new Thread( new Runnable() {
@Override
public void run() {
while ( ! threadDisable) {
try {
Thread.sleep( 1000 );
} catch (InterruptedException e) {
}
count ++ ;
Log.v( " CountService " , " Count is " + count);
}
}
}).start();
}
@Override
public void onDestroy() {
super .onDestroy();
this .threadDisable = true ;
Log.v( " CountService " , " on destroy " );
}
public int getCount() {
return count;
}
}
需要将该服务注册到配置文件AndroidManifest.xml中,否则无法找到:
xml version="1.0" encoding="utf-8" ?>
在Activity中启动和关闭本地服务。
package com.easymorse;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
public class LocalServiceDemoActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout.main);
this .startService( new Intent( this , CountService. class ));
}
@Override
protected void onDestroy() {
super .onDestroy();
this .stopService( new Intent( this , CountService. class ));
}
}
可通过日志查看到后台线程打印的计数内容。
package com.easymorse;
public interface ICountService {
public abstract int getCount();
}
修改后的CountService代码:
package com.easymorse;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
public class CountService extends Service implements ICountService {
private boolean threadDisable;
private int count;
private ServiceBinder serviceBinder = new ServiceBinder();
public class ServiceBinder extends Binder implements ICountService{
@Override
public int getCount() {
return count;
}
}
@Override
public IBinder onBind(Intent intent) {
return serviceBinder;
}
@Override
public void onCreate() {
super .onCreate();
new Thread( new Runnable() {
@Override
public void run() {
while ( ! threadDisable) {
try {
Thread.sleep( 1000 );
} catch (InterruptedException e) {
}
count ++ ;
Log.v( " CountService " , " Count is " + count);
}
}
}).start();
}
@Override
public void onDestroy() {
super .onDestroy();
this .threadDisable = true ;
Log.v( " CountService " , " on destroy " );
}
/* (non-Javadoc)
* @see com.easymorse.ICountService#getCount()
*/
public int getCount() {
return count;
}
}
服务的注册也要做改动,AndroidManifest.xml文件:
xml version="1.0" encoding="utf-8" ?>
Acitity代码不再通过startSerivce和stopService启动关闭服务,另外,需要通过ServiceConnection的内部类实现来连接Service和Activity。
package com.easymorse;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
public class LocalServiceDemoActivity extends Activity {
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
countService = (ICountService) service;
Log.v( " CountService " , " on serivce connected, count is "
+ countService.getCount());
}
@Override
public void onServiceDisconnected(ComponentName name) {
countService = null ;
}
};
private ICountService countService;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout.main);
this .bindService( new Intent( " com.easymorse.CountService " ),
this .serviceConnection, BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
this .unbindService(serviceConnection);
super .onDestroy(); //注意先后
}
}
package com.easymorse;
interface ICountService {
int getCount();
}
编写服务(Service)类,稍有差别,主要在binder是通过远程获得的,需要通过桩(Stub)来获取。桩对象是远程对象的本地代理。
package com.easymorse;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class CountService extends Service {
private boolean threadDisable;
private int count;
private ICountService.Stub serviceBinder = new ICountService.Stub() {
@Override
public int getCount() throws RemoteException {
return count;
}
};
@Override
public IBinder onBind(Intent intent) {
return serviceBinder;
}
@Override
public void onCreate() {
super .onCreate();
new Thread( new Runnable() {
@Override
public void run() {
while ( ! threadDisable) {
try {
Thread.sleep( 1000 );
} catch (InterruptedException e) {
}
count ++ ;
Log.v( " CountService " , " Count is " + count);
}
}
}).start();
}
@Override
public void onDestroy() {
super .onDestroy();
this .threadDisable = true ;
Log.v( " CountService " , " on destroy " );
}
}
配置文件AndroidManifest.xml和上面的类似,没有区别。
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
countService = (ICountService) service;
try {
Log.v( " CountService " , " on serivce connected, count is "
+ countService.getCount());
} catch (RemoteException e) {
throw new RuntimeException(e);
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
countService = null ;
}
};
这样就可以在同一个应用程序中使用远程服务的方式和自己定义的服务交互了。
package com.easymorse;
import android.os.Parcel;
import android.os.Parcelable;
public class CountBean implements Parcelable {
public static final Parcelable.Creator < CountBean > CREATOR = new Creator < CountBean > () {
@Override
public CountBean createFromParcel(Parcel source) {
CountBean bean = new CountBean();
bean.count = source.readInt();
return bean;
}
@Override
public CountBean[] newArray( int size) {
return new CountBean[size];
}
};
public int count;
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt( this .count);
}
@Override
public int describeContents() {
return 0 ;
}
}
然后,需要在相同包下建一个同名的aidl文件,用于android生成相应的辅助文件:
ackage com.easymorse;
parcelable CountBean;
这一步是android 1.5后的变化,无法通过adt生成aidl,也不能用一个比如全局的project.aidl文件,具体见: http://www.anddev.org/viewtopic.php?p=20991
package com.easymorse;
import com.easymorse.CountBean;
interface ICountService {
CountBean getCount();
}
其他的改动很小,只需将CountService和调用CountService的部分修改为使用CountBean即可
原文代码: LocalityService.zip
ALocalityService.zip
原文传送门:http://yangguangfu.iteye.com/blog/699306