From 2e1e0b7ef69b7a93cc170168aea211e739b3412e Mon Sep 17 00:00:00 2001 From: Julia Reynolds Date: Mon, 14 Dec 2015 08:32:46 -0500 Subject: [PATCH] Allow users to choose a notification assistant. Change-Id: Iddfbfedbb6a3aae246058ff41324dc06852484cb --- AndroidManifest.xml | 13 ++ res/values/strings.xml | 3 + res/xml/default_apps.xml | 4 + .../android/settings/AppListPreference.java | 43 +++++++ .../settings/CustomListPreference.java | 2 +- src/com/android/settings/Settings.java | 1 + .../android/settings/SettingsActivity.java | 2 + ...efaultNotificationAssistantPreference.java | 111 ++++++++++++++++++ .../notification/ManagedServiceSettings.java | 18 +-- 9 files changed, 187 insertions(+), 10 deletions(-) create mode 100644 src/com/android/settings/applications/DefaultNotificationAssistantPreference.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml index d35a844a00e..d8dd102488d 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -2668,6 +2668,19 @@ + + + + + + + + + Urgent: Peek onto the screen and make sound + + Notification assistant + Notification access diff --git a/res/xml/default_apps.xml b/res/xml/default_apps.xml index d5f9de04300..a38ef4ac4c2 100644 --- a/res/xml/default_apps.xml +++ b/res/xml/default_apps.xml @@ -49,4 +49,8 @@ settings:keywords="@string/keywords_more_default_sms_app" /> + + diff --git a/src/com/android/settings/AppListPreference.java b/src/com/android/settings/AppListPreference.java index c480d5a1dbb..4d24d7f3e36 100644 --- a/src/com/android/settings/AppListPreference.java +++ b/src/com/android/settings/AppListPreference.java @@ -18,6 +18,7 @@ package com.android.settings; import android.app.Activity; import android.app.AlertDialog; +import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; import android.content.pm.ApplicationInfo; @@ -131,6 +132,48 @@ public class AppListPreference extends CustomListPreference { } } + public void setComponentNames(ComponentName[] componentNames, ComponentName defaultCN) { + // Look up all package names in PackageManager. Skip ones we can't find. + PackageManager pm = getContext().getPackageManager(); + final int entryCount = componentNames.length + (mShowItemNone ? 1 : 0); + List applicationNames = new ArrayList<>(entryCount); + List validatedComponentNames = new ArrayList<>(entryCount); + List entryDrawables = new ArrayList<>(entryCount); + int selectedIndex = -1; + for (int i = 0; i < componentNames.length; i++) { + try { + ApplicationInfo appInfo = pm.getApplicationInfo( + componentNames[i].getPackageName().toString(), 0); + applicationNames.add(appInfo.loadLabel(pm)); + validatedComponentNames.add(componentNames[i].flattenToString()); + entryDrawables.add(appInfo.loadIcon(pm)); + if (defaultCN != null && componentNames[i].equals(defaultCN)) { + selectedIndex = i; + } + } catch (NameNotFoundException e) { + // Skip unknown packages. + } + } + + if (mShowItemNone) { + applicationNames.add( + getContext().getResources().getText(R.string.app_list_preference_none)); + validatedComponentNames.add(ITEM_NONE_VALUE); + entryDrawables.add(getContext().getDrawable(R.drawable.ic_remove_circle)); + } + + setEntries(applicationNames.toArray(new CharSequence[applicationNames.size()])); + setEntryValues( + validatedComponentNames.toArray(new CharSequence[validatedComponentNames.size()])); + mEntryDrawables = entryDrawables.toArray(new Drawable[entryDrawables.size()]); + + if (selectedIndex != -1) { + setValueIndex(selectedIndex); + } else { + setValue(null); + } + } + protected ListAdapter createListAdapter() { final String selectedValue = getValue(); final boolean selectedNone = selectedValue == null || diff --git a/src/com/android/settings/CustomListPreference.java b/src/com/android/settings/CustomListPreference.java index ce37c14453a..645915a6ced 100644 --- a/src/com/android/settings/CustomListPreference.java +++ b/src/com/android/settings/CustomListPreference.java @@ -24,7 +24,7 @@ import android.support.v14.preference.ListPreferenceDialogFragment; import android.support.v7.preference.ListPreference; import android.util.AttributeSet; -public class CustomListPreference extends ListPreference{ +public class CustomListPreference extends ListPreference { public CustomListPreference(Context context, AttributeSet attrs) { super(context, attrs); diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java index 149ef4504ba..edd0b4ccd2a 100644 --- a/src/com/android/settings/Settings.java +++ b/src/com/android/settings/Settings.java @@ -121,6 +121,7 @@ public class Settings extends SettingsActivity { public static class WriteSettingsActivity extends SettingsActivity { /* empty */ } public static class AppDrawOverlaySettingsActivity extends SettingsActivity { /* empty */ } public static class AppWriteSettingsActivity extends SettingsActivity { /* empty */ } + public static class ManageDefaultAppsActivity extends SettingsActivity { /* empty */ } // Categories. public static class WirelessSettings extends SettingsActivity { /* empty */ } diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java index 94379b35992..4d9e2f0ae70 100644 --- a/src/com/android/settings/SettingsActivity.java +++ b/src/com/android/settings/SettingsActivity.java @@ -61,6 +61,7 @@ import com.android.settings.applications.DrawOverlayDetails; import com.android.settings.applications.InstalledAppDetails; import com.android.settings.applications.ManageApplications; import com.android.settings.applications.ManageAssist; +import com.android.settings.applications.ManageDefaultApps; import com.android.settings.applications.ProcessStatsSummary; import com.android.settings.applications.ProcessStatsUi; import com.android.settings.applications.UsageAccessDetails; @@ -306,6 +307,7 @@ public class SettingsActivity extends SettingsDrawerActivity ProcessStatsSummary.class.getName(), DrawOverlayDetails.class.getName(), WriteSettingsDetails.class.getName(), + ManageDefaultApps.class.getName(), }; diff --git a/src/com/android/settings/applications/DefaultNotificationAssistantPreference.java b/src/com/android/settings/applications/DefaultNotificationAssistantPreference.java new file mode 100644 index 00000000000..20c1a9ebb14 --- /dev/null +++ b/src/com/android/settings/applications/DefaultNotificationAssistantPreference.java @@ -0,0 +1,111 @@ +/** + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.applications; + +import com.android.settings.AppListPreference; + +import android.app.ActivityManager; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; +import android.provider.Settings; +import android.service.notification.NotificationAssistantService; +import android.util.AttributeSet; +import android.util.Slog; + +import java.util.ArrayList; +import java.util.List; + +import com.android.settings.R; +import com.android.settings.notification.ManagedServiceSettings; + +public class DefaultNotificationAssistantPreference extends AppListPreference { + private static final String TAG = "DefaultNotiAssist"; + + private PackageManager mPm; + private final ManagedServiceSettings.Config mConfig; + private final Context mContext; + + public DefaultNotificationAssistantPreference(Context context, AttributeSet attrs) { + super(context, attrs); + + mContext = context; + mPm = context.getPackageManager(); + mConfig = getConfig(); + setShowItemNone(true); + updateList(getServices()); + } + + @Override + protected boolean persistString(String value) { + Settings.Secure.putString(mContext.getContentResolver(), mConfig.setting, value); + setSummary(getEntry()); + return true; + } + + private void updateList(List services) { + final ComponentName[] assistants = new ComponentName[services.size()]; + for (int i = 0; i < services.size(); i++) { + assistants[i] = new ComponentName(services.get(i).packageName, services.get(i).name); + } + final String assistant = + Settings.Secure.getString(mContext.getContentResolver(), mConfig.setting); + setComponentNames(assistants, assistant == null ? null + : ComponentName.unflattenFromString(assistant)); + } + + private List getServices() { + List services = new ArrayList<>(); + final int user = ActivityManager.getCurrentUser(); + + List installedServices = mPm.queryIntentServicesAsUser( + new Intent(mConfig.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 (!mConfig.permission.equals(info.permission)) { + Slog.w(mConfig.tag, "Skipping " + mConfig.noun + " service " + + info.packageName + "/" + info.name + + ": it does not require the permission " + + mConfig.permission); + continue; + } + services.add(info); + } + return services; + } + + private ManagedServiceSettings.Config getConfig() { + final ManagedServiceSettings.Config c = new ManagedServiceSettings.Config(); + c.tag = TAG; + c.setting = Settings.Secure.ENABLED_NOTIFICATION_ASSISTANT; + c.intentAction = NotificationAssistantService.SERVICE_INTERFACE; + c.permission = android.Manifest.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE; + c.noun = "notification assistant"; + c.warningDialogTitle = R.string.notification_listener_security_warning_title; + c.warningDialogSummary = R.string.notification_listener_security_warning_summary; + c.emptyText = R.string.no_notification_listeners; + return c; + } +} diff --git a/src/com/android/settings/notification/ManagedServiceSettings.java b/src/com/android/settings/notification/ManagedServiceSettings.java index 401e650fd44..56c7b6930fa 100644 --- a/src/com/android/settings/notification/ManagedServiceSettings.java +++ b/src/com/android/settings/notification/ManagedServiceSettings.java @@ -169,14 +169,14 @@ public abstract class ManagedServiceSettings extends EmptyTextSettings { } } - protected static class Config { - String tag; - String setting; - String intentAction; - String permission; - String noun; - int warningDialogTitle; - int warningDialogSummary; - int emptyText; + public static class Config { + public String tag; + public String setting; + public String intentAction; + public String permission; + public String noun; + public int warningDialogTitle; + public int warningDialogSummary; + public int emptyText; } }