Adding a warning button when notification access is not available

Bug: 63418030
Change-Id: I4c2c497d989902ac002314a3b8fb97083757958b
This commit is contained in:
Sunny Goyal 2017-07-07 03:12:21 -07:00
parent 6c5d10261e
commit 848cad56ce
6 changed files with 205 additions and 11 deletions

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2017 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="?android:attr/textColorPrimary" >
<path
android:fillColor="#FFFFFFFF"
android:pathData="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"/>
</vector>

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2017 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.
-->
<ImageView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="48dp"
android:layout_height="match_parent"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/title_missing_notification_access"
android:scaleType="center"
android:src="@drawable/ic_warning"
android:tint="?android:attr/textColorSecondary" />

View File

@ -178,6 +178,12 @@
<string name="icon_badging_desc_on">On</string>
<!-- Text to indicate that the system icon badging setting is off [CHAR LIMIT=100] -->
<string name="icon_badging_desc_off">Off</string>
<!-- Title for the dialog shown when the app does not has notification access, explaining the requirement for notification access [CHAR LIMIT=50] -->
<string name="title_missing_notification_access">Notification access needed</string>
<!-- Message explaining to the user that the notification access is required by the app for showing 'Notification dots' [CHAR LIMIT=NONE] -->
<string name="msg_missing_notification_access">To show Notification Dots, turn on app notifications for <xliff:g id="name" example="My App">%1$s</xliff:g></string>
<!-- Button text in the confirmation dialog which would take the user to the system settings [CHAR LIMIT=50] -->
<string name="title_change_settings">Change settings</string>
<!-- Label for the setting that allows the automatic placement of launcher shortcuts for applications and games installed on the device [CHAR LIMIT=40] -->
<string name="auto_add_shortcuts_label">Add icon to Home screen</string>

View File

@ -16,17 +16,18 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<Preference
<com.android.launcher3.views.ButtonPreference
android:key="pref_icon_badging"
android:title="@string/icon_badging_title"
android:persistent="false">
android:persistent="false"
android:widgetLayout="@layout/notification_pref_warning" >
<intent android:action="android.settings.NOTIFICATION_SETTINGS">
<!-- This extra highlights the "Allow icon badges" field in Notification settings -->
<extra
android:name=":settings:fragment_args_key"
android:value="notification_badging" />
</intent>
</Preference>
</com.android.launcher3.views.ButtonPreference>
<SwitchPreference
android:key="pref_add_icon_to_home"

View File

@ -17,7 +17,15 @@
package com.android.launcher3;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.FragmentManager;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.ContentObserver;
import android.os.Bundle;
import android.os.Handler;
@ -26,8 +34,11 @@ import android.preference.Preference;
import android.preference.PreferenceFragment;
import android.provider.Settings;
import android.provider.Settings.System;
import android.view.View;
import com.android.launcher3.graphics.IconShapeOverride;
import com.android.launcher3.notification.NotificationListener;
import com.android.launcher3.views.ButtonPreference;
/**
* Settings activity for Launcher. Currently implements the following setting: Allow rotation
@ -37,6 +48,8 @@ public class SettingsActivity extends Activity {
private static final String ICON_BADGING_PREFERENCE_KEY = "pref_icon_badging";
// TODO: use Settings.Secure.NOTIFICATION_BADGING
private static final String NOTIFICATION_BADGING = "notification_badging";
/** Hidden field Settings.Secure.ENABLED_NOTIFICATION_LISTENERS */
private static final String NOTIFICATION_ENABLED_LISTENERS = "enabled_notification_listeners";
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -85,17 +98,22 @@ public class SettingsActivity extends Activity {
rotationPref.setDefaultValue(Utilities.getAllowRotationDefaultValue(getActivity()));
}
Preference iconBadgingPref = findPreference(ICON_BADGING_PREFERENCE_KEY);
ButtonPreference iconBadgingPref =
(ButtonPreference) findPreference(ICON_BADGING_PREFERENCE_KEY);
if (!Utilities.isAtLeastO()) {
getPreferenceScreen().removePreference(
findPreference(SessionCommitReceiver.ADD_ICON_PREFERENCE_KEY));
getPreferenceScreen().removePreference(iconBadgingPref);
} else {
// Listen to system notification badge settings while this UI is active.
mIconBadgingObserver = new IconBadgingObserver(iconBadgingPref, resolver);
mIconBadgingObserver = new IconBadgingObserver(
iconBadgingPref, resolver, getFragmentManager());
resolver.registerContentObserver(
Settings.Secure.getUriFor(NOTIFICATION_BADGING),
false, mIconBadgingObserver);
resolver.registerContentObserver(
Settings.Secure.getUriFor(NOTIFICATION_ENABLED_LISTENERS),
false, mIconBadgingObserver);
mIconBadgingObserver.onChange(true);
}
@ -153,24 +171,74 @@ public class SettingsActivity extends Activity {
* Content observer which listens for system badging setting changes,
* and updates the launcher badging setting subtext accordingly.
*/
private static class IconBadgingObserver extends ContentObserver {
private static class IconBadgingObserver extends ContentObserver
implements View.OnClickListener {
private final Preference mBadgingPref;
private final ButtonPreference mBadgingPref;
private final ContentResolver mResolver;
private final FragmentManager mFragmentManager;
public IconBadgingObserver(Preference badgingPref, ContentResolver resolver) {
public IconBadgingObserver(ButtonPreference badgingPref, ContentResolver resolver,
FragmentManager fragmentManager) {
super(new Handler());
mBadgingPref = badgingPref;
mResolver = resolver;
mFragmentManager = fragmentManager;
}
@Override
public void onChange(boolean selfChange) {
boolean enabled = Settings.Secure.getInt(mResolver, NOTIFICATION_BADGING, 1) == 1;
mBadgingPref.setSummary(enabled
? R.string.icon_badging_desc_on
: R.string.icon_badging_desc_off);
int summary = enabled ? R.string.icon_badging_desc_on : R.string.icon_badging_desc_off;
boolean serviceEnabled = true;
if (enabled) {
// Check if the listener is enabled or not.
String enabledListeners =
Settings.Secure.getString(mResolver, NOTIFICATION_ENABLED_LISTENERS);
ComponentName myListener =
new ComponentName(mBadgingPref.getContext(), NotificationListener.class);
serviceEnabled = enabledListeners != null &&
(enabledListeners.contains(myListener.flattenToString()) ||
enabledListeners.contains(myListener.flattenToShortString()));
if (!serviceEnabled) {
summary = R.string.title_missing_notification_access;
}
}
mBadgingPref.setButtonOnClickListener(serviceEnabled ? null : this);
mBadgingPref.setSummary(summary);
}
@Override
public void onClick(View view) {
new NotificationAccessConfirmation().show(mFragmentManager, "notification_access");
}
}
public static class NotificationAccessConfirmation
extends DialogFragment implements DialogInterface.OnClickListener {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Context context = getActivity();
String msg = context.getString(R.string.msg_missing_notification_access,
context.getString(R.string.derived_app_name));
return new AlertDialog.Builder(context)
.setTitle(R.string.title_missing_notification_access)
.setMessage(msg)
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(R.string.title_change_settings, this)
.create();
}
@Override
public void onClick(DialogInterface dialogInterface, int i) {
ComponentName cn = new ComponentName(getActivity(), NotificationListener.class);
Intent intent = new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra(":settings:fragment_args_key", cn.flattenToString());
getActivity().startActivity(intent);
}
}
}

View File

@ -0,0 +1,70 @@
/*
* Copyright (C) 2017 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.launcher3.views;
import android.content.Context;
import android.preference.Preference;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
/**
* Extension of {@link Preference} which makes the widget layout clickable.
*
* @see #setWidgetLayoutResource(int)
*/
public class ButtonPreference extends Preference {
private View.OnClickListener mClickListener;
public ButtonPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public ButtonPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public ButtonPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ButtonPreference(Context context) {
super(context);
}
public void setButtonOnClickListener(View.OnClickListener clickListener) {
if (mClickListener != clickListener) {
mClickListener = clickListener;
notifyChanged();
}
}
@Override
protected void onBindView(View view) {
super.onBindView(view);
ViewGroup widgetFrame = view.findViewById(android.R.id.widget_frame);
if (widgetFrame != null) {
View button = widgetFrame.getChildAt(0);
if (button != null) {
button.setOnClickListener(mClickListener);
}
widgetFrame.setVisibility(
(mClickListener == null || button == null) ? View.GONE : View.VISIBLE);
}
}
}