App-level notification configuration settings page.
New sub-page off of notification settings to ban/unban apps and navigate to an app's notification configuration activity (if configured). Centralized all notification settings artifacts under a new settings subpackage. Bug: 13935172 Change-Id: I53b75c02f0091900734d17dc9217035d0df9b466
This commit is contained in:
@@ -564,7 +564,7 @@
|
||||
<category android:name="com.android.settings.SHORTCUT" />
|
||||
</intent-filter>
|
||||
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
|
||||
android:value="com.android.settings.ZenModeSettings" />
|
||||
android:value="com.android.settings.notification.ZenModeSettings" />
|
||||
<meta-data android:name="com.android.settings.TOP_LEVEL_HEADER_ID"
|
||||
android:resource="@id/notification_settings" />
|
||||
</activity>
|
||||
@@ -772,7 +772,7 @@
|
||||
<category android:name="com.android.settings.SHORTCUT" />
|
||||
</intent-filter>
|
||||
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
|
||||
android:value="com.android.settings.NotificationStation" />
|
||||
android:value="com.android.settings.notification.NotificationStation" />
|
||||
</activity>
|
||||
|
||||
<!--
|
||||
@@ -1690,7 +1690,7 @@
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
|
||||
android:value="com.android.settings.NotificationAccessSettings" />
|
||||
android:value="com.android.settings.notification.NotificationAccessSettings" />
|
||||
<meta-data android:name="com.android.settings.TOP_LEVEL_HEADER_ID"
|
||||
android:resource="@id/security_settings" />
|
||||
</activity>
|
||||
@@ -1707,7 +1707,7 @@
|
||||
<category android:name="com.android.settings.SHORTCUT" />
|
||||
</intent-filter>
|
||||
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
|
||||
android:value="com.android.settings.NotificationSettings" />
|
||||
android:value="com.android.settings.notification.NotificationSettings" />
|
||||
<meta-data android:name="com.android.settings.TOP_LEVEL_HEADER_ID"
|
||||
android:resource="@id/notification_settings" />
|
||||
</activity>
|
||||
|
BIN
res/drawable-hdpi/ic_settings_generic.png
Normal file
BIN
res/drawable-hdpi/ic_settings_generic.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
BIN
res/drawable-mdpi/ic_settings_generic.png
Normal file
BIN
res/drawable-mdpi/ic_settings_generic.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 969 B |
BIN
res/drawable-xhdpi/ic_settings_generic.png
Normal file
BIN
res/drawable-xhdpi/ic_settings_generic.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.0 KiB |
BIN
res/drawable-xxhdpi/ic_settings_generic.png
Normal file
BIN
res/drawable-xxhdpi/ic_settings_generic.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.9 KiB |
@@ -18,67 +18,76 @@
|
||||
android:layout_height="wrap_content" >
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:id="@android:id/button1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toStartOf="@+id/divider"
|
||||
>
|
||||
android:layout_alignWithParentIfMissing="true"
|
||||
android:layout_toStartOf="@+id/settings_divider"
|
||||
android:background="?android:attr/listChoiceBackgroundIndicator" >
|
||||
|
||||
<ImageView
|
||||
android:id="@android:id/icon"
|
||||
android:layout_width="@android:dimen/app_icon_size"
|
||||
android:layout_height="@android:dimen/app_icon_size"
|
||||
android:layout_width="@dimen/notification_app_icon_size"
|
||||
android:layout_height="@dimen/notification_app_icon_size"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:layout_marginStart="0dp"
|
||||
android:layout_marginEnd="6dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:contentDescription="@null"
|
||||
android:maxHeight="@android:dimen/app_icon_size"
|
||||
android:maxWidth="@android:dimen/app_icon_size"
|
||||
android:scaleType="fitCenter" />
|
||||
android:scaleType="center" />
|
||||
|
||||
<ImageView
|
||||
android:id="@android:id/icon1"
|
||||
android:layout_width="@dimen/notification_app_icon_badge_size"
|
||||
android:layout_height="@dimen/notification_app_icon_badge_size"
|
||||
android:layout_marginLeft="@dimen/notification_app_icon_badge_margin"
|
||||
android:layout_marginTop="@dimen/notification_app_icon_badge_margin"
|
||||
android:background="#bb8b0000"
|
||||
android:contentDescription="@null" />
|
||||
|
||||
<ImageView
|
||||
android:id="@android:id/icon2"
|
||||
android:layout_width="@dimen/notification_app_icon_badge_size"
|
||||
android:layout_height="@dimen/notification_app_icon_badge_size"
|
||||
android:layout_alignBottom="@android:id/icon"
|
||||
android:layout_alignEnd="@android:id/icon"
|
||||
android:layout_marginBottom="@dimen/notification_app_icon_badge_margin"
|
||||
android:layout_marginEnd="@dimen/notification_app_icon_badge_margin"
|
||||
android:background="#bb006400"
|
||||
android:contentDescription="@null" />
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toStartOf="@android:id/button1"
|
||||
android:layout_toEndOf="@android:id/icon"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:textAlignment="viewStart"
|
||||
android:labelFor="@android:id/button2" />
|
||||
|
||||
android:textAppearance="?android:attr/textAppearanceMedium" />
|
||||
</RelativeLayout>
|
||||
|
||||
<!-- Divider -->
|
||||
|
||||
<ImageView
|
||||
android:id="@id/divider"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
<View
|
||||
android:id="@+id/settings_divider"
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="@dimen/notification_app_settings_divider_height"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toStartOf="@android:id/button2"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/nav_divider" />
|
||||
|
||||
<!-- Settings icon -->
|
||||
android:background="?android:attr/listDivider" />
|
||||
|
||||
<ImageView
|
||||
android:id="@android:id/button2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignBottom="@android:id/widget_frame"
|
||||
android:layout_width="@dimen/notification_app_icon_size"
|
||||
android:layout_height="@dimen/notification_app_icon_size"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignTop="@android:id/widget_frame"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_margin="0dip"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:background="?android:attr/listChoiceBackgroundIndicator"
|
||||
android:contentDescription="@string/notification_app_settings_button"
|
||||
android:padding="8dip"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:src="@drawable/ic_bt_config" />
|
||||
android:scaleType="center"
|
||||
android:src="@drawable/ic_settings_generic" />
|
||||
|
||||
<View
|
||||
android:id="@+id/row_divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:attr/listDivider" />
|
||||
|
||||
</RelativeLayout>
|
47
res/layout/notification_app_dialog.xml
Normal file
47
res/layout/notification_app_dialog.xml
Normal file
@@ -0,0 +1,47 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" >
|
||||
|
||||
<ImageView
|
||||
android:id="@android:id/icon"
|
||||
android:layout_width="@dimen/notification_app_icon_size"
|
||||
android:layout_height="@dimen/notification_app_icon_size"
|
||||
android:contentDescription="@null"
|
||||
android:scaleType="center" />
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/notification_app_icon_size"
|
||||
android:layout_toEndOf="@android:id/icon"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center_vertical"
|
||||
android:singleLine="true"
|
||||
android:textAlignment="viewStart"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@android:id/button1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/notification_app_icon_size"
|
||||
android:layout_below="@android:id/icon"
|
||||
android:layout_marginStart="@dimen/content_margin_left"
|
||||
android:text="@string/app_notifications_dialog_show"
|
||||
android:textAppearance="?android:attr/textAppearanceListItem" />
|
||||
|
||||
</RelativeLayout>
|
42
res/layout/notification_app_list.xml
Normal file
42
res/layout/notification_app_list.xml
Normal file
@@ -0,0 +1,42 @@
|
||||
<?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:divider="#0000"
|
||||
android:dividerHeight="0px"
|
||||
android:fastScrollAlwaysVisible="true"
|
||||
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>
|
19
res/layout/notification_app_section.xml
Normal file
19
res/layout/notification_app_section.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
style="?android:attr/listSeparatorTextViewStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
@@ -1,115 +0,0 @@
|
||||
<!--
|
||||
Copyright (C) 2013 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.
|
||||
-->
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" >
|
||||
|
||||
<!-- Dream selectable row (icon, caption, radio button) -->
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@android:id/widget_frame"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toStartOf="@+id/divider"
|
||||
android:background="?android:attr/selectableItemBackground" >
|
||||
|
||||
<!-- Dream icon -->
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/pkgicon"
|
||||
android:layout_width="@*android:dimen/status_bar_icon_size"
|
||||
android:layout_height="@*android:dimen/status_bar_icon_size"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:layout_marginStart="0dp"
|
||||
android:layout_marginEnd="6dp"
|
||||
android:layout_marginTop="6dp"
|
||||
android:contentDescription="@null"
|
||||
android:maxHeight="@*android:dimen/status_bar_icon_size"
|
||||
android:maxWidth="@*android:dimen/status_bar_icon_size"
|
||||
android:scaleType="fitCenter" />
|
||||
|
||||
<ImageView
|
||||
android:id="@android:id/icon"
|
||||
android:layout_width="@*android:dimen/status_bar_icon_size"
|
||||
android:layout_height="@*android:dimen/status_bar_icon_size"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toEndOf="@id/pkgicon"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:layout_marginStart="0dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginTop="6dp"
|
||||
android:contentDescription="@null"
|
||||
android:maxHeight="@*android:dimen/status_bar_icon_size"
|
||||
android:maxWidth="@*android:dimen/status_bar_icon_size"
|
||||
android:scaleType="fitCenter" />
|
||||
|
||||
<!-- Dream caption -->
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toStartOf="@android:id/button1"
|
||||
android:layout_toEndOf="@android:id/icon"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textAlignment="viewStart"
|
||||
android:labelFor="@android:id/button2" />
|
||||
|
||||
<!-- Dream radio button -->
|
||||
|
||||
<!--<RadioButton
|
||||
android:id="@android:id/button1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:duplicateParentState="true"
|
||||
android:clickable="false"
|
||||
android:focusable="false" />-->
|
||||
</RelativeLayout>
|
||||
|
||||
<!-- Divider -->
|
||||
|
||||
<ImageView
|
||||
android:id="@id/divider"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toStartOf="@android:id/button2"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/nav_divider" />
|
||||
|
||||
<!-- Settings icon -->
|
||||
|
||||
<ImageView
|
||||
android:id="@android:id/button2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignBottom="@android:id/widget_frame"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignTop="@android:id/widget_frame"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_margin="0dip"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:contentDescription="@string/screensaver_settings_button"
|
||||
android:padding="8dip"
|
||||
android:src="@drawable/ic_bt_config" />
|
||||
|
||||
</RelativeLayout>
|
@@ -33,7 +33,7 @@
|
||||
android:layout_width="@*android:dimen/status_bar_icon_size"
|
||||
android:layout_height="@*android:dimen/status_bar_icon_size"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toEndOf="@id/pkgicon"
|
||||
android:layout_toEndOf="@+id/pkgicon"
|
||||
android:layout_marginStart="0dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:contentDescription="@null"
|
||||
|
@@ -78,4 +78,9 @@
|
||||
<integer name="preferences_left_pane_weight">4</integer>
|
||||
<!-- Weight of the right pane in a multi-pane preference layout. So the split is 40:60 -->
|
||||
<integer name="preferences_right_pane_weight">6</integer>
|
||||
|
||||
<dimen name="notification_app_icon_size">64dp</dimen>
|
||||
<dimen name="notification_app_icon_badge_size">20dp</dimen>
|
||||
<dimen name="notification_app_icon_badge_margin">4dp</dimen>
|
||||
<dimen name="notification_app_settings_divider_height">48dp</dimen>
|
||||
</resources>
|
||||
|
@@ -1767,9 +1767,7 @@
|
||||
<!-- Sound settings screen, notification light repeat pulsing title -->
|
||||
<string name="notification_pulse_title">Pulse notification light</string>
|
||||
<!-- Display settings screen, notification popups are enabled [CHAR LIMIT=30] -->
|
||||
<string name="heads_up_enabled_title">Heads Up Notifications</string>
|
||||
<!-- Display settings screen, notification popups are explained [CHAR LIMIT=45]-->
|
||||
<string name="heads_up_enabled_summary">Important notifications will pop up</string>
|
||||
<string name="heads_up_enabled_title">Pop up if high priority</string>
|
||||
<!-- Sound settings screen, the title of the volume bar to adjust the incoming call volume -->
|
||||
<string name="incoming_call_volume_title">Ringtone</string>
|
||||
<!-- Sound settings screen, the title of the volume bar to adjust the notification volume -->
|
||||
@@ -5027,38 +5025,31 @@
|
||||
<!-- Notifications on lockscreen -->
|
||||
<!-- Label for checkbox controlling the contents of notifications shown on
|
||||
the secure lockscreen [CHAR LIMIT=25] -->
|
||||
<string name="lock_screen_notifications">Show when locked</string>
|
||||
<string name="lock_screen_notifications">Show on lock screen</string>
|
||||
<!-- Summary for lock_screen_notifications: sensitive information will be
|
||||
hidden or redacted from notifications shown on a secure lock screen
|
||||
[CHAR LIMIT=50] -->
|
||||
<string name="lock_screen_notifications_summary_off">Sensitive notification contents will be hidden on the lock screen</string>
|
||||
<string name="lock_screen_notifications_summary_off">Unless content is sensitive</string>
|
||||
<!-- Summary for lock_screen_notifications: all information will be
|
||||
shown in notifications shown on a secure lock screen
|
||||
[CHAR LIMIT=50] -->
|
||||
<string name="lock_screen_notifications_summary_on">All notification contents will be shown on the lock screen</string>
|
||||
<string name="lock_screen_notifications_summary_on">All notifications</string>
|
||||
|
||||
<!-- [CHAR LIMIT=30] Notification settings screen, setting option name -->
|
||||
<string name="title_zen_mode">Do not disturb</string>
|
||||
|
||||
<!-- [CHAR LIMIT=30] Sound settings screen, setting option name to change zen mode -->
|
||||
<string name="title_zen_mode">Limited interruptions</string>
|
||||
<!-- [CHAR LIMIT=30] Sound settings screen, description for configuring zen mode -->
|
||||
<string name="configure_zen_mode_description">Configure limited interruptions</string>
|
||||
<!-- [CHAR LIMIT=30] Zen mode settings screen, activity title -->
|
||||
<string name="zen_mode_settings_title">Limited Interruptions</string>
|
||||
<string name="zen_mode_settings_title">Do not disturb</string>
|
||||
|
||||
<!-- [CHAR LIMIT=20] Notifications settings header -->
|
||||
<string name="notification_settings">Notifications</string>
|
||||
|
||||
<!-- [CHAR LIMIT=20] Notifications settings: General section header -->
|
||||
<string name="notification_settings_general">General</string>
|
||||
|
||||
<!-- [CHAR LIMIT=20] Notifications settings: Security section header -->
|
||||
<string name="notification_settings_security">Security</string>
|
||||
|
||||
<!-- [CHAR LIMIT=20] Notifications settings: Tweaks section header (eng
|
||||
builds only) -->
|
||||
<string name="notification_settings_tweaks">Tweaks</string>
|
||||
|
||||
<!-- [CHAR LIMIT=20] Notifications settings: Apps section header -->
|
||||
<string name="notification_settings_apps">Apps</string>
|
||||
<string name="notification_settings_apps_title">App notifications</string>
|
||||
|
||||
<!-- [CHAR LIMIT=NONE] Content description for per-app notification
|
||||
settings button -->
|
||||
@@ -5081,5 +5072,21 @@
|
||||
<!-- Text displayed when tag is not writable -->
|
||||
<string name="status_tag_not_writable">NFC tag is not writable. Please use a different tag.</string>
|
||||
|
||||
<!-- Option title for the default sound, context based on screen -->
|
||||
<string name="default_sound">Default sound</string>
|
||||
|
||||
<!-- [CHAR LIMIT=NONE] Text when loading app list in notification settings -->
|
||||
<string name="loading_notification_apps">Loading apps...</string>
|
||||
|
||||
<!-- [CHAR LIMIT=40] Notification settings: App notifications screen title -->
|
||||
<string name="app_notifications_title">App notifications</string>
|
||||
|
||||
<!-- [CHAR LIMIT=30] Notification settings: App notifications dialog show option -->
|
||||
<string name="app_notifications_dialog_show">Show notifications</string>
|
||||
|
||||
<!-- [CHAR LIMIT=30] Notification settings: App notifications dialog priority option -->
|
||||
<string name="app_notifications_dialog_priority">High priority</string>
|
||||
|
||||
<!-- [CHAR LIMIT=20] Notification settings: App notifications dialog dismiss button caption -->
|
||||
<string name="app_notifications_dialog_done">Done</string>
|
||||
</resources>
|
||||
|
@@ -19,13 +19,9 @@
|
||||
android:key="notification_settings"
|
||||
xmlns:settings="http://schemas.android.com/apk/res/com.android.settings">
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="category_general"
|
||||
android:title="@string/notification_settings_general">
|
||||
|
||||
<com.android.settings.DefaultRingtonePreference
|
||||
android:key="notification_sound"
|
||||
android:title="@string/notification_sound_title"
|
||||
android:title="@string/default_sound"
|
||||
android:dialogTitle="@string/notification_sound_dialog_title"
|
||||
android:persistent="false"
|
||||
android:ringtoneType="notification" />
|
||||
@@ -38,20 +34,8 @@
|
||||
<CheckBoxPreference
|
||||
android:key="heads_up"
|
||||
android:title="@string/heads_up_enabled_title"
|
||||
android:summary="@string/heads_up_enabled_summary"
|
||||
android:persistent="false" />
|
||||
|
||||
<PreferenceScreen
|
||||
android:key="zen_mode"
|
||||
android:title="@string/title_zen_mode"
|
||||
android:fragment="com.android.settings.ZenModeSettings" />
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="category_security"
|
||||
android:title="@string/notification_settings_security">
|
||||
|
||||
<CheckBoxPreference
|
||||
android:key="toggle_lock_screen_notifications"
|
||||
android:title="@string/lock_screen_notifications"
|
||||
@@ -59,27 +43,20 @@
|
||||
android:summaryOn="@string/lock_screen_notifications_summary_on"
|
||||
android:persistent="false" />
|
||||
|
||||
<PreferenceScreen
|
||||
android:key="configure"
|
||||
android:title="@string/notification_settings_apps_title"
|
||||
android:fragment="com.android.settings.notification.AppNotificationSettings" />
|
||||
|
||||
<PreferenceScreen
|
||||
android:key="zen_mode"
|
||||
android:title="@string/title_zen_mode"
|
||||
android:fragment="com.android.settings.notification.ZenModeSettings" />
|
||||
|
||||
<Preference
|
||||
android:key="manage_notification_access"
|
||||
android:title="@string/manage_notification_access"
|
||||
android:persistent="false"
|
||||
android:fragment="com.android.settings.NotificationAccessSettings"/>
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<!--
|
||||
<PreferenceCategory
|
||||
android:key="category_tweaks"
|
||||
android:title="@string/notification_settings_tweaks"/>
|
||||
|
||||
<Preference
|
||||
android:title="Coming soon"
|
||||
/>
|
||||
-->
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="category_apps"
|
||||
android:title="@string/notification_settings_apps">
|
||||
</PreferenceCategory>
|
||||
android:fragment="com.android.settings.notification.NotificationAccessSettings" />
|
||||
|
||||
</PreferenceScreen>
|
||||
|
@@ -85,7 +85,7 @@
|
||||
<header
|
||||
android:id="@+id/notification_settings"
|
||||
android:icon="@drawable/ic_settings_notifications"
|
||||
android:fragment="com.android.settings.NotificationSettings"
|
||||
android:fragment="com.android.settings.notification.NotificationSettings"
|
||||
android:title="@string/notification_settings" />
|
||||
|
||||
<!-- Storage -->
|
||||
|
@@ -93,6 +93,10 @@ import com.android.settings.inputmethod.UserDictionaryList;
|
||||
import com.android.settings.location.LocationSettings;
|
||||
import com.android.settings.nfc.AndroidBeam;
|
||||
import com.android.settings.nfc.PaymentSettings;
|
||||
import com.android.settings.notification.NotificationAccessSettings;
|
||||
import com.android.settings.notification.NotificationSettings;
|
||||
import com.android.settings.notification.NotificationStation;
|
||||
import com.android.settings.notification.ZenModeSettings;
|
||||
import com.android.settings.print.PrintJobSettingsFragment;
|
||||
import com.android.settings.print.PrintSettingsFragment;
|
||||
import com.android.settings.tts.TextToSpeechSettings;
|
||||
|
@@ -0,0 +1,550 @@
|
||||
/*
|
||||
* 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.animation.LayoutTransition;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.INotificationManager;
|
||||
import android.app.ListFragment;
|
||||
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.content.pm.Signature;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.ShapeDrawable;
|
||||
import android.graphics.drawable.shapes.PathShape;
|
||||
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.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.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;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
import java.text.Collator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class AppNotificationSettings extends ListFragment {
|
||||
private static final String TAG = "AppNotificationSettings";
|
||||
private static final boolean DEBUG = true;
|
||||
|
||||
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(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();
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mContext = getActivity();
|
||||
mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
mAdapter = new NotificationAppAdapter(mContext);
|
||||
getActivity().setTitle(R.string.app_notifications_title);
|
||||
}
|
||||
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.notification_app_list, container, false);
|
||||
}
|
||||
|
||||
@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 onResume() {
|
||||
super.onResume();
|
||||
loadAppsList();
|
||||
}
|
||||
|
||||
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 boolean isSystemApp(PackageInfo pkg) {
|
||||
if (mSystemSignature == null) {
|
||||
mSystemSignature = new Signature[]{ getSystemSignature() };
|
||||
}
|
||||
return mSystemSignature[0] != null && mSystemSignature[0].equals(getFirstSignature(pkg));
|
||||
}
|
||||
|
||||
private static Signature getFirstSignature(PackageInfo pkg) {
|
||||
if (pkg != null && pkg.signatures != null && pkg.signatures.length > 0) {
|
||||
return pkg.signatures[0];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Signature getSystemSignature() {
|
||||
final PackageManager pm = mContext.getPackageManager();
|
||||
try {
|
||||
final PackageInfo sys = pm.getPackageInfo("android", PackageManager.GET_SIGNATURES);
|
||||
return getFirstSignature(sys);
|
||||
} catch (NameNotFoundException e) {
|
||||
}
|
||||
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);
|
||||
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*/);
|
||||
} else {
|
||||
showBox.setOnCheckedChangeListener(null);
|
||||
showBox.setChecked(!isChecked);
|
||||
showBox.setOnCheckedChangeListener(this);
|
||||
}
|
||||
}
|
||||
};
|
||||
showBox.setOnCheckedChangeListener(showListener);
|
||||
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;
|
||||
ImageView icon;
|
||||
ImageView banBadge;
|
||||
ImageView priBadge;
|
||||
TextView title;
|
||||
View settingsDivider;
|
||||
ImageView settingsButton;
|
||||
View rowDivider;
|
||||
}
|
||||
|
||||
private class NotificationAppAdapter extends ArrayAdapter<Row> implements SectionIndexer {
|
||||
private final ShapeDrawable mBanShape, mPriShape;
|
||||
|
||||
public NotificationAppAdapter(Context context) {
|
||||
super(context, 0, 0);
|
||||
final int s = context.getResources()
|
||||
.getDimensionPixelSize(R.dimen.notification_app_icon_badge_size);
|
||||
mBanShape = shape(banPath(s), s);
|
||||
mPriShape = shape(priPath(s), s);
|
||||
}
|
||||
|
||||
private ShapeDrawable shape(Path path, int s) {
|
||||
final ShapeDrawable sd = new ShapeDrawable(new PathShape(path, s, s));
|
||||
sd.getPaint().setStyle(Paint.Style.STROKE);
|
||||
sd.getPaint().setColor(0xffffffff);
|
||||
sd.getPaint().setStrokeWidth(s / 12);
|
||||
sd.setIntrinsicWidth(s);
|
||||
sd.setIntrinsicHeight(s);
|
||||
return sd;
|
||||
}
|
||||
|
||||
private Path banPath(int s) {
|
||||
final Path p = new Path();
|
||||
final int d = s / 5;
|
||||
p.moveTo(d, d); p.lineTo(s - d, s - d);
|
||||
p.moveTo(d, s - d); p.lineTo(s - d, d);
|
||||
return p;
|
||||
}
|
||||
|
||||
private Path priPath(int s) {
|
||||
final Path p = new Path();
|
||||
final int d = s / 5;
|
||||
p.moveTo(s / 2, d); p.lineTo(s / 2, s - d);
|
||||
return p;
|
||||
}
|
||||
|
||||
@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.appButton = (ViewGroup) v.findViewById(android.R.id.button1);
|
||||
vh.appButton.setLayoutTransition(new LayoutTransition());
|
||||
vh.icon = (ImageView) v.findViewById(android.R.id.icon);
|
||||
vh.banBadge = (ImageView) v.findViewById(android.R.id.icon1);
|
||||
vh.banBadge.setImageDrawable(mBanShape);
|
||||
vh.priBadge = (ImageView) v.findViewById(android.R.id.icon2);
|
||||
vh.priBadge.setImageDrawable(mPriShape);
|
||||
vh.title = (TextView) v.findViewById(android.R.id.title);
|
||||
vh.settingsDivider = v.findViewById(R.id.settings_divider);
|
||||
vh.settingsButton = (ImageView) v.findViewById(android.R.id.button2);
|
||||
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)) {
|
||||
TextView tv = (TextView)view;
|
||||
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.appButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
showDialog(view, row);
|
||||
}
|
||||
});
|
||||
enableLayoutTransitions(vh.appButton, animate);
|
||||
vh.icon.setImageDrawable(row.icon);
|
||||
vh.banBadge.setVisibility(row.banned ? View.VISIBLE : View.GONE);
|
||||
vh.priBadge.setVisibility(row.priority ? View.VISIBLE : View.GONE);
|
||||
vh.title.setText(row.label);
|
||||
final boolean showSettings = !row.banned && row.settingsIntent != null;
|
||||
vh.settingsDivider.setVisibility(showSettings ? View.VISIBLE : View.GONE);
|
||||
vh.settingsButton.setVisibility(showSettings ? View.VISIBLE : View.GONE);
|
||||
vh.settingsButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (row.settingsIntent != null) {
|
||||
getContext().startActivity(row.settingsIntent);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
|
||||
private 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 first;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
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 non-system apps
|
||||
final PackageManager pm = mContext.getPackageManager();
|
||||
for (PackageInfo pkg : pm.getInstalledPackages(PackageManager.GET_SIGNATURES)) {
|
||||
if (pkg.applicationInfo == null || isSystemApp(pkg)) {
|
||||
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);
|
||||
mRows.put(row.pkg, row);
|
||||
}
|
||||
// collect config activities
|
||||
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);
|
||||
if (DEBUG) Log.d(TAG, "Found " + resolveInfos.size() + " preference activities");
|
||||
for (ResolveInfo ri : resolveInfos) {
|
||||
final ActivityInfo activityInfo = ri.activityInfo;
|
||||
final ApplicationInfo appInfo = activityInfo.applicationInfo;
|
||||
final AppRow row = mRows.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(Intent.ACTION_MAIN)
|
||||
.setClassName(activityInfo.packageName, activityInfo.name);
|
||||
}
|
||||
// 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 {
|
||||
public boolean setNotificationsBanned(String pkg, int uid, boolean banned) {
|
||||
INotificationManager nm = INotificationManager.Stub.asInterface(
|
||||
ServiceManager.getService(Context.NOTIFICATION_SERVICE));
|
||||
try {
|
||||
nm.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) {
|
||||
INotificationManager nm = INotificationManager.Stub.asInterface(
|
||||
ServiceManager.getService(Context.NOTIFICATION_SERVICE));
|
||||
try {
|
||||
final boolean enabled = nm.areNotificationsEnabledForPackage(pkg, uid);
|
||||
return !enabled;
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Error calling NoMan", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getHighPriority(String pkg, int uid) {
|
||||
// TODO get high-pri state from NoMan
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean setHighPriority(String pkg, int uid, boolean priority) {
|
||||
// TODO save high-pri state to NoMan
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@@ -14,41 +14,42 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
package com.android.settings.notification;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.app.DialogFragment;
|
||||
import android.app.ListFragment;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.PackageItemInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.database.ContentObserver;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.provider.Settings;
|
||||
import android.service.notification.NotificationListenerService;
|
||||
import android.util.Slog;
|
||||
import android.widget.ArrayAdapter;
|
||||
|
||||
import android.app.ListFragment;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
@@ -14,57 +14,40 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
package com.android.settings.notification;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.database.ContentObserver;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.media.RingtoneManager;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.preference.CheckBoxPreference;
|
||||
import android.preference.Preference;
|
||||
import android.preference.Preference.OnPreferenceClickListener;
|
||||
import android.preference.PreferenceGroup;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.preference.TwoStatePreference;
|
||||
import android.provider.Settings;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.text.Collator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
import com.android.settings.SoundSettings;
|
||||
|
||||
public class NotificationSettings extends SettingsPreferenceFragment implements
|
||||
Preference.OnPreferenceChangeListener, OnPreferenceClickListener {
|
||||
private static final String TAG = "NotificationSettings";
|
||||
|
||||
private static final Intent APP_NOTIFICATION_PREFS_CATEGORY_INTENT
|
||||
= new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_NOTIFICATION_PREFERENCES);
|
||||
|
||||
private static final String KEY_NOTIFICATION_SOUND = "notification_sound";
|
||||
private static final String KEY_NOTIFICATION_ACCESS = "manage_notification_access";
|
||||
private static final String KEY_LOCK_SCREEN_NOTIFICATIONS = "toggle_lock_screen_notifications";
|
||||
private static final String KEY_HEADS_UP = "heads_up";
|
||||
private static final String KEY_NOTIFICATION_PULSE = "notification_pulse";
|
||||
private static final String KEY_HEADS_UP = "heads_up";
|
||||
private static final String KEY_LOCK_SCREEN_NOTIFICATIONS = "toggle_lock_screen_notifications";
|
||||
private static final String KEY_NOTIFICATION_ACCESS = "manage_notification_access";
|
||||
|
||||
private static final String KEY_SECURITY_CATEGORY = "category_security";
|
||||
private static final String KEY_APPS_CATEGORY = "category_apps";
|
||||
private static final String KEY_TWEAKS_CATEGORY = "category_tweaks"; // power toys, eng only
|
||||
|
||||
private static final int MSG_UPDATE_SOUND_SUMMARY = 2;
|
||||
@@ -74,10 +57,9 @@ public class NotificationSettings extends SettingsPreferenceFragment implements
|
||||
|
||||
private Preference mNotificationSoundPreference;
|
||||
private Preference mNotificationAccess;
|
||||
private CheckBoxPreference mLockscreenNotifications;
|
||||
private CheckBoxPreference mHeadsUp;
|
||||
private CheckBoxPreference mNotificationPulse;
|
||||
private PreferenceGroup mAppsPreference;
|
||||
private TwoStatePreference mLockscreenNotifications;
|
||||
private TwoStatePreference mHeadsUp;
|
||||
private TwoStatePreference mNotificationPulse;
|
||||
|
||||
private final Runnable mRingtoneLookupRunnable = new Runnable() {
|
||||
@Override
|
||||
@@ -104,80 +86,6 @@ public class NotificationSettings extends SettingsPreferenceFragment implements
|
||||
}
|
||||
};
|
||||
|
||||
private final ArrayList<AppNotificationInfo> mAppNotificationInfo
|
||||
= new ArrayList<AppNotificationInfo>();
|
||||
private final HashSet<String> mAppNotificationInfoPackages = new HashSet<String>();
|
||||
private final Comparator<AppNotificationInfo> mAppComparator = new Comparator<AppNotificationInfo>() {
|
||||
private final Collator sCollator = Collator.getInstance();
|
||||
@Override
|
||||
public int compare(AppNotificationInfo lhs, AppNotificationInfo rhs) {
|
||||
return sCollator.compare(lhs.label, rhs.label);
|
||||
}
|
||||
};
|
||||
|
||||
private final Runnable mCollectAppsRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (mAppNotificationInfo) {
|
||||
mAppNotificationInfo.clear();
|
||||
mAppNotificationInfoPackages.clear();
|
||||
|
||||
final PackageManager pm = getPackageManager();
|
||||
|
||||
final List<ResolveInfo> resolveInfos = pm.queryIntentActivities(APP_NOTIFICATION_PREFS_CATEGORY_INTENT,
|
||||
PackageManager.MATCH_DEFAULT_ONLY);
|
||||
|
||||
for (ResolveInfo ri : resolveInfos) {
|
||||
final ActivityInfo activityInfo = ri.activityInfo;
|
||||
final ApplicationInfo appInfo = activityInfo.applicationInfo;
|
||||
if (mAppNotificationInfoPackages.contains(activityInfo.packageName)) {
|
||||
Log.v(TAG, "Ignoring duplicate notification preference activity ("
|
||||
+ activityInfo.name + ") for package "
|
||||
+ activityInfo.packageName);
|
||||
continue;
|
||||
}
|
||||
final AppNotificationInfo info = new AppNotificationInfo();
|
||||
mAppNotificationInfoPackages.add(activityInfo.packageName);
|
||||
|
||||
info.label = appInfo.loadLabel(pm);
|
||||
info.icon = appInfo.loadIcon(pm);
|
||||
info.name = activityInfo.name;
|
||||
info.pkg = activityInfo.packageName;
|
||||
mAppNotificationInfo.add(info);
|
||||
}
|
||||
|
||||
Collections.sort(mAppNotificationInfo, mAppComparator);
|
||||
mHandler.post(mRefreshAppsListRunnable);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final Runnable mRefreshAppsListRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (mAppNotificationInfo) {
|
||||
mAppsPreference.removeAll();
|
||||
Preference p = getPreferenceScreen().findPreference(mAppsPreference.getKey());
|
||||
final int N = mAppNotificationInfo.size();
|
||||
if (N == 0 && p != null) {
|
||||
getPreferenceScreen().removePreference(p);
|
||||
} else if (N > 0 && p == null) {
|
||||
getPreferenceScreen().addPreference(mAppsPreference);
|
||||
}
|
||||
for (int i = 0; i < N; i++) {
|
||||
final AppNotificationInfo info = mAppNotificationInfo.get(i);
|
||||
Preference pref = new AppNotificationPreference(mContext);
|
||||
pref.setTitle(info.label);
|
||||
pref.setIcon(info.icon);
|
||||
pref.setIntent(new Intent(Intent.ACTION_MAIN)
|
||||
.setClassName(info.pkg, info.name));
|
||||
mAppsPreference.addPreference(pref);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@@ -189,8 +97,6 @@ public class NotificationSettings extends SettingsPreferenceFragment implements
|
||||
addPreferencesFromResource(R.xml.notification_settings);
|
||||
|
||||
final PreferenceScreen root = getPreferenceScreen();
|
||||
final PreferenceGroup securityCategory = (PreferenceGroup)
|
||||
root.findPreference(KEY_SECURITY_CATEGORY);
|
||||
|
||||
PreferenceGroup tweaksCategory = (PreferenceGroup)
|
||||
root.findPreference(KEY_TWEAKS_CATEGORY);
|
||||
@@ -207,18 +113,16 @@ public class NotificationSettings extends SettingsPreferenceFragment implements
|
||||
refreshNotificationListeners();
|
||||
|
||||
mLockscreenNotifications
|
||||
= (CheckBoxPreference) root.findPreference(KEY_LOCK_SCREEN_NOTIFICATIONS);
|
||||
= (TwoStatePreference) root.findPreference(KEY_LOCK_SCREEN_NOTIFICATIONS);
|
||||
if (mLockscreenNotifications != null) {
|
||||
if (!getDeviceLockscreenNotificationsEnabled()) {
|
||||
if (securityCategory != null) {
|
||||
securityCategory.removePreference(mLockscreenNotifications);
|
||||
}
|
||||
root.removePreference(mLockscreenNotifications);
|
||||
} else {
|
||||
mLockscreenNotifications.setChecked(getLockscreenAllowPrivateNotifications());
|
||||
}
|
||||
}
|
||||
|
||||
mHeadsUp = (CheckBoxPreference) findPreference(KEY_HEADS_UP);
|
||||
mHeadsUp = (TwoStatePreference) findPreference(KEY_HEADS_UP);
|
||||
if (mHeadsUp != null) {
|
||||
updateHeadsUpMode(resolver);
|
||||
mHeadsUp.setOnPreferenceChangeListener(this);
|
||||
@@ -231,7 +135,7 @@ public class NotificationSettings extends SettingsPreferenceFragment implements
|
||||
}
|
||||
});
|
||||
}
|
||||
mNotificationPulse = (CheckBoxPreference) findPreference(KEY_NOTIFICATION_PULSE);
|
||||
mNotificationPulse = (TwoStatePreference) findPreference(KEY_NOTIFICATION_PULSE);
|
||||
|
||||
if (mNotificationPulse != null
|
||||
&& getResources().getBoolean(
|
||||
@@ -246,8 +150,6 @@ public class NotificationSettings extends SettingsPreferenceFragment implements
|
||||
Log.e(TAG, Settings.System.NOTIFICATION_LIGHT_PULSE + " not found");
|
||||
}
|
||||
}
|
||||
mAppsPreference = (PreferenceGroup) root.findPreference(KEY_APPS_CATEGORY);
|
||||
root.removePreference(mAppsPreference);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -256,11 +158,6 @@ public class NotificationSettings extends SettingsPreferenceFragment implements
|
||||
|
||||
refreshNotificationListeners();
|
||||
lookupRingtoneNames();
|
||||
loadAppsList();
|
||||
}
|
||||
|
||||
private void loadAppsList() {
|
||||
AsyncTask.execute(mCollectAppsRunnable);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -330,14 +227,9 @@ public class NotificationSettings extends SettingsPreferenceFragment implements
|
||||
|
||||
private void refreshNotificationListeners() {
|
||||
if (mNotificationAccess != null) {
|
||||
final PreferenceGroup securityCategory
|
||||
= (PreferenceGroup) getPreferenceScreen().findPreference(KEY_SECURITY_CATEGORY);
|
||||
|
||||
final int total = NotificationAccessSettings.getListenersCount(mPM);
|
||||
if (total == 0) {
|
||||
if (securityCategory != null) {
|
||||
securityCategory.removePreference(mNotificationAccess);
|
||||
}
|
||||
getPreferenceScreen().removePreference(mNotificationAccess);
|
||||
} else {
|
||||
final int n = getNumEnabledNotificationListeners();
|
||||
if (n == 0) {
|
||||
@@ -357,56 +249,4 @@ public class NotificationSettings extends SettingsPreferenceFragment implements
|
||||
private void lookupRingtoneNames() {
|
||||
new Thread(mRingtoneLookupRunnable).start();
|
||||
}
|
||||
|
||||
// === Per-app notification settings row ==
|
||||
|
||||
private static class AppNotificationPreference extends Preference {
|
||||
private Intent mIntent;
|
||||
|
||||
public AppNotificationPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
|
||||
setLayoutResource(R.layout.notification_app);
|
||||
}
|
||||
|
||||
public AppNotificationPreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
this(context, attrs, defStyleAttr, 0);
|
||||
}
|
||||
|
||||
public AppNotificationPreference(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public AppNotificationPreference(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public void setIntent(Intent intent) {
|
||||
mIntent = intent;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBindView(View view) {
|
||||
super.onBindView(view);
|
||||
|
||||
ImageView icon = (ImageView) view.findViewById(android.R.id.icon);
|
||||
icon.setImageDrawable(getIcon());
|
||||
TextView title = (TextView) view.findViewById(android.R.id.title);
|
||||
title.setText(getTitle());
|
||||
ImageView settingsButton = (ImageView) view.findViewById(android.R.id.button2);
|
||||
settingsButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
getContext().startActivity(mIntent);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static class AppNotificationInfo {
|
||||
public Drawable icon;
|
||||
public CharSequence label;
|
||||
public String name;
|
||||
public String pkg;
|
||||
}
|
||||
}
|
@@ -14,16 +14,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
package com.android.settings.notification;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityManager;
|
||||
import android.content.ComponentName;
|
||||
import android.service.notification.INotificationListener;
|
||||
import android.app.INotificationManager;
|
||||
import android.app.Notification;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
@@ -37,6 +35,8 @@ import android.os.Handler;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.UserHandle;
|
||||
import android.service.notification.INotificationListener;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
@@ -48,6 +48,9 @@ import android.widget.ImageView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
@@ -14,13 +14,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
package com.android.settings.notification;
|
||||
|
||||
import android.app.ActionBar;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.database.ContentObserver;
|
||||
import android.content.res.Resources;
|
||||
import android.database.ContentObserver;
|
||||
import android.graphics.Typeface;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
@@ -28,6 +28,7 @@ import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.provider.Settings.Global;
|
||||
import android.provider.SearchIndexableResource;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
@@ -45,6 +46,9 @@ import android.widget.ScrollView;
|
||||
import android.widget.Switch;
|
||||
import android.widget.TextView;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
import com.android.settings.search.Indexable;
|
||||
import com.android.settings.search.SearchIndexableRaw;
|
||||
|
@@ -17,27 +17,27 @@
|
||||
package com.android.settings.search;
|
||||
|
||||
import android.provider.SearchIndexableResource;
|
||||
|
||||
import com.android.settings.DataUsageSummary;
|
||||
import com.android.settings.DateTimeSettings;
|
||||
import com.android.settings.DevelopmentSettings;
|
||||
import com.android.settings.DeviceInfoSettings;
|
||||
import com.android.settings.DisplaySettings;
|
||||
import com.android.settings.HomeSettings;
|
||||
import com.android.settings.NotificationSettings;
|
||||
import com.android.settings.PrivacySettings;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SecuritySettings;
|
||||
import com.android.settings.SoundSettings;
|
||||
import com.android.settings.WallpaperTypeSettings;
|
||||
import com.android.settings.WirelessSettings;
|
||||
import com.android.settings.ZenModeSettings;
|
||||
import com.android.settings.accessibility.AccessibilitySettings;
|
||||
import com.android.settings.bluetooth.BluetoothSettings;
|
||||
import com.android.settings.deviceinfo.Memory;
|
||||
import com.android.settings.fuelgauge.PowerUsageSummary;
|
||||
import com.android.settings.inputmethod.InputMethodAndLanguageSettings;
|
||||
import com.android.settings.location.LocationSettings;
|
||||
import com.android.settings.net.DataUsageMeteredSettings;
|
||||
import com.android.settings.notification.NotificationSettings;
|
||||
import com.android.settings.notification.ZenModeSettings;
|
||||
import com.android.settings.print.PrintSettingsFragment;
|
||||
import com.android.settings.users.UserSettings;
|
||||
import com.android.settings.wifi.WifiSettings;
|
||||
|
Reference in New Issue
Block a user