当前位置: 代码迷 >> Android >> Android Service的知识点收拾
  详细解决方案

Android Service的知识点收拾

热度:60   发布时间:2016-05-01 17:51:21.0
Android Service的知识点整理

一、Service

	Service是一个在后台长期运行的应用组件,适用于IPC调用,当用于从当前app切换到别的app时service依然能跑在后台。当start一个service时,它马上跑起来,即使启动它的那个组件已经被销毁。如果bound一个service时,servcie是允许众多其他组件绑定它,只有当所有的client反绑定。unbind()之后才会destroy。

servcie可以像activity一样只允许当前的app使用,这需要在androidManifest.xml中声明。

*Caution:  Service试运行在进程的主线程中(main thread),如果需要service去做一些高占用CPU或者堵塞的操作,那么应该新建线程去处理。

二、Service的分类

(1)LocalService

(2)RemoteService

三、如何添加并使用一个服务

(1)继承Service

(2)继承IntentService,

这是Service的一个子类。继承该类后,工作比较省事,只需要实现 onHandleIntent() 方法即可,且不用担心堵塞的问题,因为该类实现了多线程操作。如果要实现Service别的方法,那么一定要调用父类的方法。

四、start service 与 bind service是有区别的。

bind service可以获取一个返回的IBinder对象用于操作remoet service的方法。当不需要绑定服务时,unbindService().当其他的组件通过startService()启动服务时,系统会调用onStartCommand(),当service的工作结束时,程序员有责任去调用stopSelf()或者stopService(),但如果这个服务还提供绑定的话, 就不需要这么做。

当client调用bindService()时,系统会调用服务的onBind()方法,如果实现了该接口,那么应该返回一个IBinder变量给client用来通信。当服务第一次被创建时调用onCreate()。当服务不在被使用时,它会被销毁,因此系统调用onDestroy(),程序员应该在这里做一些资源与线程的释放工作。系统在低内存的时候,回去终止服务,如果这个服务被一个焦点的activity绑定,那么它被终止的肯能行会小很多,如果服务声明了运行在前台,那么它将不会被终止。 

系统终止服务后,也会将一些服务重启,这个取决于onStartCommand()的值

五、终止service服务本身应该终止自己,推荐使用stopSelf(int),int值是onStartCommand()得到的startId,如果调用stopSelf(int)时,这个int值与startId不同,那么就不能销毁成功。因为每次bind服务的时候都会call onStartCommand(),而startId也不同。

如果是client的话,也需要有一个不使用服务的时候终止连接,stopService。

六、两个需要重视的方法

*public int onStartCommand (Intent intent, int flags, int startId)这是一个很重要的方法,当client调用startService的时候,系统会调用该方法。这个return的int值是给系统用的。比如return Service.START_STICKY;那么就是明确地告诉系统,如果不是主动stop这个service,那么是不想被系统终止的。

*public final void startForeground (int id, Notification notification)

这个方法可以让service处于前台且不被kill掉。

七、Service的生命周期图

\

八、Demo

(1) 实现一个aidl文件

*这时的gen里边会自动生成一个xxxservice文件

package com.bootoption;import java.util.List;interface IBootOptionService {		List getOriginalBlackList();	List getBlackList();	void setBlackList(in List list);}

(2)实现Service

*,关键是要实现继承与aidl中stub的子类

package com.bootoption;import java.util.List;import android.app.Service;import android.content.Intent;import android.content.pm.PackageManager;import android.os.IBinder;import android.os.RemoteException;import android.util.Log;public class BootOptionService extends Service {	static final String TAG = "bootOption";		private InnerObject innerBinder = new InnerObject();		class InnerObject extends IBootOptionService.Stub {		public List getOriginalBlackList() throws RemoteException {			Log.v(TAG, "getOriginalBlackList");						PackageManager pmg = BootOptionService.this.getPackageManager();			Intent intent = new Intent(Intent.ACTION_BOOT_COMPLETED);						return pmg.queryBroadcastReceivers(intent, PackageManager.GET_RESOLVED_FILTER);		}		public List getBlackList() throws RemoteException {			Log.v(TAG, "getBlackList");			return null;		}		public void setBlackList(List list) throws RemoteException {			Log.v(TAG, "setBlackList");					}			}		@Override	public IBinder onBind(Intent arg0) {		Log.v(TAG, "onBind");				return innerBinder;	}		@Override	public int onStartCommand(Intent intent, int flags, int startId) {		Log.v(TAG, "onStartCommand");						super.onStartCommand(intent, flags, startId);				return Service.START_STICKY;	}}

(3)本地调用

* 重点是实现 

ServiceConnection 

package com.bootoption;import java.util.List;import com.bootoption.IBootOptionService.Stub;import android.app.Activity;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.content.ServiceConnection;import android.content.pm.ApplicationInfo;import android.content.pm.PackageManager;import android.content.pm.PackageManager.NameNotFoundException;import android.content.pm.ResolveInfo;import android.os.Bundle;import android.os.IBinder;import android.os.RemoteException;import android.util.Log;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.TextView;public class BootOptionManagerActivity extends Activity {    	static final String TAG = "bootOption";	private TextView tv = null;	private Button bt = null;		private IBootOptionService.Stub bos = null;		private ServiceConnection conn = new ServiceConnection() {		boolean bConnect = false;				public void onServiceConnected(ComponentName name, IBinder service) {			if (bConnect) {				bos = null;			}			bos = (IBootOptionService.Stub)service;						bConnect = true;		}		public void onServiceDisconnected(ComponentName name) {			if (bConnect) {				bos = null;				bConnect = false;			}					}			};	    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);                tv = (TextView)findViewById(R.id.text);        bt = (Button)findViewById(R.id.bt);        bt.setOnClickListener(new OnClickListener() {						public void onClick(View v) {				BootOptionManagerActivity.this.sendBroadcast(new Intent("android.intent.action.test"));				if (bos != null) {					try {						List list = bos.getOriginalBlackList();												Log.v(TAG, "bos is " + bos + ",list is " + list);												for (int i = 0; i < list.size(); i++) {							ResolveInfo ri = (ResolveInfo) list.get(i);							Log.v(TAG, "==> " + ri.toString());														PackageManager pm = BootOptionManagerActivity.this.getPackageManager();							try {								ApplicationInfo appInfo = 										pm.getApplicationInfo(ri.activityInfo.packageName, PackageManager.GET_UNINSTALLED_PACKAGES);								Log.v(TAG, "*" + appInfo.publicSourceDir);							} catch (NameNotFoundException e) {								// TODO Auto-generated catch block								e.printStackTrace();							}						}											} catch (RemoteException e) {						// TODO Auto-generated catch block						e.printStackTrace();					}				} else {					Log.w(TAG, "bos is null");				}			}		});                Intent service = new Intent("android.intent.action.bootoption.service");        this.bindService(service, conn, Context.BIND_AUTO_CREATE);    }	@Override	protected void onResume() {				super.onResume();	}		        }

(4)远程调用

*将(1)中gen生成的xxxservice拿到远程调用的代码中

*注意包名

package com.my.app;import com.bootoption.*;import android.app.Activity;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.content.ServiceConnection;import android.content.res.Configuration;import android.os.Bundle;import android.os.IBinder;import android.os.RemoteException;import android.util.Log;public class ACTActivity extends Activity {		static final String TAG = "RemoteService";	    /** Called when the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);                this.bindService(new Intent("android.intent.action.bootoption.service"), sc, Context.BIND_AUTO_CREATE);    }                	@Override	public void onConfigurationChanged(Configuration newConfig) {		// TODO Auto-generated method stub		super.onConfigurationChanged(newConfig);				Log.v(TAG, "configuration change");	}	IBootOptionService is = null;        ServiceConnection sc = new ServiceConnection() {				public void onServiceDisconnected(ComponentName name) {			// TODO Auto-generated method stub			Log.v(TAG, "onServiceDisconnected");			is = null;		}				public void onServiceConnected(ComponentName name, IBinder service) {			// TODO Auto-generated method stub			Log.v(TAG, "onServiceConnected");			//is = (IBootOptionService.Stub)service;			is = IBootOptionService.Stub.asInterface(service);						if (is != null) {				try {					is.setBlackList(null);				} catch (RemoteException e) {					// TODO Auto-generated catch block					e.printStackTrace();				}			}		}	};}

(5)总结,本地调用与远程调用的实现区别就在于:

*本地调用时,在onServiceConnected方法中是这样的:

private IBootOptionService.Stub bos = null;

......

bos = (IBootOptionService.Stub)service;

*远程调用时,在onServiceConnected方法中是这样的:

IBootOptionService is = null;

......

is = IBootOptionService.Stub.asInterface(service);

  相关解决方案