这两天在回顾Android Service方面的知识,趁着记忆没有消退之前,来总结一下。本文主要讲解Service的基本概念与使用、跨进程调用Service、系统常见Service的使用。所以本文的难度微乎其微,仅适用于想回顾Service知识点的同学,或者还不怎么了解Service的同学,至于Service源码之类的东东,等老夫分析研究之后再来分享。
一、Service基础
我相信只要接触过Android开发的人,都或多或少的了解过Service。Service是什么呢?Service是Android四大组件中与Activity最相似的组件,它完全具有自己的生命周期,不过它可没有和Activity一样的华丽外表,它常年在后台默默付出。Service也是可执行的程序,前面说了它有自己的生命周期,其创建于配置过程与Activity极其相似。不仅如此,Activity与Service还有共同的父亲Context,因此它们都可以调用Context里定义的如getResources()、getContentResolver()等方法。
1、Service的简单使用:
开发Service需要两个步骤:(1)定义一个继承Service的子类。(2)在AndroidManifest.xml文件中配置该Service。
在动手开发第一个Service之前,我们先来了解一下Service的系列生命周期方法:
(1)IBinder onBind(Intent intent):该方法是Service子类必须实现的方法。该方法返回一个IBinder对象,应用程序可通过该对象与Service组件通信。
(2)void onCreate():当该Service第一次被创建后将立即回调该方法。
(3)void onDestroy():当该Service被关闭之前将会回调该方法。
(4)void onStartCommand(Intent intent,int flags,int startId):该方法的早期版本是void onStart(Intent intent,int startId),每次客户端调用startService(Intent)方法启动该Service 时都会回调该方法。
(5)boolean onUnbind(Intent intent):当该Service上绑定的所有客户端都断开连接时将会回调该方法。
下面我们来开发我们的第一个Service,代码如下:
package com.gc.servicetest; import android.app.Notification; import android.app.PendingIntent; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.util.Log; /** * 注意: onCreate()方法只会在Service第一次被创建的时候调用,如果当前Service已经被创建过了, * 不管怎样调用startService方法,onCreate()方法都不会再执行。 * @author Android将军 * */ public class MyService extends Service{ public static final String TAG=MyService.class.getSimpleName(); //必须要实现的方法 @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub Log.v(TAG, "onBind() executed"); return null; } //Service被创建时回调该方法 @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); Log.v(TAG, "onCreate() executed"); Log.v(TAG, "MyService thread id is "+Thread.currentThread().getId()); } //Service被启动时回调该方法 @Override public int onStartCommand(Intent intent, int flags, int startId) { // TODO Auto-generated method stub Log.v(TAG, "onStartCommand() executed"); return super.onStartCommand(intent, flags, startId); } //Service被关闭之前回调该方法 @Override public void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); Log.v(TAG, "onDestroy() executed"); } }
上面这个Service什么也没干——它只是重写了Service组件的onCreate()、onStartCommand()、onDestroy()、onBind()等方法。如果希望Service组件做某些事情,那么只要在onCreate()或onStartCommand()方法中定义相关业务代码即可。开发Service的两个步骤,我们现在已经走完了第一个步骤,下面我们一起走第二步吧。第二步很简单,在AndroidManifest.xml配置Service与在该文件中配置Activity是一样的,只不过标签一个是<service.../>,一个是<activity
.../>。下面给出本次的MyService的配置,代码如下:
<service android:name=".MyService"></service>
当两个步骤走完,我们已经开发出了一个Service组件,接下来就可在程序中运行该Service了,Android系统中运行Service有两种方式,如下:
(1)通过Context的startService()方法:通过该方法启动Service,访问者与Service之间没有关联,即使访问者退出了,Service仍然运行。
(2)通过Context的bindService()方法:使用该方法启用Service,访问者与Service绑定在了一起,访问者一旦退出,Service也就终止。
下面我们就来看看如何使用这两种方式来启动我们刚刚开发的Myservice,我们使用Activity作为Service的访问者,该Activity的界面中包含四个按钮,由于代码简单,这里就不再给出其布局文件,下面直接看一下MainActivity的代码,如下
package com.gc.servicetest; import com.gc.servicetest.MyService.MyBinder; 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; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; /** * * @author Android将军 * */ public class MainActivity extends Activity implements OnClickListener { public static final String TAG=MainActivity.class.getSimpleName(); private Button mBtnStartService; private Button mBtnStopService; private Button mBtnBindService; private Button mBtnUnBindService; private MyService.MyBinder myBinder; private ServiceConnection connection=new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub Log.v(TAG, "onServiceDisconnected() executed"); Log.v(TAG, "onServiceDisconnected() executed name"+name); } @Override public void onServiceConnected(ComponentName name, IBinder service) { // TODO Auto-generated method stub Log.v(TAG, "onServiceConnected() executed"); Log.v(TAG, "onServiceConnected() executed name"+name); myBinder=(MyBinder) service; myBinder.startDownload(); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initUI(); setListener(); Log.v(TAG, "MainActivity thread id is "+Thread.currentThread().getId()); } public void initUI() { mBtnStartService=(Button) findViewById(R.id.start_service); mBtnStopService=(Button) findViewById(R.id.stop_service); mBtnBindService=(Button) findViewById(R.id.bind_service); mBtnUnBindService=(Button) findViewById(R.id.unbind_service); } public void setListener() { mBtnStartService.setOnClickListener(this); mBtnStopService.setOnClickListener(this); mBtnBindService.setOnClickListener(this); mBtnUnBindService.setOnClickListener(this); } @Override public void onClick(View v) { // TODO Auto-generated method stub switch (v.getId()) { case R.id.start_service: Intent mStartIntent=new Intent(this, MyService.class); startService(mStartIntent); break; case R.id.stop_service: Intent mStopIntent=new Intent(this, MyService.class); stopService(mStopIntent); break; case R.id.bind_service: Intent mBindIntent=new Intent(this, MyService.class); bindService(mBindIntent, connection, BIND_AUTO_CREATE); break; case R.id.unbind_service: unbindService(connection); break; default: break; } } }
到此为止,我们已经写好了一个带有Service功能的程序。然后我们运行程序,点击Start Service按钮,然后点击Stop Service按钮,可以看到如下打印结果:
如果在不关闭Service的情况下,连续点击三次Start Sevice 按钮,程序将会连续三次启动Service,打印信息如下:
从上述两种不同的操作以及打印信息,我们验证了前面MyService注释部分注意的内容的正确性,如下:
onCreate()方法只会在Service第一次被创建的时候调用,如果当前Service已经被创建过了, 不管怎样调用startService方法,onCreate()方法都不会再执行。
现在我们已经了解了第一种方式,那么我接下来看看第二种方式:
在第一种方式中,MyService与MainActivity之间基本上不存在太多的关联,因此MyService与MainActivity之间无法进行通信、数据交换。如果想让MyService和MainActivity之间进行方法调用或数据交换,则应该采用第二种方式启动MyService,即使用bindService()和unbindService()方法启动、关闭Service。在使用第二种方式启动MyService之前,肯定是要修改前面MyService的代码的,修改之后的代码如下:
public class MyService extends Service{ public static final String TAG=MyService.class.getSimpleName(); private MyBinder mBinder=new MyBinder(); @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub Log.v(TAG, "onBind() executed"); return mBinder; } @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); Log.v(TAG, "onCreate() executed"); Log.v(TAG, "MyService thread id is "+Thread.currentThread().getId()); } @Override public int onStartCommand(Intent intent, int flags, int startId) { // TODO Auto-generated method stub Log.v(TAG, "onStartCommand() executed"); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); Log.v(TAG, "onDestroy() executed"); } class MyBinder extends Binder { public void startDownload() { Log.v(TAG, "startDownload() executed"); } } }
在进行操作之前,我们先了解一下bindService方法:
Context的bindService()方法的源码如下:
public boolean bindService(Intent service, ServiceConnection conn, int flags) { return mBase.bindService(service, conn, flags); }
这里解释一下该方法的三个参数:
service:该参数通过Intent指定要启动的Service。
conn:该参数是一个ServiceConnection对象,该对象用于监听访问者与Service之间的连接情况。当访问者与Service之间连接成功时将回调该ServiceConnecttion对象的onServiceConnected(ComponentName name,IBinder service)方法;当Service所在的宿主进程由于异常终止或由于其他原因终止,导致该Service与访问者之间断开连接时回调该ServiceConnection对象的onServiceDisconnected(ComponentName
name)方法。
注意:当调用者主动通过unBindService()方法断开与Service的连接时,ServiceConnection对象的onServiceDisconnected(ComponentName name)方法并不会被调用。
flags:指定绑定时是否自动创建Service(如果Service还未创建)。该参数可指定为0(不自动创建)或BIND_AUTO_CREATE(自动创建)。
注意到ServiceConnection对象的onServiceConnected方法中有一个IBinder对象,该对象即可实现与被绑定Service之间的通信。
额,啰嗦了这么多,是不是有点晕了,咱们看看第二种方式启动MyService的执行效果吧,运行程序,点击Bind Service,然后点击unBind Service,打印信息如下:
通过上图我们可以看到,MainActivity已经成功的和MyService进行了通信。我们在MainActivity的成员对象connection的onServiceConnected的方法中调用了startDownload()方法。
下面我们来总结一下:
开发Service需要两个步骤:(1)定义一个继承Service的子类。(2)在AndroidManifest.xml文件中配置该Service。
启动Service有两种方式:(1)startService方法(2)bindService方法
通过startService方式启动Service,Service与访问者之间的基本上没有太大的关联。通过bindService方式启动Service,可以实现Service与访问者之间的通信。那么当通过bindService启动Service时,是如何进行通信的呢?我们按照本案例分析一下,当我们开发MyService类时,我们必须实现的方法是IBinder onBinder(Intent intent),当我们通过bindService方法启动MyService时,我们已经把MainActivity与MyService绑定在一起了,这时MyService方法的onBind方法所返回的IBinder对象将会传给MainActivity的成员connection里的onServiceConnected(ComponentName
name,IBinder service)方法的service参数,这样MainActivity就可通过该IBinder对象与MyService进行通信了。
细心的通信会发现,通过startService启动Service时,调用了onStartCommand方法,而通过bindService方法启动Service时,并没有调用onStartCommand方法,这是为什呢?这是因为两种方式启动Service,导致Service的生命周期略有不同。在下一篇的Service的生命周期中,我会讲述清楚。
好了,BB了这么多,我想对于Service的基础知识应该差不多了,我会在文章末尾提供该Demo的下载地址,如果对你有帮助可以稍微顶一下奥,如果文中有哪里不正确,欢迎指出,如果还有疑问之处,或者我没有阐述清楚的地方,请留言指出,谢谢。
转载请注明出处:http://blog.csdn.net/android_jiangjun/article/details/45458063