Refinements to notification controls in Settings.
- the switch is now a checkbox - a dialog is posted to explain the ramifications of disabling notifications - the user may no longer disable notifications from system apps (signed with the system cert); this is roughly the same as the constraint on disabling packages (with the exception that launchers may not be disabled entirely, but their notifications may still be disabled). Bug: 6493120 (checkbox) Bug: 6448988 (confirmation dialog & protect system apps) Change-Id: I6c7a47ba2eb943936d7f59cfc807a4390acc980d
This commit is contained in:
@@ -50,35 +50,12 @@
|
|||||||
android:id="@+id/control_buttons_panel"/>
|
android:id="@+id/control_buttons_panel"/>
|
||||||
|
|
||||||
<!-- Ban notifications for this package -->
|
<!-- Ban notifications for this package -->
|
||||||
<LinearLayout
|
<CheckBox android:id="@+id/notification_switch"
|
||||||
android:orientation="horizontal"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:minHeight="48dp"
|
|
||||||
android:paddingLeft="6dip"
|
|
||||||
android:paddingTop="8dip"
|
|
||||||
android:gravity="center_vertical">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingRight="14dip"
|
android:layout_marginLeft="12dip"
|
||||||
android:text="@string/app_notifications_switch_label"
|
android:layout_gravity="left"
|
||||||
android:singleLine="true"
|
android:text="@string/app_notifications_switch_label" />
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
|
||||||
android:ellipsize="marquee"
|
|
||||||
android:fadingEdge="horizontal" />
|
|
||||||
<Switch android:id="@+id/notification_switch"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:padding="8dip"
|
|
||||||
android:switchTextAppearance="@style/TextAppearance.Switch"
|
|
||||||
android:textOn="@string/app_notifications_switch_on"
|
|
||||||
android:textOff="@string/app_notifications_switch_off"
|
|
||||||
android:focusable="false"
|
|
||||||
android:clickable="true" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@@ -2508,6 +2508,12 @@
|
|||||||
<!-- [CHAR LIMIT=200] Manage applications, text for dialog when disabling apps -->
|
<!-- [CHAR LIMIT=200] Manage applications, text for dialog when disabling apps -->
|
||||||
<string name="app_disable_dlg_text">If you disable a built-in app, other apps
|
<string name="app_disable_dlg_text">If you disable a built-in app, other apps
|
||||||
may misbehave.</string>
|
may misbehave.</string>
|
||||||
|
<!-- [CHAR LIMIT=30] Manage applications, title for dialog when disabling notifications for an app -->
|
||||||
|
<string name="app_disable_notifications_dlg_title">Turn off notifications?</string>
|
||||||
|
<!-- [CHAR LIMIT=200] Manage applications, text for dialog when disabling notifications for an app -->
|
||||||
|
<string name="app_disable_notifications_dlg_text">
|
||||||
|
If you turn off notifications for this app, you may miss important alerts and updates.
|
||||||
|
</string>
|
||||||
|
|
||||||
<!-- [CHAR LIMIT=25] Services settings screen, setting option name for the user to go to the screen to view app storage use -->
|
<!-- [CHAR LIMIT=25] Services settings screen, setting option name for the user to go to the screen to view app storage use -->
|
||||||
<string name="storageuse_settings_title">Storage use</string>
|
<string name="storageuse_settings_title">Storage use</string>
|
||||||
@@ -4025,13 +4031,8 @@
|
|||||||
<!-- User removal confirmation message [CHAR LIMIT=none] -->
|
<!-- User removal confirmation message [CHAR LIMIT=none] -->
|
||||||
<string name="user_confirm_remove_message">Are you sure you want to remove the user and all associated data from the device?</string>
|
<string name="user_confirm_remove_message">Are you sure you want to remove the user and all associated data from the device?</string>
|
||||||
|
|
||||||
<!-- Label for "notifications enabled" switch in app details [CHAR LIMIT=20] -->
|
<!-- Label for are-notifications-enabled checkbox in app details [CHAR LIMIT=20] -->
|
||||||
<string name="app_notifications_switch_label">Notifications</string>
|
<string name="app_notifications_switch_label">Show notifications</string>
|
||||||
<!-- Label for enabled state of "notifications enabled" switch in app details [CHAR LIMIT=10] -->
|
|
||||||
<string name="app_notifications_switch_on">Enabled</string>
|
|
||||||
<!-- Label for disabled state "notifications enabled" switch in app details [CHAR LIMIT=10] -->
|
|
||||||
<string name="app_notifications_switch_off">Disabled</string>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Help URLs for some screens. Not specified here. Specified in product overlays --><skip/>
|
<!-- Help URLs for some screens. Not specified here. Specified in product overlays --><skip/>
|
||||||
<!-- Help menu label [CHAR LIMIT=20] -->
|
<!-- Help menu label [CHAR LIMIT=20] -->
|
||||||
|
@@ -125,7 +125,7 @@ public class InstalledAppDetails extends Fragment
|
|||||||
private Button mForceStopButton;
|
private Button mForceStopButton;
|
||||||
private Button mClearDataButton;
|
private Button mClearDataButton;
|
||||||
private Button mMoveAppButton;
|
private Button mMoveAppButton;
|
||||||
private Switch mNotificationSwitch;
|
private CompoundButton mNotificationSwitch;
|
||||||
|
|
||||||
private PackageMoveObserver mPackageMoveObserver;
|
private PackageMoveObserver mPackageMoveObserver;
|
||||||
|
|
||||||
@@ -161,6 +161,7 @@ public class InstalledAppDetails extends Fragment
|
|||||||
private static final int DLG_FORCE_STOP = DLG_BASE + 5;
|
private static final int DLG_FORCE_STOP = DLG_BASE + 5;
|
||||||
private static final int DLG_MOVE_FAILED = DLG_BASE + 6;
|
private static final int DLG_MOVE_FAILED = DLG_BASE + 6;
|
||||||
private static final int DLG_DISABLE = DLG_BASE + 7;
|
private static final int DLG_DISABLE = DLG_BASE + 7;
|
||||||
|
private static final int DLG_DISABLE_NOTIFICATIONS = DLG_BASE + 8;
|
||||||
|
|
||||||
private Handler mHandler = new Handler() {
|
private Handler mHandler = new Handler() {
|
||||||
public void handleMessage(Message msg) {
|
public void handleMessage(Message msg) {
|
||||||
@@ -279,6 +280,16 @@ public class InstalledAppDetails extends Fragment
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isThisASystemPackage() {
|
||||||
|
try {
|
||||||
|
PackageInfo sys = mPm.getPackageInfo("android", PackageManager.GET_SIGNATURES);
|
||||||
|
return (mPackageInfo != null && mPackageInfo.signatures != null &&
|
||||||
|
sys.signatures[0].equals(mPackageInfo.signatures[0]));
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void initUninstallButtons() {
|
private void initUninstallButtons() {
|
||||||
mUpdatedSysApp = (mAppEntry.info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
|
mUpdatedSysApp = (mAppEntry.info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
|
||||||
boolean enabled = true;
|
boolean enabled = true;
|
||||||
@@ -298,9 +309,7 @@ public class InstalledAppDetails extends Fragment
|
|||||||
intent.addCategory(Intent.CATEGORY_HOME);
|
intent.addCategory(Intent.CATEGORY_HOME);
|
||||||
intent.setPackage(mAppEntry.info.packageName);
|
intent.setPackage(mAppEntry.info.packageName);
|
||||||
List<ResolveInfo> homes = mPm.queryIntentActivities(intent, 0);
|
List<ResolveInfo> homes = mPm.queryIntentActivities(intent, 0);
|
||||||
if ((homes != null && homes.size() > 0) ||
|
if ((homes != null && homes.size() > 0) || isThisASystemPackage()) {
|
||||||
(mPackageInfo != null && mPackageInfo.signatures != null &&
|
|
||||||
sys.signatures[0].equals(mPackageInfo.signatures[0]))) {
|
|
||||||
// Disable button for core system applications.
|
// Disable button for core system applications.
|
||||||
mUninstallButton.setText(R.string.disable_text);
|
mUninstallButton.setText(R.string.disable_text);
|
||||||
} else if (mAppEntry.info.enabled) {
|
} else if (mAppEntry.info.enabled) {
|
||||||
@@ -340,8 +349,13 @@ public class InstalledAppDetails extends Fragment
|
|||||||
// this does not bode well
|
// this does not bode well
|
||||||
}
|
}
|
||||||
mNotificationSwitch.setChecked(enabled);
|
mNotificationSwitch.setChecked(enabled);
|
||||||
|
if (isThisASystemPackage()) {
|
||||||
|
mNotificationSwitch.setEnabled(false);
|
||||||
|
} else {
|
||||||
|
mNotificationSwitch.setEnabled(true);
|
||||||
mNotificationSwitch.setOnCheckedChangeListener(this);
|
mNotificationSwitch.setOnCheckedChangeListener(this);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Called when the activity is first created. */
|
/** Called when the activity is first created. */
|
||||||
@Override
|
@Override
|
||||||
@@ -395,7 +409,7 @@ public class InstalledAppDetails extends Fragment
|
|||||||
mAskCompatibilityCB = (CheckBox)view.findViewById(R.id.ask_compatibility_cb);
|
mAskCompatibilityCB = (CheckBox)view.findViewById(R.id.ask_compatibility_cb);
|
||||||
mEnableCompatibilityCB = (CheckBox)view.findViewById(R.id.enable_compatibility_cb);
|
mEnableCompatibilityCB = (CheckBox)view.findViewById(R.id.enable_compatibility_cb);
|
||||||
|
|
||||||
mNotificationSwitch = (Switch) view.findViewById(R.id.notification_switch);
|
mNotificationSwitch = (CompoundButton) view.findViewById(R.id.notification_switch);
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
@@ -851,6 +865,26 @@ public class InstalledAppDetails extends Fragment
|
|||||||
})
|
})
|
||||||
.setNegativeButton(R.string.dlg_cancel, null)
|
.setNegativeButton(R.string.dlg_cancel, null)
|
||||||
.create();
|
.create();
|
||||||
|
case DLG_DISABLE_NOTIFICATIONS:
|
||||||
|
return new AlertDialog.Builder(getActivity())
|
||||||
|
.setTitle(getActivity().getText(R.string.app_disable_notifications_dlg_title))
|
||||||
|
.setIcon(android.R.drawable.ic_dialog_alert)
|
||||||
|
.setMessage(getActivity().getText(R.string.app_disable_notifications_dlg_text))
|
||||||
|
.setPositiveButton(R.string.dlg_ok,
|
||||||
|
new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
// Disable the package's notifications
|
||||||
|
getOwner().setNotificationsEnabled(false);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setNegativeButton(R.string.dlg_cancel,
|
||||||
|
new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
// Re-enable the checkbox
|
||||||
|
getOwner().mNotificationSwitch.setChecked(true);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.create();
|
||||||
}
|
}
|
||||||
throw new IllegalArgumentException("unknown id " + id);
|
throw new IllegalArgumentException("unknown id " + id);
|
||||||
}
|
}
|
||||||
@@ -926,6 +960,18 @@ public class InstalledAppDetails extends Fragment
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setNotificationsEnabled(boolean enabled) {
|
||||||
|
String packageName = mAppEntry.info.packageName;
|
||||||
|
INotificationManager nm = INotificationManager.Stub.asInterface(
|
||||||
|
ServiceManager.getService(Context.NOTIFICATION_SERVICE));
|
||||||
|
try {
|
||||||
|
final boolean enable = mNotificationSwitch.isChecked();
|
||||||
|
nm.setNotificationsEnabledForPackage(packageName, enabled);
|
||||||
|
} catch (android.os.RemoteException ex) {
|
||||||
|
mNotificationSwitch.setChecked(!enabled); // revert
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Method implementing functionality of buttons clicked
|
* Method implementing functionality of buttons clicked
|
||||||
* @see android.view.View.OnClickListener#onClick(android.view.View)
|
* @see android.view.View.OnClickListener#onClick(android.view.View)
|
||||||
@@ -1003,12 +1049,10 @@ public class InstalledAppDetails extends Fragment
|
|||||||
am.setPackageScreenCompatMode(packageName, isChecked ?
|
am.setPackageScreenCompatMode(packageName, isChecked ?
|
||||||
ActivityManager.COMPAT_MODE_ENABLED : ActivityManager.COMPAT_MODE_DISABLED);
|
ActivityManager.COMPAT_MODE_ENABLED : ActivityManager.COMPAT_MODE_DISABLED);
|
||||||
} else if (buttonView == mNotificationSwitch) {
|
} else if (buttonView == mNotificationSwitch) {
|
||||||
INotificationManager nm = INotificationManager.Stub.asInterface(
|
if (!isChecked) {
|
||||||
ServiceManager.getService(Context.NOTIFICATION_SERVICE));
|
showDialogInner(DLG_DISABLE_NOTIFICATIONS, 0);
|
||||||
try {
|
} else {
|
||||||
nm.setNotificationsEnabledForPackage(packageName, isChecked);
|
setNotificationsEnabled(true);
|
||||||
} catch (android.os.RemoteException ex) {
|
|
||||||
mNotificationSwitch.setChecked(!isChecked); // revert
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user