Android Service使用方法

Service 包括bound Service和unbound Service.首先我们先讨论unBound Service使用方法。详细内容可参考官方dev guide

 

创建一个Service 有两种方式,一是继承IntentService,或者继承Service。

 

一,unbound service(未绑定activity,service执行完任务后要自己停止,stopself 或者stopservice)

 

1、IntentSerivce

 

IntentService 是Service的一个子类,操作上是单线程的。当Intent  Start 这个IntentService时,IntentService会自动执行onHandleIntent(Intent intent)里面的方法。IntentService对于每一个请求会创建一个工作线程进行处理,处理完成

后结束工作。对于不要求多线程,同步的程序,IntentService使用起来比较方便。把dev guide里面的例子拿过来。

 

 

public class HelloIntentService extends IntentService {

  /** 
   * A constructor is required, and must call the super IntentService(String)
   * constructor with a name for the worker thread.
   */
  public HelloIntentService() {
      super("HelloIntentService");
  }

  /**
   * The IntentService calls this method from the default worker thread with
   * the intent that started the service. When this method returns, IntentService
   * stops the service, as appropriate.
   */
  @Override
  protected void onHandleIntent(Intent intent) {
      // Normally we would do some work here, like download a file.
      // For our sample, we just sleep for 5 seconds.
      long endTime = System.currentTimeMillis() + 5*1000;
      while (System.currentTimeMillis() < endTime) {
          synchronized (this) {
              try {
                  wait(endTime - System.currentTimeMillis());
              } catch (Exception e) {
              }
          }
      }
  }
}

 IntentService实际上是在Service上面添加了消息循环,Intent和IntentService的生命周期一致,所以每次处理请求是都会new 一个Thread进行处理工作,可以查看源码,参考博客地址http://android.blog.51cto.com/268543/528166,上面源码分析的很详细。

 

2、Service,如要程序要求同步,多线程,可以选择继承Service,这里需要自己手动写消息循环。Handler,loop。之参考dev guide 上面的例子,这个例子与上面的IntentService效果一致,一次只能助理一个请求。

 

 

public class HelloService extends Service {
  private Looper mServiceLooper;
  private ServiceHandler mServiceHandler;

  // Handler that receives messages from the thread
  private final class ServiceHandler extends Handler {
      public ServiceHandler(Looper looper) {
          super(looper);
      }
      @Override
      public void handleMessage(Message msg) {
          // Normally we would do some work here, like download a file.
          // For our sample, we just sleep for 5 seconds.
          long endTime = System.currentTimeMillis() + 5*1000;
          while (System.currentTimeMillis() < endTime) {
              synchronized (this) {
                  try {
                      wait(endTime - System.currentTimeMillis());
                  } catch (Exception e) {
                  }
              }
          }
          // Stop the service using the startId, so that we don't stop
          // the service in the middle of handling another job
          stopSelf(msg.arg1);
      }
  }

  @Override
  public void onCreate() {
    // Start up the thread running the service.  Note that we create a
    // separate thread because the service normally runs in the process's
    // main thread, which we don't want to block.  We also make it
    // background priority so CPU-intensive work will not disrupt our UI.
    HandlerThread thread = new HandlerThread("ServiceStartArguments",
            Process.THREAD_PRIORITY_BACKGROUND);
    thread.start();
    
    // Get the HandlerThread's Looper and use it for our Handler 
    mServiceLooper = thread.getLooper();
    mServiceHandler = new ServiceHandler(mServiceLooper);
  }

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
      Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();

      // For each start request, send a message to start a job and deliver the
      // start ID so we know which request we're stopping when we finish the job
      Message msg = mServiceHandler.obtainMessage();
      msg.arg1 = startId;
      mServiceHandler.sendMessage(msg);
      
      // If we get killed, after returning from here, restart
      return START_STICKY;
  }

  @Override
  public IBinder onBind(Intent intent) {
      // We don't provide binding, so return null
      return null;
  }
  
  @Override
  public void onDestroy() {
    Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show(); 
  }
}

 

二、bound service

 

当Service 和activity绑定之后,直到所有的activity结束绑定后,service才结束,一个service可以被多个activity绑定,具体声明周期参考官网Dev Guide。

 bound service启动时通过其他Application(activity)调用 bindservice()方法启动,结束是用unbindSerivce();

在service中实现onbind(IBundler)方法,返回一个IBundler。通过IBundler与Activity进行信息交互IPC。这里需要定义一个接口用来传递Service中的方法和信息。原文如下:

 

To create a bound service, the first thing you must do is define the interface that specifies how a client can communicate with the service. This interface between the service and a client must be an implementation of IBinder and is what your service must return from the onBind() callback method. Once the client receives the IBinder, it can begin interacting with the service through that interface.

 

 

1、继承binder。在service类中写一个继承自binder的内部类,在此内部类中写一个获得该Service实例的公共方法,这样Activity绑定Service的时候可以拿到这个binder,进一步拿到Service的实例,调用Service的各种方法。注意,这种消息方式只在同一个应用内使用,如果Service是其他Application调用的,需要后面的方法。

参考DEV GUIDE 上面的例子如下

 

import java.util.Random;

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

public class LocalService extends Service{

	private LocalBinder mBinder = new LocalBinder();
	
	private Random mGenerator = new Random();
	
	@Override
	public IBinder onBind(Intent intent) {
		
		
		return mBinder;
	}

	public class LocalBinder extends Binder
	{
		public LocalService getLocalService()
		{
			return LocalService.this;
		}
	}
	
	public int getRandomNum()
	{
		return mGenerator.nextInt();
	}
	
}

 

 

 

import com.android.service.LocalService.LocalBinder;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import android.widget.Button;

public class LocalActivity extends Activity{
	
	private LocalService localService;
	
	boolean mBound = false;
	
	private ServiceConnection mConnection = new ServiceConnection() {
		
		@Override
		public void onServiceDisconnected(ComponentName name) {
			
			mBound = false;
			
		}
		
		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			LocalBinder localBinder = (LocalBinder) service;
		
			localService =  localBinder.getLocalService();
			
			mBound = true;
		}
	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		setContentView(R.layout.main);

		
	}
	
	@Override
	protected void onStop() {
		
		super.onStop();
		
		if(mBound)
		{
			unbindService(mConnection);
			
			mBound = false;
		}
		
	}
	
	@Override
	protected void onStart() {
	
		super.onStart();

		Intent intent = new Intent(this,LocalService.class);
		
		bindService(intent, mConnection , Context.BIND_AUTO_CREATE);
		
	}
	
	//点击button,onclick属性在xml中配置
	public void click(View v)
	{
		Button button = (Button) v;
		
		button.setText(String.valueOf(localService.getRandomNum()));
		
	}
	
}

2、使用Messenger。通过Messenger发送消息到服务端。主要分为以下几个步骤

1)在Service子类中创建一个Handler子类的(内部类的方式),写好handlmessage方法

2)用Handler的子类创建一个Messenger

3)返回Messenger.getBinder();获得bundler,在onbind();方法中返回给Activity

4)在Activity中获得Binder,用这个binder构造一个Messenger,使用这个Messenger 发送message

 

注意如果处理响应容易死掉的任务,如获取网络数据,Hander用一个Looper构造,创建一个Handler线程处理任务,

HandlerThread.start().   HandlerThread.getLooper();  这个Looper用来创建Handler

 

下面上代码,同样是参考DEV GUIDE  感觉本来做笔记,怎么写成一个翻译了- -!

 

 

 

 

import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.os.Process;
import android.widget.Toast;

public class MyMessager extends Service {

	Looper handlerLooper;

	static final int MSG_SAY_HELLO = 1;

	@Override
	public void onCreate() {

		super.onCreate();

		HandlerThread mHandlerThread = new HandlerThread("mHandlerThread",
				Process.THREAD_PRIORITY_BACKGROUND);

		mHandlerThread.start();

		handlerLooper = mHandlerThread.getLooper();

		mServiceMessager = new Messenger(new IncomingHander(handlerLooper));

	}

	@Override
	public IBinder onBind(Intent intent) {

		return mServiceMessager.getBinder();

	}

	class IncomingHander extends Handler {

		public IncomingHander(Looper looper) {
			super(looper);
		}

		@Override
		public void handleMessage(Message msg) {

			switch (msg.what) {

			case MSG_SAY_HELLO:

				Toast.makeText(getApplicationContext(), "hello",
						Toast.LENGTH_SHORT).show();

				System.out.println("hello runs");

				break;

			default:

				super.handleMessage(msg);
			}

		}
	}

	Messenger mServiceMessager;
}
 

 

 

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.view.View;
import android.widget.Button;

public class ActivityMessenger extends Activity{
	
	private Messenger mMessenger;
	
	private boolean mBound;

	private ServiceConnection conn = new ServiceConnection() {
		
		@Override
		public void onServiceDisconnected(ComponentName name) {
		
			mMessenger = null;
			
			mBound = false;
			
		}
		
		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			
			mMessenger = new Messenger(service);
			
			mBound = true;
			
		}
	};

	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		
		super.onCreate(savedInstanceState);
	
		setContentView(R.layout.main);
		
	}
	
	@Override
	protected void onStart() {
		super.onStart();
		
		
		Intent i  = new Intent(this,MyMessager.class);
		
		bindService(i, conn , Context.BIND_AUTO_CREATE);
	}
	
	public void click(View v)
	{
		Message msg = Message.obtain(null, MyMessager.MSG_SAY_HELLO, 0, 0);
		
		try {
			
			mMessenger.send(msg);
			
		} catch (RemoteException e) {
			
			e.printStackTrace();
		}
		
	}
		
	@Override
	protected void onStop() {
		
		super.onStop();
		
		unbindService(conn);
		
		mBound = false;
	}
}
 

 

 

 

三、通过AIDL进行多线程,跨进程通信。这个步骤相对麻烦,也没完全弄懂,以后补上

 

 

 

以上内容纯属个人学习笔记,技术有限,希望不会误导其他人

 

 

 

你可能感兴趣的:(android,通信,service,ipc)