天天看点

android service 介绍

为了更好理解service, 大家可以下载示例代码,下载

android service组件用来完成android后台任务,也就是在后台默默的干自己的事,好多恶意的软件也都是通过此方法在用户的电脑上的悄悄做坏事,可以将activity比作饭店的服务员,service比作厨房的大厨,服务员直接和用户打交道,而大厨在后厨为用户烧菜。

大家也许会好奇,为什么一定要用service,我直接在activity的oncreate等函数直接启动一个线程不就好了,为什么要这么麻烦还要新建立一个service类, 假如我们在onCreate函数中启动一个线程,希望循环的处理一些消息

@Override
	protected void onStart() {
		// TODO Auto-generated method stub
		super.onStart();
		Log.e(TAG, "onStart is called");
		
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				while(true) {
					// TODO Auto-generated method stub
					Log.e(TAG, "create by activity");
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		}).start();
	}
           

好了,现在我们在activity中通过onStart启动一个线程,假如你要播放音乐吧,当这个activity destory的时候,你要销毁该线程吧,所以你要干的事也就终止了,音乐停止了,如果你不去销毁,那问题又来了,当activity 重新create的时候,有再一次创建了线程,又一个播放音乐的线程起来了,Service解决了这个问题。

启动一个service的流程如图所示,通过在activity调用startService, service会后先判断,这个service派生类是否已经处于运行状态,如果不是,调用重载函数onCreate进行Service的创建,如果已经创建,则直接调用onStartCommand函数,也就是不同activity多次start 该service后只有onStartCommand会多次执行,onCreate只会在最初时执行一次。

android service 介绍

启动一个Service的示例代码如下

1.创建一个Service类

package com.example.android.test;
import android.app.Service;
public class MainActivityService extends Service{
@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();
		
		Log.e(TAG, "service on Create");
		
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				while(true) {
					Log.e(TAG, "created by ServiceonCreate");
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				
			}
		}).start();
	}
	
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		// TODO Auto-generated method stub
		
		Log.e(TAG, "service on onStartCommand");
		return super.onStartCommand(intent, flags, startId);
	}
	
	@Override
	public void onDestroy() {
		Log.e(TAG, "service on onDestroy");
		// TODO Auto-generated method stub
		super.onDestroy();
	}
}
           

然后需要在androidManifest.xml中添加该Service的声明

<service android:name="MainActivityService"></service>
           

然后在activity中可以通过startService启动该类

package com.example.android.test;
import android.os.Bundle;
import android.os.IBinder;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ComponentName;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity implements OnClickListener{
	Button StartService;
	Button StopService;
	
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		StartService = (Button) findViewById(R.id.startService);
		StopService = (Button) findViewById(R.id.stopService);
		
		StartService.setOnClickListener(this);
		StopService.setOnClickListener(this);
	}
	
	/*当发生单击事件时,android会回调该函数*/
	@Override
	public void onClick(View v) {
		
		switch(v.getId()) {
		/*单击这个按钮会启动一个server, 我在service中启动了一个线程,循环打印log*/
		case (R.id.startService) :
			Log.e(TAG, "startService is clicked");
			Intent startIntent = new Intent(this, MainActivityService.class);
			startService(startIntent);
			break;
		/*单击这个按钮会停止service, 当然如果绑定了服务,必须要进行unbind后,service才会真正的执行onDestroy*/
		case (R.id.stopService) :
			Log.e(TAG, "stopService is clicked");
			Intent stopIntent = new Intent(this, MainActivityService.class);
			stopService(stopIntent);
			break;
		default :
			break;
		}
	}
}
           

Service类解决了activity destroy后线程无法继续运行的问题,Service可以在后台默默执行自己的任务,而不用去计较activity状态的变化,从程序来看StartService也只是相当于一个开关的作用,相当于activity通过发送一条命令告诉service你可以去执行某个任务,activity不能直接去调用service内部提供的接口,这显然是不够的,bind函数提供了activity去调用service内部接口的方法。

bind service首先应该通过一个binder 为基类的派生类,在里面可以定义向activity暴露的接口,然后重新onbinder函数,在onbinder函数内向activity返回在service定义的binder派生类

package com.example.android.test;

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

public class MainActivityService extends Service{
	public static final String TAG = "MyService";
	private MyBinder mBinder = new MyBinder();
	
	class MyBinder extends Binder {
		public void privateService() {
			Log.e(TAG, "runnging in background");
			new Thread(new Runnable() {
				
				@Override
				public void run() {
					while(true) {
						// TODO Auto-generated method stub
						Log.e(TAG, "create by binder");
						try {
							Thread.sleep(1000);
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
				}
			}).start();
		}
	}
	
	/*bindservice时会通过该重载函数将service类的成员暴露给activity*/
	@Override
	public IBinder onBind(Intent arg0) {
		// TODO Auto-generated method stub
		return mBinder;
	}
}
           

在activity类内,需要定义一个ServiceConnetion变量,通过传入的参数启动或停止service提供特定服务,代码如下

/*serviceConnection 类提供了访问server的状态,通过serverConnection可以控制Server启动或停止某些任务
	 * 和其他的回调函数一样,这个类被应用程序的主线程调用*/
	private ServiceConnection mServiceConnection = new ServiceConnection() {
		
		@Override
		public void onServiceDisconnected(ComponentName name) {
			// TODO Auto-generated method stub
			
		}
		
		/*bindService成功后会调用这个函数,IBinder service就是在MainActivityService中返回的MyBinder类*/
		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			// TODO Auto-generated method stub
			myBinder = (MainActivityService.MyBinder) service;
			myBinder.privateService();
		}
	};
           

最后在activity内,通过调用bind, unbind实现启动或停止service的某些服务。

package com.example.android.test;
import android.os.Bundle;
import android.os.IBinder;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ComponentName;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity implements OnClickListener{
	Button StartService;
	Button StopService;
	
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		BindService = (Button) findViewById(R.id.bindService);
		UnBindService = (Button) findViewById(R.id.unbindService);
		
		BindService.setOnClickListener(this);
		UnBindService.setOnClickListener(this);
	}
	
	/*当发生单击事件时,android会回调该函数*/
	@Override
	public void onClick(View v) {
		
		switch(v.getId()) {
		/*绑定一个服务,执行bindService时,将会在service类中将绑定的类返回给回调类mServiceConneciton,
		 * 也就是将Service类中的一些接口暴露给了activity, 实现activity对Service的控制*/
		case (R.id.bindService) :
			Log.e(TAG, "bindService is clicked");
			Intent bindIntent = new Intent(this, MainActivityService.class);
			bindService(bindIntent, mServiceConnection, BIND_AUTO_CREATE);
			break;
		/*解除绑定,首先会调用mServiceConnetion中的onServiceDisconnected重载函数,只有unbinderService, stopservice
		 * 同时执行时,才会调用Service类中的onDestory重载函数*/
		case (R.id.unbindService) :
			Log.e(TAG, "unbindService is clicked");
			unbindService(mServiceConnection);
		default :
			break;
		}
	}
}
           

下图为service的声明周期,当用户直接bindService也能导致service的create, 但不会执行onStartCommand函数,需要支持,当StartService与bindService同时执行时,只有当stopService与unbindService都被执行后,Service才能执行ondestory函数完成对service的销毁。

android service 介绍