当前位置: 代码迷 >> Android >> Android之通报使用权
  详细解决方案

Android之通报使用权

热度:113   发布时间:2016-04-24 11:30:23.0
Android之通知使用权

通知使用权打开方式

设置——提示音和通知——通知使用权。

详细界面如图:

存在需要拥有通知使用权应用时:

存在需要拥有通知使用权应用时:

用户为应用勾选复选框后系统弹dialog需要用户进一步确认时:

主要涉及文件:

/packages/apps/Settings/src/com/android/settings/notification/NotificationAccessSettings.java

 /packages/apps/Settings/src/com/android/settings/notification/ManagedServiceSettings.java

涉及数据库:

data/data/com.android.providers.settings

详细讲解:

/packages/apps/Settings/src/com/android/settings/notification/NotificationAccessSettings.java
public class NotificationAccessSettings extends ManagedServiceSettings {    private static final String TAG = NotificationAccessSettings.class.getSimpleName();    private static final Config CONFIG = getNotificationListenerConfig();    private static Config getNotificationListenerConfig() {        final Config c = new Config();        c.tag = TAG;        /*Settings.Secure.ENABLED_NOTIFICATION_LISTENERS =          *数据库字段,通过读取数据库中字段判断应用是否有通知使用权,有则界面中应用对应的checkbox为勾选状态,         *应用对应checkbox不勾选时,时用户勾选后会有提示框弹出,确定后通过此字段向数据库写入此应用信息。         * */        c.setting = Settings.Secure.ENABLED_NOTIFICATION_LISTENERS;        c.intentAction = NotificationListenerService.SERVICE_INTERFACE;        /*         * 应用需要在manifest文件中声明这个服务权限才会被检测到, 才会显示到同时使用权界面         * */        c.permission = android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE;        c.noun = "notification listener";        /*用户勾选后弹出的dialog中的标题*/        c.warningDialogTitle = R.string.notification_listener_security_warning_title;        /*用户勾选后弹出的dialog中的内容*/        c.warningDialogSummary = R.string.notification_listener_security_warning_summary;        /*当前系统中不存在任何需要使用通知使用权的应用时,通知使用权界面会有相应提示*/        c.emptyText = R.string.no_notification_listeners;        return c;    }    @Override    protected Config getConfig() {        return CONFIG;    }    public static int getListenersCount(PackageManager pm) {        return getServicesCount(CONFIG, pm);    }    public static int getEnabledListenersCount(Context context) {        return getEnabledServicesCount(CONFIG, context);    }}


/packages/apps/Settings/src/com/android/settings/notification/ManagedServiceSettings.java

public abstract class ManagedServiceSettings extends ListFragment {    private static final boolean SHOW_PACKAGE_NAME = false;    private final Config mConfig;    private PackageManager mPM;    private ContentResolver mCR;    private final HashSet<ComponentName> mEnabledServices = new HashSet<ComponentName>();    private ServiceListAdapter mListAdapter;    abstract protected Config getConfig();    public ManagedServiceSettings() {        mConfig = getConfig();    }    private final ContentObserver mSettingsObserver = new ContentObserver(new Handler()) {        @Override        public void onChange(boolean selfChange, Uri uri) {            updateList();        }    };    /*监听到应用的数量增减等改变时需要更新应用列表*/    private final BroadcastReceiver mPackageReceiver = new BroadcastReceiver() {        @Override        public void onReceive(Context context, Intent intent) {            updateList();        }    };    /*用户勾选后弹出对应dialog等待用户进一步确认要为此应用打开通知使用权*/    public class ScaryWarningDialogFragment extends DialogFragment {        static final String KEY_COMPONENT = "c";        static final String KEY_LABEL = "l";        public ScaryWarningDialogFragment setServiceInfo(ComponentName cn, String label) {            Bundle args = new Bundle();            args.putString(KEY_COMPONENT, cn.flattenToString());            args.putString(KEY_LABEL, label);            setArguments(args);            return this;        }        @Override        public Dialog onCreateDialog(Bundle savedInstanceState) {            super.onCreate(savedInstanceState);            final Bundle args = getArguments();            final String label = args.getString(KEY_LABEL);            final ComponentName cn = ComponentName.unflattenFromString(args.getString(KEY_COMPONENT));            final String title = getResources().getString(mConfig.warningDialogTitle, label);            final String summary = getResources().getString(mConfig.warningDialogSummary, label);            return new AlertDialog.Builder(getActivity())                    .setMessage(summary)                    .setTitle(title)                    .setCancelable(true)                    .setPositiveButton(android.R.string.ok,//                            new DialogInterface.OnClickListener() {                                public void onClick(DialogInterface dialog, int id) {                                    mEnabledServices.add(cn);//添加应用信息到HashSet<ComponentName>中                                    saveEnabledServices();//数据库写操作                                }                            })                    .setNegativeButton(android.R.string.cancel,                            new DialogInterface.OnClickListener() {                                public void onClick(DialogInterface dialog, int id) {                                    // pass                                }                            })                    .create();        }    }    @Override    public void onCreate(Bundle icicle) {        super.onCreate(icicle);        mPM = getActivity().getPackageManager();        mCR = getActivity().getContentResolver();        mListAdapter = new ServiceListAdapter(getActivity());    }    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container,            Bundle savedInstanceState) {        View v =  inflater.inflate(R.layout.managed_service_settings, container, false);        TextView empty = (TextView) v.findViewById(android.R.id.empty);        empty.setText(mConfig.emptyText);        return v;    }    @Override    public void onResume() {        super.onResume();        updateList();        // listen for package changes        IntentFilter filter = new IntentFilter();        filter.addAction(Intent.ACTION_PACKAGE_ADDED);//应用添加        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);//应用改变        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);//应用卸载        filter.addAction(Intent.ACTION_PACKAGE_REPLACED);//应用更新        filter.addDataScheme("package");        getActivity().registerReceiver(mPackageReceiver, filter);        mCR.registerContentObserver(Settings.Secure.getUriFor(mConfig.setting),                false, mSettingsObserver);    }    @Override    public void onPause() {        super.onPause();        getActivity().unregisterReceiver(mPackageReceiver);        mCR.unregisterContentObserver(mSettingsObserver);    }        /*从数据库中加载拥有通知使用权的应用,并将其信息存入到HashSet<ComponentName>中。*/    private void loadEnabledServices() {        mEnabledServices.clear();//首先清空HashSet<ComponentName>,确保数据最新从数据库读取        final String flat = Settings.Secure.getString(mCR, mConfig.setting);//数据库读操作        if (flat != null && !"".equals(flat)) {            final String[] names = flat.split(":");            for (int i = 0; i < names.length; i++) {                final ComponentName cn = ComponentName.unflattenFromString(names[i]);                if (cn != null) {                    mEnabledServices.add(cn);                }            }        }    }    /*数据库存操作*/    private void saveEnabledServices() {        StringBuilder sb = null;        for (ComponentName cn : mEnabledServices) {            if (sb == null) {                sb = new StringBuilder();            } else {                sb.append(':');            }            sb.append(cn.flattenToString());        }        /*数据库存操作*/        Settings.Secure.putString(mCR,                mConfig.setting,                sb != null ? sb.toString() : "");    }    /*更新应用显示列表*/    private void updateList() {        loadEnabledServices();        getServices(mConfig, mListAdapter, mPM);        mListAdapter.sort(new PackageItemInfo.DisplayNameComparator(mPM));        getListView().setAdapter(mListAdapter);    }    protected static int getEnabledServicesCount(Config config, Context context) {        final String flat = Settings.Secure.getString(context.getContentResolver(), config.setting);        if (flat == null || "".equals(flat)) return 0;        final String[] components = flat.split(":");        return components.length;    }    protected static int getServicesCount(Config c, PackageManager pm) {        return getServices(c, null, pm);    }    private static int getServices(Config c, ArrayAdapter<ServiceInfo> adapter, PackageManager pm) {        int services = 0;        if (adapter != null) {            adapter.clear();        }        final int user = ActivityManager.getCurrentUser();        List<ResolveInfo> installedServices = pm.queryIntentServicesAsUser(                new Intent(c.intentAction),                PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,                user);        for (int i = 0, count = installedServices.size(); i < count; i++) {            ResolveInfo resolveInfo = installedServices.get(i);            ServiceInfo info = resolveInfo.serviceInfo;            if (!c.permission.equals(info.permission)) {                Slog.w(c.tag, "Skipping " + c.noun + " service "                        + info.packageName + "/" + info.name                        + ": it does not require the permission "                        + c.permission);                continue;            }            if (adapter != null) {                adapter.add(info);            }            services++;        }        return services;    }    private boolean isServiceEnabled(ServiceInfo info) {        final ComponentName cn = new ComponentName(info.packageName, info.name);        return mEnabledServices.contains(cn);    }    @Override    public void onListItemClick(ListView l, View v, int position, long id) {        ServiceInfo info = mListAdapter.getItem(position);        final ComponentName cn = new ComponentName(info.packageName, info.name);        if (mEnabledServices.contains(cn)) {        	//取消勾选            // the simple version: disabling            mEnabledServices.remove(cn);            saveEnabledServices();        } else {        	//选择勾选后填出dialog            // show a scary dialog            new ScaryWarningDialogFragment()                .setServiceInfo(cn, info.loadLabel(mPM).toString())                .show(getFragmentManager(), "dialog");        }    }    private static class ViewHolder {        ImageView icon;        TextView name;        CheckBox checkbox;        TextView description;    }        /*用于应用列表加载显示*/    private class ServiceListAdapter extends ArrayAdapter<ServiceInfo> {        final LayoutInflater mInflater;        ServiceListAdapter(Context context) {            super(context, 0, 0);            mInflater = (LayoutInflater)                    getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);        }        public boolean hasStableIds() {            return true;        }        public long getItemId(int position) {            return position;        }        public View getView(int position, View convertView, ViewGroup parent) {            View v;            if (convertView == null) {                v = newView(parent);            } else {                v = convertView;            }            bindView(v, position);            return v;        }        public View newView(ViewGroup parent) {            View v = mInflater.inflate(R.layout.managed_service_item, parent, false);            ViewHolder h = new ViewHolder();            h.icon = (ImageView) v.findViewById(R.id.icon);//应用图标            h.name = (TextView) v.findViewById(R.id.name);//应用名            h.checkbox = (CheckBox) v.findViewById(R.id.checkbox);//勾选框            h.description = (TextView) v.findViewById(R.id.description);//应用描述            v.setTag(h);            return v;        }        public void bindView(View view, int position) {            ViewHolder vh = (ViewHolder) view.getTag();            ServiceInfo info = getItem(position);            vh.icon.setImageDrawable(info.loadIcon(mPM));            vh.name.setText(info.loadLabel(mPM));            if (SHOW_PACKAGE_NAME) {                vh.description.setText(info.packageName);                vh.description.setVisibility(View.VISIBLE);            } else {                vh.description.setVisibility(View.GONE);            }            vh.checkbox.setChecked(isServiceEnabled(info));        }    }    protected static class Config {        String tag;        String setting;        String intentAction;        String permission;        String noun;        int warningDialogTitle;        int warningDialogSummary;        int emptyText;    }<p>}</p>

数据库相关信息

数据库字段对应应用信息格式:包名/service:包名/service。两应用间信息用”:“隔开。

  相关解决方案