Make notifications app list use new manage apps
The designs for Settings have the notification app list using the same UI as the Manage Apps list, so switch the notification app list over to the ManageApplications fragment. This involves adding some notification based filters and connecting the data from the Notification Backend to ApplicationsState. Bug: 19443900 Change-Id: I5e5cdb16890d536613ee59292b89a89b6fb9e2e6
This commit is contained in:
@@ -2084,7 +2084,7 @@
|
||||
android:exported="true"
|
||||
android:taskAffinity="">
|
||||
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
|
||||
android:value="com.android.settings.notification.NotificationAppList" />
|
||||
android:value="com.android.settings.applications.ManageApplications" />
|
||||
<meta-data android:name="com.android.settings.TOP_LEVEL_HEADER_ID"
|
||||
android:resource="@id/notification_settings" />
|
||||
</activity>
|
||||
|
@@ -1,43 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ListView
|
||||
android:id="@android:id/list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingStart="@dimen/settings_side_margin"
|
||||
android:paddingEnd="@dimen/settings_side_margin"
|
||||
android:divider="#0000"
|
||||
android:dividerHeight="0px"
|
||||
android:fastScrollEnabled="true"
|
||||
android:listSelector="#0000"
|
||||
android:scrollbarStyle="outsideInset" />
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/empty"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:text="@string/loading_notification_apps"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium" />
|
||||
|
||||
</LinearLayout>
|
@@ -6103,6 +6103,12 @@
|
||||
<string name="filter_personal_apps">Personal</string>
|
||||
<!-- Label for showing work apps in list [CHAR LIMIT=30] -->
|
||||
<string name="filter_work_apps">Work</string>
|
||||
<!-- Label for showing apps with blocked notifications in list [CHAR LIMIT=30] -->
|
||||
<string name="filter_notif_blocked_apps">Blocked</string>
|
||||
<!-- Label for showing apps with priority notifications in list [CHAR LIMIT=30] -->
|
||||
<string name="filter_notif_priority_apps">Priority</string>
|
||||
<!-- Label for showing apps with sensitive notifications in list [CHAR LIMIT=30] -->
|
||||
<string name="filter_notif_sensitive_apps">Sensitive</string>
|
||||
|
||||
<!-- Description for advanced menu option to reset app preferences [CHAR LIMIT=NONE] -->
|
||||
<string name="reset_app_preferences_description">Reset preferences across all apps to defaults</string>
|
||||
|
@@ -114,7 +114,11 @@
|
||||
<PreferenceScreen
|
||||
android:key="app_notifications"
|
||||
android:title="@string/app_notifications_title"
|
||||
android:fragment="com.android.settings.notification.NotificationAppList" />
|
||||
android:fragment="com.android.settings.applications.ManageApplications">
|
||||
<extra
|
||||
android:name="classname"
|
||||
android:value="com.android.settings.Settings$NotificationAppListActivity" />
|
||||
</PreferenceScreen>
|
||||
|
||||
<!-- Notification access -->
|
||||
<Preference
|
||||
|
@@ -118,10 +118,10 @@ public class AppPicker extends ListActivity {
|
||||
holder.appName.setText(info.label);
|
||||
if (info.info != null) {
|
||||
holder.appIcon.setImageDrawable(info.info.loadIcon(getPackageManager()));
|
||||
holder.appSize.setText(info.info.packageName);
|
||||
holder.summary.setText(info.info.packageName);
|
||||
} else {
|
||||
holder.appIcon.setImageDrawable(null);
|
||||
holder.appSize.setText("");
|
||||
holder.summary.setText("");
|
||||
}
|
||||
holder.disabled.setVisibility(View.GONE);
|
||||
holder.checkBox.setVisibility(View.GONE);
|
||||
|
@@ -81,7 +81,6 @@ import com.android.settings.deviceinfo.Memory;
|
||||
import com.android.settings.deviceinfo.UsbSettings;
|
||||
import com.android.settings.fuelgauge.BatterySaverSettings;
|
||||
import com.android.settings.fuelgauge.PowerUsageSummary;
|
||||
import com.android.settings.notification.NotificationAppList;
|
||||
import com.android.settings.notification.OtherSoundSettings;
|
||||
import com.android.settings.search.DynamicIndexableContentMonitor;
|
||||
import com.android.settings.search.Index;
|
||||
@@ -296,7 +295,6 @@ public class SettingsActivity extends Activity
|
||||
ChooseLockPattern.ChooseLockPatternFragment.class.getName(),
|
||||
InstalledAppDetails.class.getName(),
|
||||
BatterySaverSettings.class.getName(),
|
||||
NotificationAppList.class.getName(),
|
||||
AppNotificationSettings.class.getName(),
|
||||
OtherSoundSettings.class.getName(),
|
||||
ApnSettings.class.getName(),
|
||||
|
@@ -254,4 +254,9 @@ public class AdvancedAppSettings extends SettingsPreferenceFragment implements C
|
||||
// No-op.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadEntriesCompleted() {
|
||||
// No-op.
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -184,6 +184,11 @@ public abstract class AppInfoBase extends PreferenceFragment
|
||||
// No op.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadEntriesCompleted() {
|
||||
// No op.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPackageListChanged() {
|
||||
refreshUi();
|
||||
|
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* 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 android.content.pm.PackageManager;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
|
||||
import com.android.settings.applications.ApplicationsState.AppEntry;
|
||||
import com.android.settings.applications.ApplicationsState.AppFilter;
|
||||
import com.android.settings.applications.ApplicationsState.Session;
|
||||
import com.android.settings.notification.NotificationBackend;
|
||||
import com.android.settings.notification.NotificationBackend.AppRow;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Connects the info provided by ApplicationsState and the NotificationBackend.
|
||||
* Also provides app filters that can use the notification data.
|
||||
*/
|
||||
public class AppStateNotificationBridge implements ApplicationsState.Callbacks {
|
||||
|
||||
private final ApplicationsState mAppState;
|
||||
private final NotificationBackend mNotifBackend;
|
||||
private final Session mAppSession;
|
||||
private final Callback mCallback;
|
||||
private final BackgroundHandler mHandler;
|
||||
private final MainHandler mMainHandler;
|
||||
private final PackageManager mPm;
|
||||
|
||||
public AppStateNotificationBridge(PackageManager pm, ApplicationsState appState,
|
||||
NotificationBackend notifBackend, Callback callback) {
|
||||
mAppState = appState;
|
||||
mPm = pm;
|
||||
mAppSession = mAppState.newSession(this);
|
||||
mNotifBackend = notifBackend;
|
||||
mCallback = callback;
|
||||
// Running on the same background thread as the ApplicationsState lets
|
||||
// us run in the background and make sure they aren't doing updates at
|
||||
// the same time as us as well.
|
||||
mHandler = new BackgroundHandler(mAppState.getBackgroundLooper());
|
||||
mMainHandler = new MainHandler();
|
||||
mHandler.sendEmptyMessage(BackgroundHandler.MSG_LOAD_ALL);
|
||||
}
|
||||
|
||||
public void resume() {
|
||||
mHandler.sendEmptyMessage(BackgroundHandler.MSG_LOAD_ALL);
|
||||
mAppSession.resume();
|
||||
}
|
||||
|
||||
public void pause() {
|
||||
mAppSession.pause();
|
||||
}
|
||||
|
||||
public void release() {
|
||||
mAppSession.release();
|
||||
}
|
||||
|
||||
public void forceUpdate(String pkg, int uid) {
|
||||
mHandler.obtainMessage(BackgroundHandler.MSG_FORCE_LOAD_PKG, uid, 0, pkg).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPackageListChanged() {
|
||||
mHandler.sendEmptyMessage(BackgroundHandler.MSG_LOAD_ALL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadEntriesCompleted() {
|
||||
mHandler.sendEmptyMessage(BackgroundHandler.MSG_LOAD_ALL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRunningStateChanged(boolean running) {
|
||||
// No op.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRebuildComplete(ArrayList<AppEntry> apps) {
|
||||
// No op.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPackageIconChanged() {
|
||||
// No op.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPackageSizeChanged(String packageName) {
|
||||
// No op.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAllSizesComputed() {
|
||||
// No op.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLauncherInfoChanged() {
|
||||
// No op.
|
||||
}
|
||||
|
||||
private class MainHandler extends Handler {
|
||||
private static final int MSG_NOTIF_UPDATED = 1;
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case MSG_NOTIF_UPDATED:
|
||||
mCallback.onNotificationInfoUpdated();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class BackgroundHandler extends Handler {
|
||||
private static final int MSG_LOAD_ALL = 1;
|
||||
private static final int MSG_FORCE_LOAD_PKG = 2;
|
||||
|
||||
public BackgroundHandler(Looper looper) {
|
||||
super(looper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
List<AppEntry> apps = mAppSession.getAllApps();
|
||||
final int N = apps.size();
|
||||
switch (msg.what) {
|
||||
case MSG_LOAD_ALL:
|
||||
for (int i = 0; i < N; i++) {
|
||||
AppEntry app = apps.get(i);
|
||||
app.extraInfo = mNotifBackend.loadAppRow(mPm, app.info);
|
||||
}
|
||||
mMainHandler.sendEmptyMessage(MainHandler.MSG_NOTIF_UPDATED);
|
||||
break;
|
||||
case MSG_FORCE_LOAD_PKG:
|
||||
String pkg = (String) msg.obj;
|
||||
int uid = msg.arg1;
|
||||
for (int i = 0; i < N; i++) {
|
||||
AppEntry app = apps.get(i);
|
||||
if (app.info.uid == uid && pkg.equals(app.info.packageName)) {
|
||||
app.extraInfo = mNotifBackend.loadAppRow(mPm, app.info);
|
||||
break;
|
||||
}
|
||||
}
|
||||
mMainHandler.sendEmptyMessage(MainHandler.MSG_NOTIF_UPDATED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface Callback {
|
||||
void onNotificationInfoUpdated();
|
||||
}
|
||||
|
||||
public static final AppFilter FILTER_APP_NOTIFICATION_BLOCKED = new AppFilter() {
|
||||
@Override
|
||||
public void init() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean filterApp(AppEntry info) {
|
||||
return info.extraInfo != null && ((AppRow) info.extraInfo).banned;
|
||||
}
|
||||
};
|
||||
|
||||
public static final AppFilter FILTER_APP_NOTIFICATION_PRIORITY = new AppFilter() {
|
||||
@Override
|
||||
public void init() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean filterApp(AppEntry info) {
|
||||
return info.extraInfo != null && ((AppRow) info.extraInfo).priority;
|
||||
}
|
||||
};
|
||||
|
||||
public static final AppFilter FILTER_APP_NOTIFICATION_SENSITIVE = new AppFilter() {
|
||||
@Override
|
||||
public void init() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean filterApp(AppEntry info) {
|
||||
return info.extraInfo != null && ((AppRow) info.extraInfo).sensitive;
|
||||
}
|
||||
};
|
||||
}
|
@@ -15,7 +15,7 @@ public class AppViewHolder {
|
||||
public View rootView;
|
||||
public TextView appName;
|
||||
public ImageView appIcon;
|
||||
public TextView appSize;
|
||||
public TextView summary;
|
||||
public TextView disabled;
|
||||
public CheckBox checkBox;
|
||||
|
||||
@@ -29,7 +29,7 @@ public class AppViewHolder {
|
||||
holder.rootView = convertView;
|
||||
holder.appName = (TextView) convertView.findViewById(R.id.app_name);
|
||||
holder.appIcon = (ImageView) convertView.findViewById(R.id.app_icon);
|
||||
holder.appSize = (TextView) convertView.findViewById(R.id.app_size);
|
||||
holder.summary = (TextView) convertView.findViewById(R.id.app_size);
|
||||
holder.disabled = (TextView) convertView.findViewById(R.id.app_disabled);
|
||||
holder.checkBox = (CheckBox) convertView.findViewById(R.id.app_on_sdcard);
|
||||
convertView.setTag(holder);
|
||||
@@ -42,22 +42,22 @@ public class AppViewHolder {
|
||||
}
|
||||
|
||||
void updateSizeText(CharSequence invalidSizeStr, int whichSize) {
|
||||
if (ManageApplications.DEBUG) Log.i(ManageApplications.TAG, "updateSizeText of " + entry.label + " " + entry
|
||||
+ ": " + entry.sizeStr);
|
||||
if (ManageApplications.DEBUG) Log.i(ManageApplications.TAG, "updateSizeText of "
|
||||
+ entry.label + " " + entry + ": " + entry.sizeStr);
|
||||
if (entry.sizeStr != null) {
|
||||
switch (whichSize) {
|
||||
case ManageApplications.SIZE_INTERNAL:
|
||||
appSize.setText(entry.internalSizeStr);
|
||||
summary.setText(entry.internalSizeStr);
|
||||
break;
|
||||
case ManageApplications.SIZE_EXTERNAL:
|
||||
appSize.setText(entry.externalSizeStr);
|
||||
summary.setText(entry.externalSizeStr);
|
||||
break;
|
||||
default:
|
||||
appSize.setText(entry.sizeStr);
|
||||
summary.setText(entry.sizeStr);
|
||||
break;
|
||||
}
|
||||
} else if (entry.size == ApplicationsState.SIZE_INVALID) {
|
||||
appSize.setText(invalidSizeStr);
|
||||
summary.setText(invalidSizeStr);
|
||||
}
|
||||
}
|
||||
}
|
@@ -57,6 +57,7 @@ public class ApplicationsState {
|
||||
public void onPackageSizeChanged(String packageName);
|
||||
public void onAllSizesComputed();
|
||||
public void onLauncherInfoChanged();
|
||||
public void onLoadEntriesCompleted();
|
||||
}
|
||||
|
||||
public static interface AppFilter {
|
||||
@@ -125,6 +126,9 @@ public class ApplicationsState {
|
||||
|
||||
String normalizedLabel;
|
||||
|
||||
// A location where extra info can be placed to be used by custom filters.
|
||||
Object extraInfo;
|
||||
|
||||
AppEntry(Context context, ApplicationInfo info, long id) {
|
||||
apkFile = new File(info.sourceDir);
|
||||
this.id = id;
|
||||
@@ -444,6 +448,7 @@ public class ApplicationsState {
|
||||
static final int MSG_ALL_SIZES_COMPUTED = 5;
|
||||
static final int MSG_RUNNING_STATE_CHANGED = 6;
|
||||
static final int MSG_LAUNCHER_INFO_CHANGED = 7;
|
||||
static final int MSG_LOAD_ENTRIES_COMPLETE = 8;
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
@@ -487,6 +492,11 @@ public class ApplicationsState {
|
||||
mActiveSessions.get(i).mCallbacks.onLauncherInfoChanged();
|
||||
}
|
||||
} break;
|
||||
case MSG_LOAD_ENTRIES_COMPLETE: {
|
||||
for (int i=0; i<mActiveSessions.size(); i++) {
|
||||
mActiveSessions.get(i).mCallbacks.onLoadEntriesCompleted();
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -552,6 +562,10 @@ public class ApplicationsState {
|
||||
}
|
||||
}
|
||||
|
||||
Looper getBackgroundLooper() {
|
||||
return mThread.getLooper();
|
||||
}
|
||||
|
||||
public class Session {
|
||||
final Callbacks mCallbacks;
|
||||
boolean mResumed;
|
||||
@@ -1131,6 +1145,9 @@ public class ApplicationsState {
|
||||
if (numDone >= 6) {
|
||||
sendEmptyMessage(MSG_LOAD_ENTRIES);
|
||||
} else {
|
||||
if (!mMainHandler.hasMessages(MainHandler.MSG_LOAD_ENTRIES_COMPLETE)) {
|
||||
mMainHandler.sendEmptyMessage(MainHandler.MSG_LOAD_ENTRIES_COMPLETE);
|
||||
}
|
||||
sendEmptyMessage(MSG_LOAD_LAUNCHER);
|
||||
}
|
||||
} break;
|
||||
|
@@ -62,9 +62,8 @@ import com.android.settings.Utils;
|
||||
import com.android.settings.applications.ApplicationsState.AppEntry;
|
||||
import com.android.settings.net.ChartData;
|
||||
import com.android.settings.net.ChartDataLoader;
|
||||
import com.android.settings.notification.NotificationAppList;
|
||||
import com.android.settings.notification.NotificationAppList.AppRow;
|
||||
import com.android.settings.notification.NotificationAppList.Backend;
|
||||
import com.android.settings.notification.NotificationBackend;
|
||||
import com.android.settings.notification.NotificationBackend.AppRow;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
@@ -122,7 +121,7 @@ public class InstalledAppDetails extends AppInfoBase
|
||||
|
||||
private boolean mDisableAfterUninstall;
|
||||
// Used for updating notification preference.
|
||||
private final Backend mBackend = new Backend();
|
||||
private final NotificationBackend mBackend = new NotificationBackend();
|
||||
|
||||
private ChartData mChartData;
|
||||
private INetworkStatsSession mStatsSession;
|
||||
@@ -636,13 +635,16 @@ public class InstalledAppDetails extends AppInfoBase
|
||||
}
|
||||
|
||||
public static CharSequence getNotificationSummary(AppEntry appEntry, Context context) {
|
||||
return getNotificationSummary(appEntry, context, new Backend());
|
||||
return getNotificationSummary(appEntry, context, new NotificationBackend());
|
||||
}
|
||||
|
||||
public static CharSequence getNotificationSummary(AppEntry appEntry, Context context,
|
||||
Backend backend) {
|
||||
AppRow appRow = NotificationAppList.loadAppRow(context.getPackageManager(), appEntry.info,
|
||||
backend);
|
||||
NotificationBackend backend) {
|
||||
AppRow appRow = backend.loadAppRow(context.getPackageManager(), appEntry.info);
|
||||
return getNotificationSummary(appRow, context);
|
||||
}
|
||||
|
||||
public static CharSequence getNotificationSummary(AppRow appRow, Context context) {
|
||||
if (appRow.banned) {
|
||||
return context.getString(R.string.notifications_disabled);
|
||||
} else if (appRow.priority) {
|
||||
|
@@ -54,10 +54,13 @@ import android.widget.Spinner;
|
||||
import com.android.internal.content.PackageHelper;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Settings.AllApplicationsActivity;
|
||||
import com.android.settings.Settings.NotificationAppListActivity;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.applications.ApplicationsState.AppEntry;
|
||||
import com.android.settings.applications.ApplicationsState.AppFilter;
|
||||
import com.android.settings.notification.NotificationBackend;
|
||||
import com.android.settings.notification.NotificationBackend.AppRow;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -135,8 +138,11 @@ public class ManageApplications extends Fragment implements OnItemClickListener,
|
||||
public static final int FILTER_APPS_ALL = 1;
|
||||
public static final int FILTER_APPS_ENABLED = 2;
|
||||
public static final int FILTER_APPS_DISABLED = 3;
|
||||
public static final int FILTER_APPS_PERSONAL = 4;
|
||||
public static final int FILTER_APPS_WORK = 5;
|
||||
public static final int FILTER_APPS_BLOCKED = 4;
|
||||
public static final int FILTER_APPS_PRIORITY = 5;
|
||||
public static final int FILTER_APPS_SENSITIVE = 6;
|
||||
public static final int FILTER_APPS_PERSONAL = 7;
|
||||
public static final int FILTER_APPS_WORK = 8;
|
||||
|
||||
// This is the string labels for the filter modes above, the order must be kept in sync.
|
||||
public static final int[] FILTER_LABELS = new int[] {
|
||||
@@ -144,6 +150,9 @@ public class ManageApplications extends Fragment implements OnItemClickListener,
|
||||
R.string.filter_all_apps, // All apps
|
||||
R.string.filter_enabled_apps, // Enabled
|
||||
R.string.filter_apps_disabled, // Disabled
|
||||
R.string.filter_notif_blocked_apps, // Blocked Notifications
|
||||
R.string.filter_notif_priority_apps, // Priority Notifications
|
||||
R.string.filter_notif_sensitive_apps, // Sensitive Notifications
|
||||
R.string.filter_personal_apps, // Personal
|
||||
R.string.filter_work_apps, // Work
|
||||
};
|
||||
@@ -154,6 +163,9 @@ public class ManageApplications extends Fragment implements OnItemClickListener,
|
||||
ApplicationsState.FILTER_EVERYTHING, // All apps
|
||||
ApplicationsState.FILTER_ALL_ENABLED, // Enabled
|
||||
ApplicationsState.FILTER_DISABLED, // Disabled
|
||||
AppStateNotificationBridge.FILTER_APP_NOTIFICATION_BLOCKED, // Blocked Notifications
|
||||
AppStateNotificationBridge.FILTER_APP_NOTIFICATION_PRIORITY, // Priority Notifications
|
||||
AppStateNotificationBridge.FILTER_APP_NOTIFICATION_SENSITIVE, // Sensitive Notifications
|
||||
ApplicationsState.FILTER_PERSONAL, // Personal
|
||||
ApplicationsState.FILTER_WORK, // Work
|
||||
};
|
||||
@@ -194,12 +206,14 @@ public class ManageApplications extends Fragment implements OnItemClickListener,
|
||||
|
||||
public static final int LIST_TYPE_MAIN = 0;
|
||||
public static final int LIST_TYPE_ALL = 1;
|
||||
public static final int LIST_TYPE_NOTIFICATION = 2;
|
||||
|
||||
private View mRootView;
|
||||
|
||||
private View mSpinnerHeader;
|
||||
private Spinner mFilterSpinner;
|
||||
private FilterSpinnerAdapter mFilterAdapter;
|
||||
private NotificationBackend mNotifBackend;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
@@ -214,9 +228,11 @@ public class ManageApplications extends Fragment implements OnItemClickListener,
|
||||
if (className == null) {
|
||||
className = intent.getComponent().getClassName();
|
||||
}
|
||||
if (Settings.ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS.equals(action)
|
||||
|| className.equals(AllApplicationsActivity.class.getName())) {
|
||||
if (className.equals(AllApplicationsActivity.class.getName())) {
|
||||
mListType = LIST_TYPE_ALL;
|
||||
} else if (className.equals(NotificationAppListActivity.class.getName())) {
|
||||
mListType = LIST_TYPE_NOTIFICATION;
|
||||
mNotifBackend = new NotificationBackend();
|
||||
} else {
|
||||
mListType = LIST_TYPE_MAIN;
|
||||
}
|
||||
@@ -289,6 +305,11 @@ public class ManageApplications extends Fragment implements OnItemClickListener,
|
||||
mFilterAdapter.enableFilter(FILTER_APPS_WORK);
|
||||
}
|
||||
}
|
||||
if (mListType == LIST_TYPE_NOTIFICATION) {
|
||||
mFilterAdapter.enableFilter(FILTER_APPS_BLOCKED);
|
||||
mFilterAdapter.enableFilter(FILTER_APPS_PRIORITY);
|
||||
mFilterAdapter.enableFilter(FILTER_APPS_SENSITIVE);
|
||||
}
|
||||
}
|
||||
|
||||
private int getDefaultFilter() {
|
||||
@@ -335,19 +356,30 @@ public class ManageApplications extends Fragment implements OnItemClickListener,
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (requestCode == INSTALLED_APP_DETAILS && mCurrentPkgName != null) {
|
||||
mApplicationsState.requestSize(mCurrentPkgName, UserHandle.getUserId(mCurrentUid));
|
||||
if (mListType == LIST_TYPE_NOTIFICATION) {
|
||||
mApplications.mNotifBridge.forceUpdate(mCurrentPkgName, mCurrentUid);
|
||||
} else {
|
||||
mApplicationsState.requestSize(mCurrentPkgName, UserHandle.getUserId(mCurrentUid));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// utility method used to start sub activity
|
||||
private void startApplicationDetailsActivity() {
|
||||
// TODO: Figure out if there is a way where we can spin up the profile's settings
|
||||
// process ahead of time, to avoid a long load of data when user clicks on a managed app.
|
||||
// Maybe when they load the list of apps that contains managed profile apps.
|
||||
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
||||
intent.setData(Uri.fromParts("package", mCurrentPkgName, null));
|
||||
getActivity().startActivityAsUser(intent,
|
||||
new UserHandle(UserHandle.getUserId(mCurrentUid)));
|
||||
if (mListType == LIST_TYPE_NOTIFICATION) {
|
||||
getActivity().startActivity(new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
.putExtra(Settings.EXTRA_APP_PACKAGE, mCurrentPkgName)
|
||||
.putExtra(Settings.EXTRA_APP_UID, mCurrentUid));
|
||||
} else {
|
||||
// TODO: Figure out if there is a way where we can spin up the profile's settings
|
||||
// process ahead of time, to avoid a long load of data when user clicks on a managed app.
|
||||
// Maybe when they load the list of apps that contains managed profile apps.
|
||||
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
||||
intent.setData(Uri.fromParts("package", mCurrentPkgName, null));
|
||||
getActivity().startActivityAsUser(intent,
|
||||
new UserHandle(UserHandle.getUserId(mCurrentUid)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -517,12 +549,14 @@ public class ManageApplications extends Fragment implements OnItemClickListener,
|
||||
* The order of applications in the list is mirrored in mAppLocalList
|
||||
*/
|
||||
static class ApplicationsAdapter extends BaseAdapter implements Filterable,
|
||||
ApplicationsState.Callbacks, AbsListView.RecyclerListener {
|
||||
ApplicationsState.Callbacks, AppStateNotificationBridge.Callback,
|
||||
AbsListView.RecyclerListener {
|
||||
private final ApplicationsState mState;
|
||||
private final ApplicationsState.Session mSession;
|
||||
private final ManageApplications mManageApplications;
|
||||
private final Context mContext;
|
||||
private final ArrayList<View> mActive = new ArrayList<View>();
|
||||
private final AppStateNotificationBridge mNotifBridge;
|
||||
private int mFilterMode;
|
||||
private ArrayList<ApplicationsState.AppEntry> mBaseEntries;
|
||||
private ArrayList<ApplicationsState.AppEntry> mEntries;
|
||||
@@ -558,6 +592,13 @@ public class ManageApplications extends Fragment implements OnItemClickListener,
|
||||
mManageApplications = manageApplications;
|
||||
mContext = manageApplications.getActivity();
|
||||
mFilterMode = filterMode;
|
||||
if (mManageApplications.mListType == LIST_TYPE_NOTIFICATION) {
|
||||
mNotifBridge = new AppStateNotificationBridge(
|
||||
mContext.getPackageManager(), mState,
|
||||
manageApplications.mNotifBackend, this);
|
||||
} else {
|
||||
mNotifBridge = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void setFilter(int filter) {
|
||||
@@ -571,6 +612,9 @@ public class ManageApplications extends Fragment implements OnItemClickListener,
|
||||
mResumed = true;
|
||||
mSession.resume();
|
||||
mLastSortMode = sort;
|
||||
if (mNotifBridge != null) {
|
||||
mNotifBridge.resume();
|
||||
}
|
||||
rebuild(true);
|
||||
} else {
|
||||
rebuild(sort);
|
||||
@@ -581,11 +625,17 @@ public class ManageApplications extends Fragment implements OnItemClickListener,
|
||||
if (mResumed) {
|
||||
mResumed = false;
|
||||
mSession.pause();
|
||||
if (mNotifBridge != null) {
|
||||
mNotifBridge.pause();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void release() {
|
||||
mSession.release();
|
||||
if (mNotifBridge != null) {
|
||||
mNotifBridge.release();
|
||||
}
|
||||
}
|
||||
|
||||
public void rebuild(int sort) {
|
||||
@@ -680,6 +730,13 @@ public class ManageApplications extends Fragment implements OnItemClickListener,
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotificationInfoUpdated() {
|
||||
if (mFilterMode != mManageApplications.getDefaultFilter()) {
|
||||
rebuild(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRunningStateChanged(boolean running) {
|
||||
mManageApplications.getActivity().setProgressBarIndeterminateVisibility(running);
|
||||
@@ -711,13 +768,20 @@ public class ManageApplications extends Fragment implements OnItemClickListener,
|
||||
// don't care about icons loaded in the background.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadEntriesCompleted() {
|
||||
// No op.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPackageSizeChanged(String packageName) {
|
||||
for (int i=0; i<mActive.size(); i++) {
|
||||
AppViewHolder holder = (AppViewHolder)mActive.get(i).getTag();
|
||||
if (holder.entry.info.packageName.equals(packageName)) {
|
||||
synchronized (holder.entry) {
|
||||
holder.updateSizeText(mManageApplications.mInvalidSizeStr, mWhichSize);
|
||||
if (mManageApplications.mListType != LIST_TYPE_NOTIFICATION) {
|
||||
holder.updateSizeText(mManageApplications.mInvalidSizeStr, mWhichSize);
|
||||
}
|
||||
}
|
||||
if (holder.entry.info.packageName.equals(mManageApplications.mCurrentPkgName)
|
||||
&& mLastSortMode == SORT_ORDER_SIZE) {
|
||||
@@ -780,7 +844,16 @@ public class ManageApplications extends Fragment implements OnItemClickListener,
|
||||
if (entry.icon != null) {
|
||||
holder.appIcon.setImageDrawable(entry.icon);
|
||||
}
|
||||
holder.updateSizeText(mManageApplications.mInvalidSizeStr, mWhichSize);
|
||||
if (mManageApplications.mListType == LIST_TYPE_NOTIFICATION) {
|
||||
if (entry.extraInfo != null) {
|
||||
holder.summary.setText(InstalledAppDetails.getNotificationSummary(
|
||||
(AppRow) entry.extraInfo, mContext));
|
||||
} else {
|
||||
holder.summary.setText("");
|
||||
}
|
||||
} else {
|
||||
holder.updateSizeText(mManageApplications.mInvalidSizeStr, mWhichSize);
|
||||
}
|
||||
if ((entry.info.flags&ApplicationInfo.FLAG_INSTALLED) == 0) {
|
||||
holder.disabled.setVisibility(View.VISIBLE);
|
||||
holder.disabled.setText(R.string.not_installed);
|
||||
|
@@ -16,11 +16,15 @@
|
||||
|
||||
package com.android.settings.notification;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.os.Bundle;
|
||||
import android.preference.Preference;
|
||||
import android.preference.Preference.OnPreferenceChangeListener;
|
||||
@@ -36,8 +40,9 @@ import com.android.settings.AppHeader;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.notification.NotificationAppList.AppRow;
|
||||
import com.android.settings.notification.NotificationAppList.Backend;
|
||||
import com.android.settings.notification.NotificationBackend.AppRow;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/** These settings are per app, so should not be returned in global search results. */
|
||||
public class AppNotificationSettings extends SettingsPreferenceFragment {
|
||||
@@ -52,7 +57,11 @@ public class AppNotificationSettings extends SettingsPreferenceFragment {
|
||||
static final String EXTRA_HAS_SETTINGS_INTENT = "has_settings_intent";
|
||||
static final String EXTRA_SETTINGS_INTENT = "settings_intent";
|
||||
|
||||
private final Backend mBackend = new Backend();
|
||||
private static final Intent APP_NOTIFICATION_PREFS_CATEGORY_INTENT
|
||||
= new Intent(Intent.ACTION_MAIN)
|
||||
.addCategory(Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCES);
|
||||
|
||||
private final NotificationBackend mBackend = new NotificationBackend();
|
||||
|
||||
private Context mContext;
|
||||
private SwitchPreference mBlock;
|
||||
@@ -115,7 +124,8 @@ public class AppNotificationSettings extends SettingsPreferenceFragment {
|
||||
mPeekable = (SwitchPreference) findPreference(KEY_PEEKABLE);
|
||||
mSensitive = (SwitchPreference) findPreference(KEY_SENSITIVE);
|
||||
|
||||
mAppRow = NotificationAppList.loadAppRow(pm, info.applicationInfo, mBackend);
|
||||
mAppRow = mBackend.loadAppRow(pm, info.applicationInfo);
|
||||
|
||||
if (intent.hasExtra(EXTRA_HAS_SETTINGS_INTENT)) {
|
||||
// use settings intent from extra
|
||||
if (intent.getBooleanExtra(EXTRA_HAS_SETTINGS_INTENT, false)) {
|
||||
@@ -125,7 +135,7 @@ public class AppNotificationSettings extends SettingsPreferenceFragment {
|
||||
// load settings intent
|
||||
ArrayMap<String, AppRow> rows = new ArrayMap<String, AppRow>();
|
||||
rows.put(mAppRow.pkg, mAppRow);
|
||||
NotificationAppList.collectConfigActivities(getPackageManager(), rows);
|
||||
collectConfigActivities(getPackageManager(), rows);
|
||||
}
|
||||
|
||||
mBlock.setChecked(mAppRow.banned);
|
||||
@@ -225,4 +235,44 @@ public class AppNotificationSettings extends SettingsPreferenceFragment {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<ResolveInfo> queryNotificationConfigActivities(PackageManager pm) {
|
||||
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,
|
||||
0 //PackageManager.MATCH_DEFAULT_ONLY
|
||||
);
|
||||
return resolveInfos;
|
||||
}
|
||||
|
||||
public static void collectConfigActivities(PackageManager pm, ArrayMap<String, AppRow> rows) {
|
||||
final List<ResolveInfo> resolveInfos = queryNotificationConfigActivities(pm);
|
||||
applyConfigActivities(pm, rows, resolveInfos);
|
||||
}
|
||||
|
||||
public static void applyConfigActivities(PackageManager pm, ArrayMap<String, AppRow> rows,
|
||||
List<ResolveInfo> resolveInfos) {
|
||||
if (DEBUG) Log.d(TAG, "Found " + resolveInfos.size() + " preference activities"
|
||||
+ (resolveInfos.size() == 0 ? " ;_;" : ""));
|
||||
for (ResolveInfo ri : resolveInfos) {
|
||||
final ActivityInfo activityInfo = ri.activityInfo;
|
||||
final ApplicationInfo appInfo = activityInfo.applicationInfo;
|
||||
final AppRow row = rows.get(appInfo.packageName);
|
||||
if (row == null) {
|
||||
if (DEBUG) Log.v(TAG, "Ignoring notification preference activity ("
|
||||
+ activityInfo.name + ") for unknown package "
|
||||
+ activityInfo.packageName);
|
||||
continue;
|
||||
}
|
||||
if (row.settingsIntent != null) {
|
||||
if (DEBUG) Log.v(TAG, "Ignoring duplicate notification preference activity ("
|
||||
+ activityInfo.name + ") for package "
|
||||
+ activityInfo.packageName);
|
||||
continue;
|
||||
}
|
||||
row.settingsIntent = new Intent(APP_NOTIFICATION_PREFS_CATEGORY_INTENT)
|
||||
.setClassName(activityInfo.packageName, activityInfo.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,623 +0,0 @@
|
||||
/*
|
||||
* 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 static com.android.settings.notification.AppNotificationSettings.EXTRA_HAS_SETTINGS_INTENT;
|
||||
import static com.android.settings.notification.AppNotificationSettings.EXTRA_SETTINGS_INTENT;
|
||||
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
|
||||
import android.animation.LayoutTransition;
|
||||
import android.app.INotificationManager;
|
||||
import android.app.Notification;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.LauncherActivityInfo;
|
||||
import android.content.pm.LauncherApps;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.Signature;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Parcelable;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.SystemClock;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Settings;
|
||||
import android.service.notification.NotificationListenerService;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewGroup.LayoutParams;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.OnItemSelectedListener;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.SectionIndexer;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.settings.PinnedHeaderListFragment;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Settings.NotificationAppListActivity;
|
||||
import com.android.settings.UserSpinnerAdapter;
|
||||
import com.android.settings.Utils;
|
||||
|
||||
import java.text.Collator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
/** Just a sectioned list of installed applications, nothing else to index **/
|
||||
public class NotificationAppList extends PinnedHeaderListFragment
|
||||
implements OnItemSelectedListener {
|
||||
private static final String TAG = "NotificationAppList";
|
||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
|
||||
private static final String EMPTY_SUBTITLE = "";
|
||||
private static final String SECTION_BEFORE_A = "*";
|
||||
private static final String SECTION_AFTER_Z = "**";
|
||||
private static final Intent APP_NOTIFICATION_PREFS_CATEGORY_INTENT
|
||||
= new Intent(Intent.ACTION_MAIN)
|
||||
.addCategory(Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCES);
|
||||
|
||||
private final Handler mHandler = new Handler();
|
||||
private final ArrayMap<String, AppRow> mRows = new ArrayMap<String, AppRow>();
|
||||
private final ArrayList<AppRow> mSortedRows = new ArrayList<AppRow>();
|
||||
private final ArrayList<String> mSections = new ArrayList<String>();
|
||||
|
||||
private Context mContext;
|
||||
private LayoutInflater mInflater;
|
||||
private NotificationAppAdapter mAdapter;
|
||||
private Signature[] mSystemSignature;
|
||||
private Parcelable mListViewState;
|
||||
private Backend mBackend = new Backend();
|
||||
private UserSpinnerAdapter mProfileSpinnerAdapter;
|
||||
private Spinner mSpinner;
|
||||
|
||||
private PackageManager mPM;
|
||||
private UserManager mUM;
|
||||
private LauncherApps mLauncherApps;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mContext = getActivity();
|
||||
mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
mAdapter = new NotificationAppAdapter(mContext);
|
||||
mUM = UserManager.get(mContext);
|
||||
mPM = mContext.getPackageManager();
|
||||
mLauncherApps = (LauncherApps) mContext.getSystemService(Context.LAUNCHER_APPS_SERVICE);
|
||||
getActivity().setTitle(R.string.app_notifications_title);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.notification_app_list, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
mProfileSpinnerAdapter = Utils.createUserSpinnerAdapter(mUM, mContext);
|
||||
if (mProfileSpinnerAdapter != null) {
|
||||
mSpinner = (Spinner) getActivity().getLayoutInflater().inflate(
|
||||
R.layout.spinner_view, null);
|
||||
mSpinner.setAdapter(mProfileSpinnerAdapter);
|
||||
mSpinner.setOnItemSelectedListener(this);
|
||||
// Set layout parameters, otherwise we get the default ones
|
||||
mSpinner.setLayoutParams(new LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
|
||||
setPinnedHeaderView(mSpinner);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
repositionScrollbar();
|
||||
getListView().setAdapter(mAdapter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
if (DEBUG) Log.d(TAG, "Saving listView state");
|
||||
mListViewState = getListView().onSaveInstanceState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
mListViewState = null; // you're dead to me
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
loadAppsList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||
UserHandle selectedUser = mProfileSpinnerAdapter.getUserHandle(position);
|
||||
if (selectedUser.getIdentifier() != UserHandle.myUserId()) {
|
||||
Intent intent = new Intent(getActivity(), NotificationAppListActivity.class);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||
mContext.startActivityAsUser(intent, selectedUser);
|
||||
// Go back to default selection, which is the first one; this makes sure that pressing
|
||||
// the back button takes you into a consistent state
|
||||
mSpinner.setSelection(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> parent) {
|
||||
}
|
||||
|
||||
public void setBackend(Backend backend) {
|
||||
mBackend = backend;
|
||||
}
|
||||
|
||||
private void loadAppsList() {
|
||||
AsyncTask.execute(mCollectAppsRunnable);
|
||||
}
|
||||
|
||||
private String getSection(CharSequence label) {
|
||||
if (label == null || label.length() == 0) return SECTION_BEFORE_A;
|
||||
final char c = Character.toUpperCase(label.charAt(0));
|
||||
if (c < 'A') return SECTION_BEFORE_A;
|
||||
if (c > 'Z') return SECTION_AFTER_Z;
|
||||
return Character.toString(c);
|
||||
}
|
||||
|
||||
private void repositionScrollbar() {
|
||||
final int sbWidthPx = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
|
||||
getListView().getScrollBarSize(),
|
||||
getResources().getDisplayMetrics());
|
||||
final View parent = (View)getView().getParent();
|
||||
final int eat = Math.min(sbWidthPx, parent.getPaddingEnd());
|
||||
if (eat <= 0) return;
|
||||
if (DEBUG) Log.d(TAG, String.format("Eating %dpx into %dpx padding for %dpx scroll, ld=%d",
|
||||
eat, parent.getPaddingEnd(), sbWidthPx, getListView().getLayoutDirection()));
|
||||
parent.setPaddingRelative(parent.getPaddingStart(), parent.getPaddingTop(),
|
||||
parent.getPaddingEnd() - eat, parent.getPaddingBottom());
|
||||
}
|
||||
|
||||
private static class ViewHolder {
|
||||
ViewGroup row;
|
||||
ImageView icon;
|
||||
TextView title;
|
||||
TextView subtitle;
|
||||
View rowDivider;
|
||||
}
|
||||
|
||||
private class NotificationAppAdapter extends ArrayAdapter<Row> implements SectionIndexer {
|
||||
public NotificationAppAdapter(Context context) {
|
||||
super(context, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasStableIds() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getViewTypeCount() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
Row r = getItem(position);
|
||||
return r instanceof AppRow ? 1 : 0;
|
||||
}
|
||||
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
Row r = getItem(position);
|
||||
View v;
|
||||
if (convertView == null) {
|
||||
v = newView(parent, r);
|
||||
} else {
|
||||
v = convertView;
|
||||
}
|
||||
bindView(v, r, false /*animate*/);
|
||||
return v;
|
||||
}
|
||||
|
||||
public View newView(ViewGroup parent, Row r) {
|
||||
if (!(r instanceof AppRow)) {
|
||||
return mInflater.inflate(R.layout.notification_app_section, parent, false);
|
||||
}
|
||||
final View v = mInflater.inflate(R.layout.notification_app, parent, false);
|
||||
final ViewHolder vh = new ViewHolder();
|
||||
vh.row = (ViewGroup) v;
|
||||
vh.row.setLayoutTransition(new LayoutTransition());
|
||||
vh.row.setLayoutTransition(new LayoutTransition());
|
||||
vh.icon = (ImageView) v.findViewById(android.R.id.icon);
|
||||
vh.title = (TextView) v.findViewById(android.R.id.title);
|
||||
vh.subtitle = (TextView) v.findViewById(android.R.id.text1);
|
||||
vh.rowDivider = v.findViewById(R.id.row_divider);
|
||||
v.setTag(vh);
|
||||
return v;
|
||||
}
|
||||
|
||||
private void enableLayoutTransitions(ViewGroup vg, boolean enabled) {
|
||||
if (enabled) {
|
||||
vg.getLayoutTransition().enableTransitionType(LayoutTransition.APPEARING);
|
||||
vg.getLayoutTransition().enableTransitionType(LayoutTransition.DISAPPEARING);
|
||||
} else {
|
||||
vg.getLayoutTransition().disableTransitionType(LayoutTransition.APPEARING);
|
||||
vg.getLayoutTransition().disableTransitionType(LayoutTransition.DISAPPEARING);
|
||||
}
|
||||
}
|
||||
|
||||
public void bindView(final View view, Row r, boolean animate) {
|
||||
if (!(r instanceof AppRow)) {
|
||||
// it's a section row
|
||||
final TextView tv = (TextView)view.findViewById(android.R.id.title);
|
||||
tv.setText(r.section);
|
||||
return;
|
||||
}
|
||||
|
||||
final AppRow row = (AppRow)r;
|
||||
final ViewHolder vh = (ViewHolder) view.getTag();
|
||||
enableLayoutTransitions(vh.row, animate);
|
||||
vh.rowDivider.setVisibility(row.first ? View.GONE : View.VISIBLE);
|
||||
vh.row.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
mContext.startActivity(new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
.putExtra(Settings.EXTRA_APP_PACKAGE, row.pkg)
|
||||
.putExtra(Settings.EXTRA_APP_UID, row.uid)
|
||||
.putExtra(EXTRA_HAS_SETTINGS_INTENT, row.settingsIntent != null)
|
||||
.putExtra(EXTRA_SETTINGS_INTENT, row.settingsIntent));
|
||||
}
|
||||
});
|
||||
enableLayoutTransitions(vh.row, animate);
|
||||
vh.icon.setImageDrawable(row.icon);
|
||||
vh.title.setText(row.label);
|
||||
final String sub = getSubtitle(row);
|
||||
vh.subtitle.setText(sub);
|
||||
vh.subtitle.setVisibility(!sub.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
private String getSubtitle(AppRow row) {
|
||||
if (row.banned) {
|
||||
return mContext.getString(R.string.app_notification_row_banned);
|
||||
}
|
||||
if (!row.priority && !row.sensitive) {
|
||||
return EMPTY_SUBTITLE;
|
||||
}
|
||||
final String priString = mContext.getString(R.string.app_notification_row_priority);
|
||||
final String senString = mContext.getString(R.string.app_notification_row_sensitive);
|
||||
if (row.priority != row.sensitive) {
|
||||
return row.priority ? priString : senString;
|
||||
}
|
||||
return priString + mContext.getString(R.string.summary_divider_text) + senString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getSections() {
|
||||
return mSections.toArray(new Object[mSections.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPositionForSection(int sectionIndex) {
|
||||
final String section = mSections.get(sectionIndex);
|
||||
final int n = getCount();
|
||||
for (int i = 0; i < n; i++) {
|
||||
final Row r = getItem(i);
|
||||
if (r.section.equals(section)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSectionForPosition(int position) {
|
||||
Row row = getItem(position);
|
||||
return mSections.indexOf(row.section);
|
||||
}
|
||||
}
|
||||
|
||||
private static class Row {
|
||||
public String section;
|
||||
}
|
||||
|
||||
public static class AppRow extends Row {
|
||||
public String pkg;
|
||||
public int uid;
|
||||
public Drawable icon;
|
||||
public CharSequence label;
|
||||
public Intent settingsIntent;
|
||||
public boolean banned;
|
||||
public boolean priority;
|
||||
public boolean peekable;
|
||||
public boolean sensitive;
|
||||
public boolean first; // first app in section
|
||||
}
|
||||
|
||||
private static final Comparator<AppRow> mRowComparator = new Comparator<AppRow>() {
|
||||
private final Collator sCollator = Collator.getInstance();
|
||||
@Override
|
||||
public int compare(AppRow lhs, AppRow rhs) {
|
||||
return sCollator.compare(lhs.label, rhs.label);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public static AppRow loadAppRow(PackageManager pm, ApplicationInfo app,
|
||||
Backend backend) {
|
||||
final AppRow row = new AppRow();
|
||||
row.pkg = app.packageName;
|
||||
row.uid = app.uid;
|
||||
try {
|
||||
row.label = app.loadLabel(pm);
|
||||
} catch (Throwable t) {
|
||||
Log.e(TAG, "Error loading application label for " + row.pkg, t);
|
||||
row.label = row.pkg;
|
||||
}
|
||||
row.icon = app.loadIcon(pm);
|
||||
row.banned = backend.getNotificationsBanned(row.pkg, row.uid);
|
||||
row.priority = backend.getHighPriority(row.pkg, row.uid);
|
||||
row.peekable = backend.getPeekable(row.pkg, row.uid);
|
||||
row.sensitive = backend.getSensitive(row.pkg, row.uid);
|
||||
return row;
|
||||
}
|
||||
|
||||
public static List<ResolveInfo> queryNotificationConfigActivities(PackageManager pm) {
|
||||
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,
|
||||
0 //PackageManager.MATCH_DEFAULT_ONLY
|
||||
);
|
||||
return resolveInfos;
|
||||
}
|
||||
public static void collectConfigActivities(PackageManager pm, ArrayMap<String, AppRow> rows) {
|
||||
final List<ResolveInfo> resolveInfos = queryNotificationConfigActivities(pm);
|
||||
applyConfigActivities(pm, rows, resolveInfos);
|
||||
}
|
||||
|
||||
public static void applyConfigActivities(PackageManager pm, ArrayMap<String, AppRow> rows,
|
||||
List<ResolveInfo> resolveInfos) {
|
||||
if (DEBUG) Log.d(TAG, "Found " + resolveInfos.size() + " preference activities"
|
||||
+ (resolveInfos.size() == 0 ? " ;_;" : ""));
|
||||
for (ResolveInfo ri : resolveInfos) {
|
||||
final ActivityInfo activityInfo = ri.activityInfo;
|
||||
final ApplicationInfo appInfo = activityInfo.applicationInfo;
|
||||
final AppRow row = rows.get(appInfo.packageName);
|
||||
if (row == null) {
|
||||
Log.v(TAG, "Ignoring notification preference activity ("
|
||||
+ activityInfo.name + ") for unknown package "
|
||||
+ activityInfo.packageName);
|
||||
continue;
|
||||
}
|
||||
if (row.settingsIntent != null) {
|
||||
Log.v(TAG, "Ignoring duplicate notification preference activity ("
|
||||
+ activityInfo.name + ") for package "
|
||||
+ activityInfo.packageName);
|
||||
continue;
|
||||
}
|
||||
row.settingsIntent = new Intent(APP_NOTIFICATION_PREFS_CATEGORY_INTENT)
|
||||
.setClassName(activityInfo.packageName, activityInfo.name);
|
||||
}
|
||||
}
|
||||
|
||||
private final Runnable mCollectAppsRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (mRows) {
|
||||
final long start = SystemClock.uptimeMillis();
|
||||
if (DEBUG) Log.d(TAG, "Collecting apps...");
|
||||
mRows.clear();
|
||||
mSortedRows.clear();
|
||||
|
||||
// collect all launchable apps, plus any packages that have notification settings
|
||||
final List<ApplicationInfo> appInfos = new ArrayList<ApplicationInfo>();
|
||||
|
||||
final List<LauncherActivityInfo> lais
|
||||
= mLauncherApps.getActivityList(null /* all */,
|
||||
UserHandle.getCallingUserHandle());
|
||||
if (DEBUG) Log.d(TAG, " launchable activities:");
|
||||
for (LauncherActivityInfo lai : lais) {
|
||||
if (DEBUG) Log.d(TAG, " " + lai.getComponentName().toString());
|
||||
appInfos.add(lai.getApplicationInfo());
|
||||
}
|
||||
|
||||
final List<ResolveInfo> resolvedConfigActivities
|
||||
= queryNotificationConfigActivities(mPM);
|
||||
if (DEBUG) Log.d(TAG, " config activities:");
|
||||
for (ResolveInfo ri : resolvedConfigActivities) {
|
||||
if (DEBUG) Log.d(TAG, " "
|
||||
+ ri.activityInfo.packageName + "/" + ri.activityInfo.name);
|
||||
appInfos.add(ri.activityInfo.applicationInfo);
|
||||
}
|
||||
|
||||
for (ApplicationInfo info : appInfos) {
|
||||
final String key = info.packageName;
|
||||
if (mRows.containsKey(key)) {
|
||||
// we already have this app, thanks
|
||||
continue;
|
||||
}
|
||||
|
||||
final AppRow row = loadAppRow(mPM, info, mBackend);
|
||||
mRows.put(key, row);
|
||||
}
|
||||
|
||||
// add config activities to the list
|
||||
applyConfigActivities(mPM, mRows, resolvedConfigActivities);
|
||||
|
||||
// sort rows
|
||||
mSortedRows.addAll(mRows.values());
|
||||
Collections.sort(mSortedRows, mRowComparator);
|
||||
// compute sections
|
||||
mSections.clear();
|
||||
String section = null;
|
||||
for (AppRow r : mSortedRows) {
|
||||
r.section = getSection(r.label);
|
||||
if (!r.section.equals(section)) {
|
||||
section = r.section;
|
||||
mSections.add(section);
|
||||
}
|
||||
}
|
||||
mHandler.post(mRefreshAppsListRunnable);
|
||||
final long elapsed = SystemClock.uptimeMillis() - start;
|
||||
if (DEBUG) Log.d(TAG, "Collected " + mRows.size() + " apps in " + elapsed + "ms");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private void refreshDisplayedItems() {
|
||||
if (DEBUG) Log.d(TAG, "Refreshing apps...");
|
||||
mAdapter.clear();
|
||||
synchronized (mSortedRows) {
|
||||
String section = null;
|
||||
final int N = mSortedRows.size();
|
||||
boolean first = true;
|
||||
for (int i = 0; i < N; i++) {
|
||||
final AppRow row = mSortedRows.get(i);
|
||||
if (!row.section.equals(section)) {
|
||||
section = row.section;
|
||||
Row r = new Row();
|
||||
r.section = section;
|
||||
mAdapter.add(r);
|
||||
first = true;
|
||||
}
|
||||
row.first = first;
|
||||
mAdapter.add(row);
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
if (mListViewState != null) {
|
||||
if (DEBUG) Log.d(TAG, "Restoring listView state");
|
||||
getListView().onRestoreInstanceState(mListViewState);
|
||||
mListViewState = null;
|
||||
}
|
||||
if (DEBUG) Log.d(TAG, "Refreshed " + mSortedRows.size() + " displayed items");
|
||||
}
|
||||
|
||||
private final Runnable mRefreshAppsListRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
refreshDisplayedItems();
|
||||
}
|
||||
};
|
||||
|
||||
public static class Backend {
|
||||
static INotificationManager sINM = INotificationManager.Stub.asInterface(
|
||||
ServiceManager.getService(Context.NOTIFICATION_SERVICE));
|
||||
|
||||
public boolean setNotificationsBanned(String pkg, int uid, boolean banned) {
|
||||
try {
|
||||
sINM.setNotificationsEnabledForPackage(pkg, uid, !banned);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Error calling NoMan", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getNotificationsBanned(String pkg, int uid) {
|
||||
try {
|
||||
final boolean enabled = sINM.areNotificationsEnabledForPackage(pkg, uid);
|
||||
return !enabled;
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Error calling NoMan", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getHighPriority(String pkg, int uid) {
|
||||
try {
|
||||
return sINM.getPackagePriority(pkg, uid) == Notification.PRIORITY_MAX;
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Error calling NoMan", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean setHighPriority(String pkg, int uid, boolean highPriority) {
|
||||
try {
|
||||
sINM.setPackagePriority(pkg, uid,
|
||||
highPriority ? Notification.PRIORITY_MAX : Notification.PRIORITY_DEFAULT);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Error calling NoMan", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getPeekable(String pkg, int uid) {
|
||||
try {
|
||||
return sINM.getPackagePeekable(pkg, uid);
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Error calling NoMan", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean setPeekable(String pkg, int uid, boolean peekable) {
|
||||
try {
|
||||
sINM.setPackagePeekable(pkg, uid, peekable);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Error calling NoMan", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getSensitive(String pkg, int uid) {
|
||||
try {
|
||||
return sINM.getPackageVisibilityOverride(pkg, uid) == Notification.VISIBILITY_PRIVATE;
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Error calling NoMan", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean setSensitive(String pkg, int uid, boolean sensitive) {
|
||||
try {
|
||||
sINM.setPackageVisibilityOverride(pkg, uid,
|
||||
sensitive ? Notification.VISIBILITY_PRIVATE
|
||||
: NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Error calling NoMan", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
150
src/com/android/settings/notification/NotificationBackend.java
Normal file
150
src/com/android/settings/notification/NotificationBackend.java
Normal file
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* 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.notification;
|
||||
|
||||
import android.app.INotificationManager;
|
||||
import android.app.Notification;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.ServiceManager;
|
||||
import android.service.notification.NotificationListenerService;
|
||||
import android.util.Log;
|
||||
|
||||
public class NotificationBackend {
|
||||
private static final String TAG = "NotificationBackend";
|
||||
|
||||
static INotificationManager sINM = INotificationManager.Stub.asInterface(
|
||||
ServiceManager.getService(Context.NOTIFICATION_SERVICE));
|
||||
|
||||
public AppRow loadAppRow(PackageManager pm, ApplicationInfo app) {
|
||||
final AppRow row = new AppRow();
|
||||
row.pkg = app.packageName;
|
||||
row.uid = app.uid;
|
||||
try {
|
||||
row.label = app.loadLabel(pm);
|
||||
} catch (Throwable t) {
|
||||
Log.e(TAG, "Error loading application label for " + row.pkg, t);
|
||||
row.label = row.pkg;
|
||||
}
|
||||
row.icon = app.loadIcon(pm);
|
||||
row.banned = getNotificationsBanned(row.pkg, row.uid);
|
||||
row.priority = getHighPriority(row.pkg, row.uid);
|
||||
row.peekable = getPeekable(row.pkg, row.uid);
|
||||
row.sensitive = getSensitive(row.pkg, row.uid);
|
||||
return row;
|
||||
}
|
||||
|
||||
public boolean setNotificationsBanned(String pkg, int uid, boolean banned) {
|
||||
try {
|
||||
sINM.setNotificationsEnabledForPackage(pkg, uid, !banned);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Error calling NoMan", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getNotificationsBanned(String pkg, int uid) {
|
||||
try {
|
||||
final boolean enabled = sINM.areNotificationsEnabledForPackage(pkg, uid);
|
||||
return !enabled;
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Error calling NoMan", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getHighPriority(String pkg, int uid) {
|
||||
try {
|
||||
return sINM.getPackagePriority(pkg, uid) == Notification.PRIORITY_MAX;
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Error calling NoMan", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean setHighPriority(String pkg, int uid, boolean highPriority) {
|
||||
try {
|
||||
sINM.setPackagePriority(pkg, uid,
|
||||
highPriority ? Notification.PRIORITY_MAX : Notification.PRIORITY_DEFAULT);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Error calling NoMan", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getPeekable(String pkg, int uid) {
|
||||
try {
|
||||
return sINM.getPackagePeekable(pkg, uid);
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Error calling NoMan", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean setPeekable(String pkg, int uid, boolean peekable) {
|
||||
try {
|
||||
sINM.setPackagePeekable(pkg, uid, peekable);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Error calling NoMan", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getSensitive(String pkg, int uid) {
|
||||
try {
|
||||
return sINM.getPackageVisibilityOverride(pkg, uid) == Notification.VISIBILITY_PRIVATE;
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Error calling NoMan", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean setSensitive(String pkg, int uid, boolean sensitive) {
|
||||
try {
|
||||
sINM.setPackageVisibilityOverride(pkg, uid,
|
||||
sensitive ? Notification.VISIBILITY_PRIVATE
|
||||
: NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Error calling NoMan", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static class Row {
|
||||
public String section;
|
||||
}
|
||||
|
||||
public static class AppRow extends Row {
|
||||
public String pkg;
|
||||
public int uid;
|
||||
public Drawable icon;
|
||||
public CharSequence label;
|
||||
public Intent settingsIntent;
|
||||
public boolean banned;
|
||||
public boolean priority;
|
||||
public boolean peekable;
|
||||
public boolean sensitive;
|
||||
public boolean first; // first app in section
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user