欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android9.0勿扰模式【Do Not Disturb】

程序员文章站 2022-06-05 15:58:12
...

前言

最近使用客户的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
相关标签: Android系统