Android之通知使用權

來源:互聯網
上載者:User

標籤:tor   names   klist   manage   卸載   positive   not   eset   最新   

通知使用權開啟檔案

設定——提示音和通知——通知使用權。

具體介面

存在須要擁有通知使用權應用時:

不存在須要擁有通知使用權應用時:

使用者為應用勾選複選框後系統彈dialog須要使用者進一步確認時:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" />

主要涉及檔案:

/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>

資料庫相關資訊

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" />

資料庫欄位相應應用資訊格式:包名/service:包名/service。兩應用間資訊用”:“隔開。

Android之通知使用權

相關文章

Beyond APAC's No.1 Cloud

19.6% IaaS Market Share in Asia Pacific - Gartner IT Service report, 2018

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。