Android开发之Service服务详解

服务,作为Android四大组件之一,必然是重点。我们今天就来讲解一下有关服务的生命周期、两种开启方式以及相关用法。

服务有两种开启方式,一种是正常开启, 一种是以绑定的方式开启,当然,这两种方式可以组成混合开启。


一、服务的正常开启

正常开启服务的方法非常简单,我们先看如何定义一个服务

1、编写一个类,继承Service类。

   我们先不管代码中的binder类。那个后续讲解用。
public class TestService extends Service {

	@Override
	public IBinder onBind(Intent arg0) {
		System.out.println("onBind");
		return new Mybinder();
	}

	@Override
	public void onCreate() {
		System.out.println("create");
		super.onCreate();
	}

	@Override
	public void onDestroy() {
		System.out.println("onDestroy");
		super.onDestroy();
	}

	@Override
	@Deprecated
	public void onStart(Intent intent, int startId) {
		System.out.println("start");
		super.onStart(intent, startId);
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		System.out.println("onStartCommand");
		return super.onStartCommand(intent, flags, startId);
	}

	@Override
	public boolean onUnbind(Intent intent) {
		System.out.println("onUnbind");
		return super.onUnbind(intent);
	}

	class Mybinder extends Binder implements IService {

		public void method() {

			System.out.println("serviceMethod");
		}

	}

}

2、清单文件中注册服务

  <service android:name="com.example.servicedemo.TestService" >
        </service>

3、正常开启服务

intent = new Intent(getBaseContext(), TestService.class);
		startService(intent);

4、正常关闭服务

	stopService(intent);

这里我们值得注意的是,一般服务的意图对象会做成全局变量,便于在退出的时候销毁服务。这是服务正常使用的步骤。正常使用的时候,服务的生命周期是这样的:
开启: onCreate-->onStartCommand-->onStart
结束: onDestory
正常情况下,服务只开启一次,既只执行一次onCreate方法,如果已经开启服务,再次执行startService方法时候,会跳过onCreate,直接执行onStartCommand方法以及之后的方法。其中onStart方法已经废弃

二、服务的绑定开启

      有时候,我们需要调用服务里的方法,这个时候,我们就需要采取绑定的方式,开启服务了。关于绑定开启服务的原理,这个涉及的android的binder机制,这个我们在下一篇专题中在讲解。这里直接跳过。
    采用绑定的方式开启服务,我们需要准备几个东西。
   1、实现一个继承binder的类
   2、activity里面实现一个实现ServiceConnection接口的类。

1、binder类的实现

    绑定服务,会调用onBind的方法,然后返回一个IBinder的代理。所以我们需要实现一个继承Binder的类。然后在里面写一个方法,就可以调用服务里的方法了。其中IService是一个接口类,便于后续操作远程调用服务方法就这样一起写了。
 
class Mybinder extends Binder implements IService {

		public void method() {

			System.out.println("serviceMethod");
		}

	}

  在onBind方法里返回这个binder
	@Override
	public IBinder onBind(Intent arg0) {
		System.out.println("onBind");
		return new Mybinder();
	}

        2、拿到代理binder

因为Binder实现了IService接口,所以我们拿到的也是一个实现过IService的类。
 
	class Mycon implements ServiceConnection {

		@Override
		public void onServiceConnected(ComponentName arg0, IBinder binder) {
			Iservice = (IService) binder;
		}

		@Override
		public void onServiceDisconnected(ComponentName arg0) {

		}

	}

          3、服务的绑定与调用服务方法和解绑

   
intent = new Intent(getBaseContext(), TestService.class);
		conn = new Mycon();
		bindService(intent, conn, BIND_AUTO_CREATE);
当这样绑定服务后,服务的生命周期执行是这样的:onCreate-->onBind,不会执行onStartCommand方法,拿到代理类后,我们可以执行服务里的方法了。
	findViewById(R.id.test).setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				//startService(intent);
				Iservice.method();
			}
		});
        这样,就调用了服务里的方法。
         采用绑定的方式开启服务有一个风险,就是如果采用绑定的方法开启服务,那么当你最小化程序的时候,会报错。程序会提醒你要解绑服务才能这样。这个时候我们就需要在一些actvity的生命周期里面解绑服务
 
unbindService(conn);
         执行这行代码,就可以解绑服务了。执行的生命周期函是:onUnBind-->onDestory


       三、服务的混合开启

之前,我们说,采用绑定的方式开启服务,就会造成最小化的时候程序报错,那么有什么办法解决呢?这个时候,我们就需要采用混合开启的方法开启服务了。
所谓的混合开启,就是在正常开启服务之后,在采用绑定的方法绑定服务。我们来看代码
intent = new Intent(getBaseContext(), TestService.class);
		startService(intent);
		conn = new Mycon();
		bindService(intent, conn, BIND_AUTO_CREATE);

这样就达到了混合开启服务的效果。他所执行的生命周期的函数为:onCreate-->onStartCommand-->onStart-->onBind
        那么退出的时候,我们需要先解绑,在停止服务
				unbindService(conn);
				stopService(intent);
				conn=null;
				intent=null;

这个时候执行的生命周期函数为:onUnbind-->onDestory



四、调用远程服务的方法

 有时候,我们需要调用别的应用里面的服务的方法,这个其实就是android的IPC机制原理的实现。我们今天就先讲讲实现步骤的方法代码。
 

1、将接口文件重命名为.aidl文件

  
package com.example.servicedemo;

interface IService {
	
	 void method();

}

我们将之前的IService接口文件的后缀名改为.aidl后,需要将里面的public等修饰字段去掉。
 

  2、在新的应用中,新建一个与之前存放.aidl文件包名一样的包。

     新建好之后,将.aidl文件复制到包里
技术分享

   3、修改之前服务类里的binder实现方法

      
	class Mybinder extends IService.Stub {

		public void method() {

			System.out.println("serviceDemomethod");
		}

	}
      将之前的接口文件修改之后,我们直接继承接口文件自动生成的.Stub类即可

     4、定义服务的隐试意图开启方式,并采用隐式意图开启服务

     因为不能拿到别的应用里的服务的类名,所以我们需要采用隐式意图去开启服务并绑定。
    
        <service android:name="com.example.servicedemo.TestService" >
            <intent-filter>
                <action android:name="com.example.servicedemo.TestService.action" />
            </intent-filter>
        </service>
在绑定服务之前,需要重写一下代理接口实现类,这里不再采用强制转换了。
       
	class Mycon implements ServiceConnection {

		@Override
		public void onServiceConnected(ComponentName arg0, IBinder binder) {
			Iservice = IService.Stub.asInterface(binder);
		}

		@Override
		public void onServiceDisconnected(ComponentName arg0) {

		}

	}

       然后绑定服务,就可以调用远程服务的方法了
      
<span style="white-space:pre">		</span>Intent intent = new Intent();
		intent.setAction("com.example.servicedemo.TestService.action");
		bindService(intent, new Mycon(), BIND_AUTO_CREATE);
		findViewById(R.id.test).setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				try {
					Iservice.method();
				} catch (RemoteException e) {
					e.printStackTrace();
				}

			}
		});


在服务使用的过程中,需要注意的是,结束服务的时候,一定要记得释放掉服务里的所有资源,尤其是服务里有开启子线程并无线循环的。
好了,服务的基本使用方法到此讲解结束,希望此文能帮助到大家。

 

 

 

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