OSDN Git Service

Settings: Carve out app-level notifcation settings dialog.
authorJohn Spurlock <jspurlock@google.com>
Sun, 27 Jul 2014 17:33:34 +0000 (13:33 -0400)
committerJohn Spurlock <jspurlock@google.com>
Tue, 29 Jul 2014 02:10:46 +0000 (22:10 -0400)
Bug:16208321
Change-Id: I46574618518e8fe4cbef70e80204cc7bb7cb76e9

AndroidManifest.xml
src/com/android/settings/notification/AppNotificationDialog.java [new file with mode: 0644]
src/com/android/settings/notification/AppNotificationSettings.java

index 5457d72..67e34f1 100644 (file)
                 android:label="@string/app_notifications_title"
                 android:exported="true"
                 android:taskAffinity="">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <action android:name="android.settings.ACTION_APP_NOTIFICATION_SETTINGS" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
             <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
                 android:value="com.android.settings.notification.AppNotificationSettings" />
             <meta-data android:name="com.android.settings.TOP_LEVEL_HEADER_ID"
                 android:resource="@id/notification_settings" />
         </activity>
 
+        <activity android:name=".notification.AppNotificationDialog"
+                android:theme="@style/Theme.AlertDialog"
+                android:launchMode="singleTop"
+                android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <action android:name="android.settings.APP_NOTIFICATION_SETTINGS" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
         <!-- Show regulatory info (from settings item or dialing "*#07#") -->
         <activity android:name="RegulatoryInfoDisplayActivity"
                   android:label="@string/regulatory_information"
diff --git a/src/com/android/settings/notification/AppNotificationDialog.java b/src/com/android/settings/notification/AppNotificationDialog.java
new file mode 100644 (file)
index 0000000..55f25c2
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2014 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.notification;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.widget.Toast;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+
+import com.android.internal.app.AlertActivity;
+import com.android.internal.app.AlertController;
+import com.android.settings.R;
+import com.android.settings.notification.AppNotificationSettings.Backend;
+import com.android.settings.notification.AppNotificationSettings.AppRow;
+
+public class AppNotificationDialog extends AlertActivity {
+    private static final String TAG = "AppNotificationDialog";
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+    /**
+     * Show a checkbox in the per-app notification control dialog to allow the user to
+     * selectively redact this app's notifications on the lockscreen.
+     */
+    private static final boolean ENABLE_APP_NOTIFICATION_PRIVACY_OPTION = false;
+
+    private final Context mContext = this;
+    private final Backend mBackend = new Backend();
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        if (DEBUG) Log.d(TAG, "onCreate getIntent()=" + getIntent());
+        if (!buildDialog()) {
+            Toast.makeText(mContext, R.string.app_not_found_dlg_text, Toast.LENGTH_SHORT).show();
+            finish();
+        }
+    }
+
+    private boolean buildDialog() {
+        final Intent intent = getIntent();
+        if (intent != null) {
+            final int uid = intent.getIntExtra(Settings.EXTRA_APP_UID, -1);
+            final String pkg = intent.getStringExtra(Settings.EXTRA_APP_PACKAGE);
+            if (uid != -1 && !TextUtils.isEmpty(pkg)) {
+                if (DEBUG) Log.d(TAG, "Load details for pkg=" + pkg + " uid=" + uid);
+                final PackageManager pm = getPackageManager();
+                final PackageInfo info = findPackageInfo(pm, pkg, uid);
+                if (info != null) {
+                    final AppRow row = AppNotificationSettings.loadAppRow(pm, info, mBackend);
+                    final AlertController.AlertParams p = mAlertParams;
+                    p.mView = getLayoutInflater().inflate(R.layout.notification_app_dialog,
+                            null, false);
+                    p.mPositiveButtonText = getString(R.string.app_notifications_dialog_done);
+                    bindDialog(p.mView, row);
+                    setupAlert();
+                    return true;
+                } else {
+                    Log.w(TAG, "Failed to find package info");
+                }
+            } else {
+                Log.w(TAG, "Missing extras: " + Settings.EXTRA_APP_PACKAGE + " was " + pkg + ", "
+                        + Settings.EXTRA_APP_UID + " was " + uid);
+            }
+        } else {
+            Log.w(TAG, "No intent");
+        }
+        return false;
+    }
+
+    private static PackageInfo findPackageInfo(PackageManager pm, String pkg, int uid) {
+        final String[] packages = pm.getPackagesForUid(uid);
+        if (packages != null && pkg != null) {
+            final int N = packages.length;
+            for (int i = 0; i < N; i++) {
+                final String p = packages[i];
+                if (pkg.equals(p)) {
+                    try {
+                        return pm.getPackageInfo(pkg, 0);
+                    } catch (NameNotFoundException e) {
+                        Log.w(TAG, "Failed to load package " + pkg, e);
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    private void bindDialog(final View v, final AppRow row) {
+        final ImageView icon = (ImageView) v.findViewById(android.R.id.icon);
+        icon.setImageDrawable(row.icon);
+        final TextView title = (TextView) v.findViewById(android.R.id.title);
+        title.setText(row.label);
+        final CheckBox showNotifications = (CheckBox) v.findViewById(android.R.id.button1);
+        final CheckBox highPriority = (CheckBox) v.findViewById(android.R.id.button2);
+        final CheckBox sensitive = (CheckBox) v.findViewById(android.R.id.button3);
+
+        if (!ENABLE_APP_NOTIFICATION_PRIVACY_OPTION) {
+            sensitive.setVisibility(View.GONE);
+        }
+
+        showNotifications.setChecked(!row.banned);
+        final OnCheckedChangeListener showListener = new OnCheckedChangeListener() {
+            @Override
+            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+                boolean success = mBackend.setNotificationsBanned(row.pkg, row.uid, !isChecked);
+                if (success) {
+                    row.banned = !isChecked;
+                    highPriority.setEnabled(!row.banned);
+                    sensitive.setEnabled(!row.banned);
+                } else {
+                    showNotifications.setOnCheckedChangeListener(null);
+                    showNotifications.setChecked(!isChecked);
+                    showNotifications.setOnCheckedChangeListener(this);
+                }
+            }
+        };
+        showNotifications.setOnCheckedChangeListener(showListener);
+
+        highPriority.setChecked(row.priority);
+        final OnCheckedChangeListener priListener = new OnCheckedChangeListener() {
+            @Override
+            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+                boolean success = mBackend.setHighPriority(row.pkg, row.uid, isChecked);
+                if (success) {
+                    row.priority = isChecked;
+                } else {
+                    highPriority.setOnCheckedChangeListener(null);
+                    highPriority.setChecked(!isChecked);
+                    highPriority.setOnCheckedChangeListener(this);
+                }
+            }
+        };
+        highPriority.setOnCheckedChangeListener(priListener);
+
+        sensitive.setChecked(row.sensitive);
+        final OnCheckedChangeListener senListener = new OnCheckedChangeListener() {
+            @Override
+            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+                boolean success = mBackend.setSensitive(row.pkg, row.uid, isChecked);
+                if (success) {
+                    row.sensitive = isChecked;
+                } else {
+                    sensitive.setOnCheckedChangeListener(null);
+                    sensitive.setChecked(!isChecked);
+                    sensitive.setOnCheckedChangeListener(this);
+                }
+            }
+        };
+        sensitive.setOnCheckedChangeListener(senListener);
+
+        highPriority.setEnabled(!row.banned);
+        sensitive.setEnabled(!row.banned);
+    }
+}
index eb868b4..25047a4 100644 (file)
@@ -17,9 +17,7 @@
 package com.android.settings.notification;
 
 import android.animation.LayoutTransition;
-import android.app.AlertDialog;
 import android.app.INotificationManager;
-import android.app.ListFragment;
 import android.app.Notification;
 import android.content.Context;
 import android.content.Intent;
@@ -37,6 +35,7 @@ import android.os.Handler;
 import android.os.Parcelable;
 import android.os.ServiceManager;
 import android.os.SystemClock;
+import android.provider.Settings;
 import android.util.ArrayMap;
 import android.util.Log;
 import android.util.TypedValue;
@@ -45,11 +44,7 @@ import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.widget.ArrayAdapter;
-import android.widget.CheckBox;
-import android.widget.CompoundButton;
-import android.widget.CompoundButton.OnCheckedChangeListener;
 import android.widget.ImageView;
-import android.widget.RelativeLayout;
 import android.widget.SectionIndexer;
 import android.widget.TextView;
 
@@ -65,18 +60,7 @@ import java.util.List;
 /** Just a sectioned list of installed applications, nothing else to index **/
 public class AppNotificationSettings extends PinnedHeaderListFragment {
     private static final String TAG = "AppNotificationSettings";
-    private static final boolean DEBUG = true;
-
-    /**
-     * Show a checkbox in the per-app notification control dialog to allow the user
-     * to promote this app's notifications to higher priority.
-     */
-    private static final boolean ENABLE_APP_NOTIFICATION_PRIORITY_OPTION = true;
-    /**
-     * Show a checkbox in the per-app notification control dialog to allow the user to
-     * selectively redact this app's notifications on the lockscreen.
-     */
-    private static final boolean ENABLE_APP_NOTIFICATION_PRIVACY_OPTION = false;
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private static final String SECTION_BEFORE_A = "*";
     private static final String SECTION_AFTER_Z = "**";
@@ -189,89 +173,6 @@ public class AppNotificationSettings extends PinnedHeaderListFragment {
         return null;
     }
 
-
-    private void showDialog(final View v, final AppRow row) {
-        final RelativeLayout layout = (RelativeLayout)
-                mInflater.inflate(R.layout.notification_app_dialog, null);
-        final ImageView icon = (ImageView) layout.findViewById(android.R.id.icon);
-        icon.setImageDrawable(row.icon);
-        final TextView title = (TextView) layout.findViewById(android.R.id.title);
-        title.setText(row.label);
-        final CheckBox showBox = (CheckBox) layout.findViewById(android.R.id.button1);
-        final CheckBox priBox = (CheckBox) layout.findViewById(android.R.id.button2);
-        final CheckBox senBox = (CheckBox) layout.findViewById(android.R.id.button3);
-
-        if (!ENABLE_APP_NOTIFICATION_PRIORITY_OPTION) {
-            priBox.setVisibility(View.GONE);
-        }
-
-        if (!ENABLE_APP_NOTIFICATION_PRIVACY_OPTION) {
-            senBox.setVisibility(View.GONE);
-        }
-
-        showBox.setChecked(!row.banned);
-        final OnCheckedChangeListener showListener = new OnCheckedChangeListener() {
-            @Override
-            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
-                boolean success = mBackend.setNotificationsBanned(row.pkg, row.uid, !isChecked);
-                if (success) {
-                    row.banned = !isChecked;
-                    mAdapter.bindView(v, row, true /*animate*/);
-                    priBox.setEnabled(!row.banned);
-                    senBox.setEnabled(!row.banned);
-                } else {
-                    showBox.setOnCheckedChangeListener(null);
-                    showBox.setChecked(!isChecked);
-                    showBox.setOnCheckedChangeListener(this);
-                }
-            }
-        };
-        showBox.setOnCheckedChangeListener(showListener);
-
-        priBox.setChecked(row.priority);
-        final OnCheckedChangeListener priListener = new OnCheckedChangeListener() {
-            @Override
-            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
-                boolean success = mBackend.setHighPriority(row.pkg, row.uid, isChecked);
-                if (success) {
-                    row.priority = isChecked;
-                    mAdapter.bindView(v, row, true /*animate*/);
-                } else {
-                    priBox.setOnCheckedChangeListener(null);
-                    priBox.setChecked(!isChecked);
-                    priBox.setOnCheckedChangeListener(this);
-                }
-            }
-        };
-        priBox.setOnCheckedChangeListener(priListener);
-
-        senBox.setChecked(row.sensitive);
-        final OnCheckedChangeListener senListener = new OnCheckedChangeListener() {
-            @Override
-            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
-                boolean success = mBackend.setSensitive(row.pkg, row.uid, isChecked);
-                if (success) {
-                    row.sensitive = isChecked;
-                    mAdapter.bindView(v, row, true /*animate*/);
-                } else {
-                    senBox.setOnCheckedChangeListener(null);
-                    senBox.setChecked(!isChecked);
-                    senBox.setOnCheckedChangeListener(this);
-                }
-            }
-        };
-        senBox.setOnCheckedChangeListener(senListener);
-
-        priBox.setEnabled(!row.banned);
-        senBox.setEnabled(!row.banned);
-
-        final AlertDialog d = new AlertDialog.Builder(mContext)
-            .setView(layout)
-            .setPositiveButton(R.string.app_notifications_dialog_done, null)
-            .create();
-        d.show();
-    }
-
     private static class ViewHolder {
         ViewGroup row;
         ViewGroup appButton;
@@ -366,7 +267,10 @@ public class AppNotificationSettings extends PinnedHeaderListFragment {
             vh.appButton.setOnClickListener(new OnClickListener() {
                 @Override
                 public void onClick(View v) {
-                    showDialog(view, row);
+                    mContext.startActivity(new Intent(mContext, AppNotificationDialog.class)
+                            .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
+                            .putExtra(Settings.EXTRA_APP_PACKAGE, row.pkg)
+                            .putExtra(Settings.EXTRA_APP_UID, row.uid));
                 }
             });
             enableLayoutTransitions(vh.appButton, animate);
@@ -428,7 +332,7 @@ public class AppNotificationSettings extends PinnedHeaderListFragment {
         public String section;
     }
 
-    private static class AppRow extends Row {
+    public static class AppRow extends Row {
         public String pkg;
         public int uid;
         public Drawable icon;
@@ -448,6 +352,23 @@ public class AppNotificationSettings extends PinnedHeaderListFragment {
         }
     };
 
+    public static AppRow loadAppRow(PackageManager pm, PackageInfo pkg, Backend backend) {
+        final AppRow row = new AppRow();
+        row.pkg = pkg.packageName;
+        row.uid = pkg.applicationInfo.uid;
+        try {
+            row.label = pkg.applicationInfo.loadLabel(pm);
+        } catch (Throwable t) {
+            Log.e(TAG, "Error loading application label for " + row.pkg, t);
+            row.label = row.pkg;
+        }
+        row.icon = pkg.applicationInfo.loadIcon(pm);
+        row.banned = backend.getNotificationsBanned(row.pkg, row.uid);
+        row.priority = backend.getHighPriority(row.pkg, row.uid);
+        row.sensitive = backend.getSensitive(row.pkg, row.uid);
+        return row;
+    }
+
     private final Runnable mCollectAppsRunnable = new Runnable() {
         @Override
         public void run() {
@@ -464,23 +385,12 @@ public class AppNotificationSettings extends PinnedHeaderListFragment {
                         if (DEBUG) Log.d(TAG, "Skipping " + pkg.packageName);
                         continue;
                     }
-                    final AppRow row = new AppRow();
-                    row.pkg = pkg.packageName;
-                    row.uid = pkg.applicationInfo.uid;
-                    try {
-                        row.label = pkg.applicationInfo.loadLabel(pm);
-                    } catch (Throwable t) {
-                        Log.e(TAG, "Error loading application label for " + row.pkg, t);
-                        row.label = row.pkg;
-                    }
-                    row.icon = pkg.applicationInfo.loadIcon(pm);
-                    row.banned = mBackend.getNotificationsBanned(row.pkg, row.uid);
-                    row.priority = mBackend.getHighPriority(row.pkg, row.uid);
-                    row.sensitive = mBackend.getSensitive(row.pkg, row.uid);
+                    final AppRow row = loadAppRow(pm, pkg, mBackend);
                     mRows.put(row.pkg, row);
                 }
                 // collect config activities
-                Log.d(TAG, "APP_NOTIFICATION_PREFS_CATEGORY_INTENT is " + APP_NOTIFICATION_PREFS_CATEGORY_INTENT);
+                if (DEBUG) Log.d(TAG, "APP_NOTIFICATION_PREFS_CATEGORY_INTENT is "
+                        + APP_NOTIFICATION_PREFS_CATEGORY_INTENT);
                 final List<ResolveInfo> resolveInfos = pm.queryIntentActivities(
                         APP_NOTIFICATION_PREFS_CATEGORY_INTENT,
                         PackageManager.MATCH_DEFAULT_ONLY);