Merge "Allow users to choose a notification assistant."

This commit is contained in:
Julia Reynolds
2016-01-04 22:07:28 +00:00
committed by Android (Google) Code Review
9 changed files with 187 additions and 10 deletions

View File

@@ -2668,6 +2668,19 @@
</intent-filter>
</activity>
<activity android:name="Settings$ManageDefaultAppsActivity"
android:taskAffinity=""
android:exported="true">
<intent-filter android:priority="1">
<action android:name="android.settings.MANAGE_DEFAULT_APPS_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.applications.ManageDefaultApps" />
<meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
android:value="true" />
</activity>
<!-- Conditional receivers, only enabled during silenced state, default off-->
<receiver
android:name=".dashboard.conditional.HotspotCondition$Receiver"

View File

@@ -5720,6 +5720,9 @@
<!-- [CHAR LIMIT=100] Notification Importance slider: max importance level description -->
<string name="notification_importance_max">Urgent: Peek onto the screen and make sound</string>
<!-- Default Apps > Default notification assistant -->
<string name="default_notification_assistant">Notification assistant</string>
<!-- Sound & notification > Advanced section: Title for managing notification listeners option. [CHAR LIMIT=30] -->
<string name="manage_notification_access_title">Notification access</string>

View File

@@ -49,4 +49,8 @@
settings:keywords="@string/keywords_more_default_sms_app"
/>
<com.android.settings.applications.DefaultNotificationAssistantPreference
android:key="default_notification_asst_app"
android:title="@string/default_notification_assistant" />
</PreferenceScreen>

View File

@@ -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<CharSequence> applicationNames = new ArrayList<>(entryCount);
List<CharSequence> validatedComponentNames = new ArrayList<>(entryCount);
List<Drawable> 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 ||

View File

@@ -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 */ }

View File

@@ -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(),
};

View File

@@ -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<ServiceInfo> 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<ServiceInfo> getServices() {
List<ServiceInfo> services = new ArrayList<>();
final int user = ActivityManager.getCurrentUser();
List<ResolveInfo> 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;
}
}

View File

@@ -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;
}
}