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);

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值