前言
最近使用客戶的launcher設置音量時,會彈出一個界面,用於授權,用於給【勿擾模式】進行授權。
授權界面的源碼
通過adb shell 指令獲取當前的包名和界面,發現顯示如下:
com.android.Settings.Settings$ZenAccessSettingsActivity
明顯界面已經跳轉到了原生setting app,一番搜索,該界面的實現源碼如下:
packages/apps/Settings/src/com/android/settings/notification/ZenAccessSettings.java
在這裏,主要通過如下方法獲取所有需要勿擾權限的app:
private void reloadList() {
final PreferenceScreen screen = getPreferenceScreen();
screen.removeAll();
final ArrayList<ApplicationInfo> apps = new ArrayList<>();
final ArraySet<String> requesting = getPackagesRequestingNotificationPolicyAccess();
if (!requesting.isEmpty()) {
final List<ApplicationInfo> installed = mPkgMan.getInstalledApplications(0);
if (installed != null) {
for (ApplicationInfo app : installed) {
if (requesting.contains(app.packageName)) {
apps.add(app);
}
}
}
}
ArraySet<String> autoApproved = new ArraySet<>();
autoApproved.addAll(mNoMan.getEnabledNotificationListenerPackages());
requesting.addAll(autoApproved);
Collections.sort(apps, new PackageItemInfo.DisplayNameComparator(mPkgMan));
for (ApplicationInfo app : apps) {
final String pkg = app.packageName;
final CharSequence label = app.loadLabel(mPkgMan);
final SwitchPreference pref = new AppSwitchPreference(getPrefContext());
pref.setKey(pkg);
pref.setPersistent(false);
pref.setIcon(app.loadIcon(mPkgMan));
pref.setTitle(label);
pref.setChecked(hasAccess(pkg));
if (autoApproved.contains(pkg)) {
pref.setEnabled(false);
pref.setSummary(getString(R.string.zen_access_disabled_package_warning));
}
pref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
final boolean access = (Boolean) newValue;
if (access) {
new ScaryWarningDialogFragment()
.setPkgInfo(pkg, label)
.show(getFragmentManager(), "dialog");
} else {
new FriendlyWarningDialogFragment()
.setPkgInfo(pkg, label)
.show(getFragmentManager(), "dialog");
}
return false;
}
});
screen.addPreference(pref);
}
}
這裏可以獲取到所有需要授權的app,接着需要用戶去點擊開關進行授權,這裏授權的主要方法如下:
private static void setAccess(final Context context, final String pkg, final boolean access) {
logSpecialPermissionChange(access, pkg, context);
AsyncTask.execute(new Runnable() {
@Override
public void run() {
final NotificationManager mgr = context.getSystemService(NotificationManager.class);
mgr.setNotificationPolicyAccessGranted(pkg, access);
}
});
}
該方法的關鍵實現是如下函數:
mgr.setNotificationPolicyAccessGranted(pkg, access);
通過搜索發現,mgr定義如下“
final NotificationManager mgr = context.getSystemService(NotificationManager.class);
這麼看來,想要不彈出授權界面,在系統起來的時候,給該應用進行授權即可。這次選擇在自己開發的系統服務中進行授權;
final NotificationManager mgr = context.getSystemService(NotificationManager.class);
mgr.setNotificationPolicyAccessGranted(pkg, access);
到此可解決該問題。
需要注意的是,應用需要先在AndroidManifest.xml中申請如下權限:
android.permission.ACCESS_NOTIFICATION_POLICY