前言
最近使用客户的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