Android之使用NotificationListenerService使得自己的应用不被杀及其源码分析
2016-08-22 20:12
726 查看
使用NotificationListenerService需要用户手动授权,该服务主要是获取系统通知的相关信息,这里只分析应用为什么不会被杀,使用通知内容这里不做分析。
NotificationListenerService的使用需要三步:
1.写一个类继承NotificationListenerService:
2.在AndroidManifest.xml中注册该服务并声明相关权限:
3.开启监听通知的功能:
这一步需要用户手动授权,在“Settings” > “Security” > “Notification access”中,引导用户勾选自己的应用程序。此时服务连接成功、收到通知时就会有相应的log打出了。设置界面并不好找,所以可以在代码中帮助用户跳转到设置界面,如果服务没有被授权则跳转到设置界面:
到这里,只要用户授权,你的应用程序就不会被杀了。很简单吧,下面分析为什么不会被杀:
先看下NotificationListenerService服务的启动,总共就三种启动该服务的途径,分别是接收到PACKAGE相关的广播(安装、更新、卸载等)触发启动、多用户之间的切换触发启动、数据库变化触发启动。
接收到PACKAGE相关的广播触发启动:
开机时,会进行NotificationManagerService服务的初始化操作:
下面看下ManagedServices类的onPackagesChanged方法:
到这里,服务就启动起来了。
多用户之间的切换触发启动:
数据库变化触发启动:
到这里三种触发启动的方式都分析完了,但是好像还看不出应用为什么不会被杀。
系统杀应用的两种方式:killApplicationProcess和forceStopPackage
上面两种方法都是系统方法,故需要使用Binder代理对象和反射的方法来调用:
上面只是介绍了两种方法的使用方式,下面具体分析下两种方式的区别,这两个方法的具体实现都是在ActivityManagerService类中:
通过Binder代理对象最后调用到ActivityThread类中内部类ApplicationThread类的scheduleSuicide方法:
下面看下Process类的killProcess方法:
kill杀应用时,系统会调用ActiveServices类的killServicesLocked(ProcessRecord app, boolean allowRestart)方法,允许服务重启,即服务杀不死。
下面分析forceStopPackage方法:
到这里终于知道应用为什么杀不死了,因为forceStop杀死应用后会发送PACKAGE相关的广播,而接收到这个广播后NotificationManagerService又会重新启动所有用户授权的服务,故实现了NotificationListenerService服务的Service是杀不死的。
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是杀不死的。
相关文章推荐
- Android中IntentService源码分析及其使用
- 【Android应用源码分析】IntentService 源码分析
- [Android Pro] Android 4.3 NotificationListenerService使用详解
- Android 4.4 KitKat NotificationManagerService使用详解与原理分析(二)__原理分析
- Android 4.4 KitKat NotificationManagerService使用详解与原理分析(二)__原理分析
- Android 通过系统使用NotificationListenerService 监听各种Notification的使用方法
- Android 4.4 KitKat NotificationManagerService使用详解与原理分析(一)__使用详解
- Android开发:IntentService使用(源码分析)
- Android 4.4 KitKat NotificationManagerService使用详解与原理分析(二)__原理分析
- Android N NotificationManagerService源码分析
- Android 通过系统使用NotificationListenerService 监听各种Notification的使用方法
- Android 通过系统使用NotificationListenerService 监听各种Notification的用法
- Android 通过系统使用NotificationListenerService 监听各种Notification的使用方法
- Android 4.4 KitKat NotificationManagerService使用详解与原理分析
- Android IntentService的使用和源码分析
- Android 4.4 KitKat NotificationManagerService使用详解与原理分析(二)__原理分析
- Android 4.4 KitKat NotificationManagerService使用详解与原理分析(一)__使用详解
- Android 4.4 NotificationManagerService使用详解与原理分析(二)__原理分析
- Android 4.4 KitKat NotificationManagerService使用详解与原理分析(一)__使用详解
- 使用eclipse跟踪调试Android源码及其.classpath的作用分析