Android四大组件之—— 使用服务进行后台操作

 

什么是服务

       服务是一个没有可视化界面的组件,它可以在后台长期运行并进行各种操作。

 

服务的创建

       我们只需要继承Service类并实现相应的方法即可创建服务

       要想启动服务,还得在AndroidManifest中注册服务

 

服务类的示例代码

 

package com.whathecode.servicedemo;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;

public class ExtendsionService extends Service
{

	/**
	 * 当服务第一次被创建的时候调用此方法
	 */
	@Override
	public void onCreate()
	{
		
		super.onCreate();
		Toast.makeText(getBaseContext(), "服务被创建了", Toast.LENGTH_SHORT).show();
	}
	
	/**
	 * 当通过startService方法启动服务时此方法被调用
	 */
	@Override
	public int onStartCommand(Intent intent, int flags, int startId)
	{
		Toast.makeText(getBaseContext(), "服务被启动了", Toast.LENGTH_SHORT).show();
		return super.onStartCommand(intent, flags, startId);
	}

	@Override
	public IBinder onBind(Intent intent)
	{
		return null;
	}

	@Override
	public void onDestroy()
	{
		super.onDestroy();
	}

}

 

使用startService启动服务

主界面的逻辑代码:

 

package com.whathecode.servicedemo;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends Activity
{

	Intent service = null;
	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		//创建服务
		service = new Intent(this, ExtendsionService.class);
	}

	public void start(View view)
	{
		//启动服务
		startService(service);
	}
	
	public void stop(View view)
	{
		//停止服务
		stopService(service);
	}
}

 

注册服务:

 

<service android:name="com.whathecode.servicedemo.BackgroundService"></service>

 

运行效果:

 

技术分享

 

注意:

         当我们第一次点击启动服务按钮的时候,onCreate方法和onStartCommand方法依次执行,

         但在第二次点击启动服务按钮的时候,这个服务已经处于运行状态,onCreate方法不再执行第二次,

         而onStartCommand方法总是在调用startService启动服务的时候执行。

         onDestroy方法在stopService方法被调用后执行。

 

除了使用startService方法启动服务外,我们还可以使用Bind的方式启动服务。

前者和后者的不同在于:

      服务的生命周期不依赖于启动者。服务被启动后一直在后台运行直到调用stopService被停止。

       使用Bind方式启动服务,服务的生命周期依赖于启动者。即服务在启动者退出后自动销毁。

 

使用Bind方式启动服务

主要使用bindService方法启动服务,unbindService方法销毁服务。

使用此方式启动服务的好处是,bind定成功的时候服务返回一个IBinder对象,

我们可以通过在服务类里面实现这个对象,从而访问服务里面的具体方法。

从而达到和服务沟通的目的。

 

注意:

        我们不能以直接实例化服务的方式调用里面的方法。

 

另外:

       如果在退出服务的时候没有解绑,那么程序就会抛出异常IllegalArgumentException异常。

       因此,每次调用bindService启动服务,完成后需要退出服务都需要使用unbindService 解绑。  

 

示例代码:

package com.whathecode.servicedemo;

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.view.View;

public class MainActivity extends Activity
{

	Intent service = null;
	IReceptionist rpst;

	/**
	 * bindService和unbindService方法使用的参数
	 */
	private ServiceConnection conn = new ServiceConnection()
	{
		
		//此方法在服务连接被意外终止的时候被调用,
		@Override
		public void onServiceDisconnected(ComponentName name)
		{
		
		}
		
		//当服务被连接上的时候自动调用这个方法,第二个参数是服务类onBind方法中返回的对象
		@Override
		public void onServiceConnected(ComponentName name, IBinder service)
		{
			rpst = (IReceptionist) service;
			rpst.callExtendsionNumber();
		}
	};
	
	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		//创建服务
		service = new Intent(this, ExtendsionService.class);
	}

	public void start(View view)
	{
		//启动服务
		startService(service);
	}
	
	public void stop(View view)
	{
		//停止服务
		stopService(service);
	}
	
	public void bind(View view)
	{
		//绑定服务
		bindService(service, conn , BIND_AUTO_CREATE);
	}
	
	public void unBind(View view)
	{
		//解绑服务
		unbindService(conn);
	}
}

 

继承ServiceBinder对象,并实现自定义接口:

通过这个方式,我们可以暴露只需要的方法,实现代码的保护。

 

IReceptionist接口代码:
package com.whathecode.servicedemo;

public interface IReceptionist 
{
	public void callExtendsionNumber();
}

 

ExtendsionService服务类代码:

 

package com.whathecode.servicedemo;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;

public class ExtendsionService extends Service
{

	private static final String TAG = "ExtendsionService";

	/**
	 * 当服务第一次被创建的时候调用此方法
	 */
	@Override
	public void onCreate()
	{
		
		super.onCreate();
		Toast.makeText(getBaseContext(), "服务被创建了", Toast.LENGTH_SHORT).show();
	}
	
	/**
	 * 当通过startService方法启动服务时此方法被调用
	 */
	@Override
	public int onStartCommand(Intent intent, int flags, int startId)
	{
		Toast.makeText(getBaseContext(), "服务被启动了", Toast.LENGTH_SHORT).show();
		return super.onStartCommand(intent, flags, startId);
	}

	@Override
	public IBinder onBind(Intent intent)
	{
		return new ServiceBinder();
	}

	@Override
	public void onDestroy()
	{
		Toast.makeText(getBaseContext(), "服务被销毁了", Toast.LENGTH_SHORT).show();
		Log.d(TAG, "服务被销毁了");
		super.onDestroy();
	}
	
	public void putExtendsion()
	{
		Toast.makeText(getBaseContext(), "正在帮你转接分机", Toast.LENGTH_SHORT).show();
	}
	
	/**
	 * 
	 * 继承Binder并实现IReceptionist接口
	 * 继承Binder类的目的是onBind方法中需要返回这个类型的对象
	 * 
	 * 实现IReceptionist接口是暴露方法的需要
	 */
	private class ServiceBinder extends Binder implements IReceptionist
	{
		public void callExtendsionNumber()
		{
			putExtendsion();
		}
		
		private void otherMethod()
		{
			
		}
	}
}

 

运行效果:

技术分享

 

注意看上图,我们在按下返回键的时候,Activity被销毁,由它启动的服务也跟着被销毁。

这样的服务貌似作用不大,有没有办法在退出Activity的时候不退出服务呢?

答案是有的:Android允许我们先启动一个服务,然后再调用bindService绑定到服务,

                    这样,我们既可以达到和服务沟通的目的,也可以使服务长期在后台运行。

 

看下图:

技术分享

 

通过下面的图,就可以更清楚地理解上面代码的工作原理:

 

技术分享

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