Android 回顾Service之Service基础使用

      这两天在回顾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

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。