使用NotificationListenerService需要用户手动授权,该服务主要是获取系统通知的相关信息,这里只分析应用为什么不会被杀,使用通知内容这里不做分析。
NotificationListenerService的使用需要三步:
1.写一个类继承NotificationListenerService:
public class NotificationService extends NotificationListenerService {
@Override
public void onListenerConnected() {
System.out.println("zyf onListenerConnected");
super.onListenerConnected();
}
@Override
public void onNotificationPosted(StatusBarNotification sbn) {
System.out.println("zyf onNotificationPosted");
super.onNotificationPosted(sbn);
}
}
2.在AndroidManifest.xml中注册该服务并声明相关权限:
<service
android:name="com.example.notification.NotificationService"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" >
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
3.开启监听通知的功能:
这一步需要用户手动授权,在“Settings” > “Security” > “Notification access”中,引导用户勾选自己的应用程序。此时服务连接成功、收到通知时就会有相应的log打出了。设置界面并不好找,所以可以在代码中帮助用户跳转到设置界面,如果服务没有被授权则跳转到设置界面:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String string = Settings.Secure.getString(getContentResolver(),
"enabled_notification_listeners");
System.out.println("zyf 已经允许使用通知权的应用:" + string);
// 数据库中保存的格式:包名/服务名:包名/服务名,如:
// com.example.notification/com.example.notification.NotificationService
// :com.example.smartface/com.example.smartface.notification.SmartFaceListenerService
if (!string.contains(NotificationService.class.getName())) {
startActivity(new Intent(
"android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"));
}
}
}
到这里,只要用户授权,你的应用程序就不会被杀了。很简单吧,下面分析为什么不会被杀:
先看下NotificationListenerService服务的启动,总共就三种启动该服务的途径,分别是接收到PACKAGE相关的广播(安装、更新、卸载等)触发启动、多用户之间的切换触发启动、数据库变化触发启动。
接收到PACKAGE相关的广播触发启动:
开机时,会进行NotificationManagerService服务的初始化操作:
public NotificationManagerService(Context context) {
super(context);
}
@Override
public void onStart() {
. . .
// 初始化NotificationListeners,它是ManagedServices的子类
mListeners = new NotificationListeners();
. . .
// 注册接收PACKAGE相关的广播
IntentFilter pkgFilter = new IntentFilter();
pkgFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
pkgFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
pkgFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
pkgFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
pkgFilter.addDataScheme("package");
getContext().registerReceiverAsUser(mPackageIntentReceiver, UserHandle.ALL, pkgFilter, null,
null);
. . .
// 发布服务到系统
publishBinderService(Context.NOTIFICATION_SERVICE, mService);
. . .
}
// 接收PACKAGE相关的广播
private final BroadcastReceiver mPackageIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action == null) {
return;
}
. . .
if (action.equals(Intent.ACTION_PACKAGE_ADDED)
|| (queryRemove=action.equals(Intent.ACTION_PACKAGE_REMOVED))
|| action.equals(Intent.ACTION_PACKAGE_RESTARTED)
|| (packageChanged=action.equals(Intent.ACTION_PACKAGE_CHANGED))
|| (queryRestart=action.equals(Intent.ACTION_QUERY_PACKAGE_RESTART))
|| action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) {
. . .
// 接收到广播后回调mListeners的onPackagesChanged方法
mListeners.onPackagesChanged(queryReplace, pkgList);
. . .
}
}
};
下面看下ManagedServices类的onPackagesChanged方法:
public void onPackagesChanged(boolean queryReplace, String[] pkgList) {
if (DEBUG) Slog.d(TAG, "onPackagesChanged queryReplace=" + queryReplace
+ " pkgList=" + (pkgList == null ? null : Arrays.asList(pkgList))
+ " mEnabledServicesPackageNames=" + mEnabledServicesPackageNames);
boolean anyServicesInvolved = false;
if (pkgList != null && (pkgList.length > 0)) {
for (String pkgName : pkgList) {
// mEnabledServicesPackageNames中保存的是从数据库中查询到的经过用户授权的应用包名
if (mEnabledServicesPackageNames.contains(pkgName)) {
anyServicesInvolved = true;
}
}
}
if (anyServicesInvolved) {
// if we're not replacing a package, clean up orphaned bits
if (!queryReplace) {
disableNonexistentServices();
}
// 重新绑定所有经过授权的服务
rebindServices();
}
}
/**
* Called whenever packages change, the user switches, or the secure setting
* is altered. (For example in response to USER_SWITCHED in our broadcast receiver)
*/
// 重新绑定所有经过授权的服务
private void rebindServices() {
// 取出所有经过授权的服务
. . .
for (ManagedServiceInfo info : toRemove) {
final ComponentName component = info.component;
final int oldUser = info.userid;
Slog.v(TAG, "disabling " + getCaption() + " for user "
+ oldUser + ": " + component);
// 注销服务
unregisterService(component, info.userid);
}
for (int i = 0; i < nUserIds; ++i) {
final ArrayList<ComponentName> add = toAdd.get(userIds[i]);
final int N = add.size();
for (int j = 0; j < N; j++) {
final ComponentName component = add.get(j);
Slog.v(TAG, "enabling " + getCaption() + " for user " + userIds[i] + ": "
+ component);
// 根据组件名重新绑定服务
registerService(component, userIds[i]);
}
}
mLastSeenProfileIds = mUserProfiles.getCurrentProfileIds();
}
// 绑定服务
private void registerService(final ComponentName name, final int userid) {
if (DEBUG) Slog.v(TAG, "registerService: " + name + " u=" + userid);
synchronized (mMutex) {
. . .
Intent intent = new Intent(mConfig.serviceInterface);
intent.setComponent(name);
. . .
try {
if (DEBUG) Slog.v(TAG, "binding: " + intent);
// 绑定服务
if (!mContext.bindServiceAsUser(intent,
new ServiceConnection() {
IInterface mService;
@Override
public void onServiceConnected(ComponentName name, IBinder binder) {
boolean added = false;
ManagedServiceInfo info = null;
synchronized (mMutex) {
mServicesBinding.remove(servicesBindingTag);
try {
mService = asInterface(binder);
info = newServiceInfo(mService, name,
userid, false /*isSystem*/, this, targetSdkVersion);
binder.linkToDeath(info, 0);
added = mServices.add(info);
} catch (RemoteException e) {
// already dead
}
}
if (added) {
onServiceAdded(info);
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
Slog.v(TAG, getCaption() + " connection lost: " + name);
}
},
Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
new UserHandle(userid)))
{
mServicesBinding.remove(servicesBindingTag);
Slog.w(TAG, "Unable to bind " + getCaption() + " service: " + intent);
return;
}
} catch (SecurityException ex) {
Slog.e(TAG, "Unable to bind " + getCaption() + " service: " + intent, ex);
return;
}
}
}
到这里,服务就启动起来了。
多用户之间的切换触发启动:
// 用户切换
public void onUserSwitched(int user) {
if (DEBUG) Slog.d(TAG, "onUserSwitched u=" + user);
if (Arrays.equals(mLastSeenProfileIds, mUserProfiles.getCurrentProfileIds())) {
if (DEBUG) Slog.d(TAG, "Current profile IDs didn't change, skipping rebindServices().");
return;
}
// 重新绑定经过授权的服务
rebindServices();
}
数据库变化触发启动:
public ManagedServices(Context context, Handler handler, Object mutex,
UserProfiles userProfiles) {
. . .
mSettingsObserver = new SettingsObserver(handler);
. . .
}
// 手机启动后注册监听
public void onBootPhaseAppsCanStart() {
// 注册数据库监听
mSettingsObserver.observe();
}
// 监听数据库变化
private class SettingsObserver extends ContentObserver {
private final Uri mSecureSettingsUri = Settings.Secure.getUriFor(mConfig.secureSettingName);
private SettingsObserver(Handler handler) {
super(handler);
}
// 注册数据库监听
private void observe() {
ContentResolver resolver = mContext.getContentResolver();
resolver.registerContentObserver(mSecureSettingsUri,
false, this, UserHandle.USER_ALL);
update(null);
}
@Override
public void onChange(boolean selfChange, Uri uri) {
update(uri);
}
private void update(Uri uri) {
if (uri == null || mSecureSettingsUri.equals(uri)) {
if (DEBUG) Slog.d(TAG, "Setting changed: mSecureSettingsUri=" + mSecureSettingsUri +
" / uri=" + uri);
// 数据库变化时重新绑定所有授权的服务
rebindServices();
}
}
}
到这里三种触发启动的方式都分析完了,但是好像还看不出应用为什么不会被杀。
系统杀应用的两种方式:killApplicationProcess和forceStopPackage
上面两种方法都是系统方法,故需要使用Binder代理对象和反射的方法来调用:
public class KillForceStopManager {
private Method mKill;
private Method mForceStop;
private Object mActivityManagerNative;
public KillForceStopManager() {
try {
Method getDefault = Class.forName(
"android.app.ActivityManagerNative").getDeclaredMethod(
"getDefault", new Class[] {});
mActivityManagerNative = getDefault.invoke(null, new Object[] {});
mKill = mActivityManagerNative.getClass().getDeclaredMethod(
"killApplicationProcess", String.class, int.class);
mForceStop = mActivityManagerNative.getClass().getDeclaredMethod(
"forceStopPackage", String.class);
} catch (Exception e) {
e.printStackTrace();
}
}
// 只有系统应用才有kill的权限,故这里传递的uid是1000
public void killApplicationProcess(String processName) {
killApplicationProcess(processName, 1000);
}
private void killApplicationProcess(String processName, int processUid) {
if (mKill != null) {
try {
mKill.invoke(mActivityManagerNative, processName, processUid);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void forceStopPackage(String pkgName) {
if (mForceStop != null) {
try {
mForceStop.invoke(mActivityManagerNative, pkgName);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
上面只是介绍了两种方法的使用方式,下面具体分析下两种方式的区别,这两个方法的具体实现都是在ActivityManagerService类中:
@Override
public void killApplicationProcess(String processName, int uid) {
if (processName == null) {
return;
}
int callerUid = Binder.getCallingUid();
// 只有系统进程能kill应用程序
if (callerUid == Process.SYSTEM_UID) {
synchronized (this) {
// 根据进程名获取进程
ProcessRecord app = getProcessRecordLocked(processName, uid, true);
if (app != null && app.thread != null) {
try {
// 通过Binder对象调用scheduleSuicide方法执行自杀操作
app.thread.scheduleSuicide();
} catch (RemoteException e) {
// If the other end already died, then our work here is done.
}
} else {
Slog.w(TAG, "Process/uid not found attempting kill of "
+ processName + " / " + uid);
}
}
} else {
throw new SecurityException(callerUid + " cannot kill app process: " +
processName);
}
}
通过Binder代理对象最后调用到ActivityThread类中内部类ApplicationThread类的scheduleSuicide方法:
public final void scheduleSuicide() {
sendMessage(H.SUICIDE, null);
}
private class H extends Handler {
. . .
public static final int SUICIDE = 130;
. . .
public void handleMessage(Message msg) {
switch (msg.what) {
. . .
case SUICIDE:
Process.killProcess(Process.myPid());
break;
. . .
}
. . .
}
. . .
}
下面看下Process类的killProcess方法:
public static final int SIGNAL_KILL = 9;
public static final void killProcess(int pid) {
sendSignal(pid, SIGNAL_KILL);
}
public static final native void sendSignal(int pid, int signal);
kill杀应用时,系统会调用ActiveServices类的killServicesLocked(ProcessRecord app, boolean allowRestart)方法,允许服务重启,即服务杀不死。
下面分析forceStopPackage方法:
@Override
public void forceStopPackage(final String packageName, int userId) {
// forceStopPackage杀应用需要FORCE_STOP_PACKAGES权限
if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
!= PackageManager.PERMISSION_GRANTED) {
. . .
}
. . .
try {
IPackageManager pm = AppGlobals.getPackageManager();
synchronized(this) {
int[] users = userId == UserHandle.USER_ALL
? getUsersLocked() : new int[] { userId };
for (int user : users) {
. . .
try {
// 设置应用为停止运行状态,第一次安装应用时也调用过该方法
pm.setPackageStoppedState(packageName, true, user);
} catch (RemoteException e) {
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
+ packageName + ": " + e);
}
if (isUserRunningLocked(user, false)) {
// 杀应用后发送广播
forceStopPackageLocked(packageName, pkgUid, "from pid " + callingPid);
}
}
}
} finally {
Binder.restoreCallingIdentity(callingId);
}
}
// 杀应用后发送广播
private void forceStopPackageLocked(final String packageName, int uid, String reason) {
// 杀应用
forceStopPackageLocked(packageName, UserHandle.getAppId(uid), false,
false, true, false, false, UserHandle.getUserId(uid), reason);
// 创建Action为ACTION_PACKAGE_RESTARTED的intent
Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
Uri.fromParts("package", packageName, null));
if (!mProcessesReady) {
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
| Intent.FLAG_RECEIVER_FOREGROUND);
}
intent.putExtra(Intent.EXTRA_UID, uid);
intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(uid));
// 发送intent所描述的广播,广播的发送过程前面有文章已经分析过
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null, AppOpsManager.OP_NONE,
null, false, false, MY_PID, Process.SYSTEM_UID, UserHandle.getUserId(uid));
}
// 杀应用
private final boolean forceStopPackageLocked(String packageName, int appId,
boolean callerWillRestart, boolean purgeCache, boolean doit,
boolean evenPersistent, boolean uninstalling, int userId, String reason) {
. . .
// 杀应用进程
boolean didSomething = killPackageProcessesLocked(packageName, appId, userId,
-100, callerWillRestart, true, doit, evenPersistent,
packageName == null ? ("stop user " + userId) : ("stop " + packageName));
// 结束应用所有Activity
if (mStackSupervisor.finishDisabledPackageActivitiesLocked(
packageName, null, doit, evenPersistent, userId)) {
if (!doit) {
return true;
}
didSomething = true;
}
// 结束应用所有Service
if (mServices.bringDownDisabledPackageServicesLocked(
packageName, null, userId, evenPersistent, true, doit)) {
if (!doit) {
return true;
}
didSomething = true;
}
. . .
// 结束应用所有Provider
ArrayList<ContentProviderRecord> providers = new ArrayList<>();
if (mProviderMap.collectPackageProvidersLocked(packageName, null, doit, evenPersistent,
userId, providers)) {
if (!doit) {
return true;
}
didSomething = true;
}
for (i = providers.size() - 1; i >= 0; i--) {
removeDyingProviderLocked(null, providers.get(i), true);
}
// Remove transient permissions granted from/to this package/user
removeUriPermissionsForPackageLocked(packageName, userId, false);
// 结束应用所有广播
if (doit) {
for (i = mBroadcastQueues.length - 1; i >= 0; i--) {
didSomething |= mBroadcastQueues[i].cleanupDisabledPackageReceiversLocked(
packageName, null, userId, doit);
}
}
. . .
return didSomething;
}
到这里终于知道应用为什么杀不死了,因为forceStop杀死应用后会发送PACKAGE相关的广播,而接收到这个广播后NotificationManagerService又会重新启动所有用户授权的服务,故实现了NotificationListenerService服务的Service是杀不死的。