Freedie移动互联网研究院原创文章如转载,请注明:转载自博客原文地址:http://www.qinjianping.com/?p=20#content
Service是没有用户界面的,在后台运行的Android Framework核心组件之一。Android支持两种Service:本地Service和远程Service。所谓的“本地Service”是指这种Service只能被当前应用程序访问,而不能被其他应用程序访问。那与之相对的“远程Service”不仅可以被当前的应用程序访问,还可以被不同进程当中的应用程序访问。远程Service通过使用Android Interface Definition Language(AIDL)来实现不同进程当中对于Service的调用。
秘籍一、如何创建一个简单的Service
public class TestService1 extends Service {
private static final String TAG = "TestService1";
@Override
public void onCreate() {
Log.d(TAG, "-->onCreate() method was invoked");
super.onCreate();
}
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "-->onBind() method was invoked");
return null;
}
}
首先,定义的Service需要继承android.app.Service,然后需要在项目清单文件当中声明此Service。
<service android:name="TestService1"></service>
PS:虽然这么一个Service没有任何实际的作用,但是不得不说定义一个Service就是这么的简单。
秘籍二、深入理解Android当中的Service
onCreate()方法是当Service第一次创建时由系统自动回调的一个方法,跟Activity的onCreate()的回调机制类似,主要可以用来做一些在Service启动的时候的初始化的操作。比如,我们可以在onCreate()方法当中启动一个后台线程,在onDestory()方法当中停止线程。调用Service的客户端可以通过两种方式来启动Service,分别为Context.startService()和Context.bindService()方法。注意:一般来讲,通过Context.startService()启动的Service都是本地的Service,而通过Context.bindService()启动的Service都是远程Service,但是也不一定,如果你的应用程序,比如说Activity需要跟本地Service做交互,那么你也只能采用Context.bindService()来启动本地Service。Android为什么提供Service这种机制?主要有两个原因,第一是允许开发者利用Service从而轻松的实现一些后台的任务处理,第二是允许开发者通过使用AIDL来实现进程间的交互。什么时候使用本地Service,什么时候使用远程Service?简单来说,如果某一个Service目的仅仅是为了在当前应用程序当中做一些后台任务,而其他应用程序当中不需要做这些任务的时候,那么这个Service就可以定义为本地Service, 而不用去实现onBind()方法。相反,如果某一个Service()的后台任务,不仅当前应用程序需要,其他应用程序也需要做此中后台任务,那么可以把这个Service定义为远程Service,实现服务的共享。
综上所述:不能仅仅通过客户端的调用方式来判断这个Service是属于本地Service还是远程Service。因为客户端如果需要与本地Service做一定的交互,也只能是通过Context.bindService()来启动服务,我们可以根据应用程序当中是否有相应的AIDL文件来进行判断,如果有相应的AIDL文件,则表明此Service是远程Service。如果没有,则表明此Service为本地Service。
秘籍三、理解本地Service
public class BackgroundService extends Service {
private NotificationManager notificationMgr;
@Override
public void onCreate() {
super.onCreate();
notificationMgr = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
displayNotificationMessage("starting Background Services");
Thread tr = new Thread(new ServiceWorker());
tr.start();
}
class ServiceWorker implements Runnable{
@Override
public void run() {
//do background processing here
//stop when service when done
//BackgroundService.this.stopSelf();
}
}
private void displayNotificationMessage(String message) {
Notification notification = new Notification(R.drawable.icon, message, System.currentTimeMillis());
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0);
notification.setLatestEventInfo(this, "Background Service", message, contentIntent);
notificationMgr.notify(R.id.app_notification_id, notification);
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onDestroy() {
super.onDestroy();
displayNotificationMessage("stopping Background Service");
}
}
客户端如何调用本地Service:public class LocaleServiceActivity extends Activity {
private static final String TAG = "LocaleServiceActivity";
Button mBindBtn, mUnbindBtn;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Log.d(TAG, "starting service");
mBindBtn = (Button)findViewById(R.id.bindButton);
mUnbindBtn = (Button)findViewById(R.id.stopButton);
mBindBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
startService(new Intent(LocaleServiceActivity.this, BackgroundService.class));
}
});
mUnbindBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
stopService(new Intent(LocaleServiceActivity.this, BackgroundService.class));
}
});
}
}
如果你还是觉得我写的不够详细 看的不够爽 不要紧我把本地Service源代码的下载地址贴出来 欢迎大家一起讨论学习ALFA DeV工作室希望可以和大家一起进步。下载地址: http://download.csdn.net/source/3568186
秘籍四、理解远程Service
1、首先需要定义AIDL文件
定义好AIDL文件之后,eclipse会在gen目录下面自动生成IStockQuoteService.java文件。在这个接口当中定义了一个静态抽象类Stub,这个类继承了android.os.Binder并且实现了IStockQuoteService接口。
2、实现远程Service
public class StockQuoteService extends Service {
private static final String TAG = "StockQuoteService";
public class StockQuoteServiceImpl extends IStockQuoteService.Stub{
@Override
public double getQuote(String ticker) throws RemoteException {
Log.v(TAG, "getQuote() called for" + ticker);
return 20.0;
}
}
@Override
public void onCreate() {
Log.v(TAG,"onCreate() called");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.v(TAG,"onStartCommand() called");
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent intent) {
return new StockQuoteServiceImpl();
}
@Override
public void onDestroy() {
Log.v(TAG,"onDestory() called");
super.onDestroy();
}
}
为了将此Service暴露给其他客户端,我们需要在项目清单文件中加上如下配置:
<service android:name="StockQuoteService">
<intent-filter>
<action android:name="com.freedie.remoteservicedemo.IStockQuoteService"/>
</intent-filter>
</service>
3、客户端对远程Service进行调用
![](http://hi.csdn.net/attachment/201109/1/0_1314915079cjA6.gif)
需要将aidl文件copy到客户端应用程序当中,当然你需要建立好原先AIDL所在的包名,然后将AIDL文件放在此包名下。
public class MainActivity extends Activity {
private static final String TAG = "MainActivty";
private Button bindBtn, calBtn, unbindBtn;
private IStockQuoteService stockService = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
bindBtn = (Button)findViewById(R.id.bindButton);
calBtn = (Button)findViewById(R.id.calButton);
unbindBtn = (Button)findViewById(R.id.unbindButton);
bindBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
bindService(new Intent(IStockQuoteService.class.getName()), serConn, Context.BIND_AUTO_CREATE);
}
});
calBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
calService();
}
});
unbindBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
unbindService(serConn);
}
});
}
private void calService() {
try{
double val = stockService.getQuote("ALFA DeV");
Toast.makeText(this, "Value From service is:" + val, Toast.LENGTH_SHORT).show();
}catch(RemoteException e){
Log.e(TAG, e.getMessage());
}
}
private ServiceConnection serConn = new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.v(TAG, "onServiceConnected() callled");
stockService = IStockQuoteService.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.v(TAG, "onServiceDisconnected() called");
stockService = null;
}
};
}
客户端也写好之后,需要写将远程Service应用程序部署到真机或者模拟器上面,然后将客户端调用程序也部署上去。单击Bind按钮之后,进行绑定远程Service。单击Cal按钮,界面效果如下:
调用远程服务成功。
本篇博客简单介绍了两种不同的Service,本地服务如何定义,以及客户端如何进行调用,以及远程服务的定义和调用方法。下篇博客,ALFA DeV工作室将会为大家更深入的讲解如何使用Service,在什么情况下使用Service,目的是让大家对Service有个非常清晰地认识,能够在适当场合正确使用Service。
最后如果你还是觉得我写的不够详细 看的不够爽 不要紧我把远程服务源代码的下载地址贴出来 欢迎大家一起讨论学习ALFA DeV工作室希望可以和大家一起进步。
下载地址:http://download.csdn.net/source/3568196