1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.launcher3.settings; 17 18 import static com.android.launcher3.settings.SettingsActivity.EXTRA_FRAGMENT_ARG_KEY; 19 import static com.android.launcher3.settings.SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGS; 20 21 import android.app.AlertDialog; 22 import android.app.Dialog; 23 import android.app.DialogFragment; 24 import android.content.ComponentName; 25 import android.content.Context; 26 import android.content.DialogInterface; 27 import android.content.Intent; 28 import android.os.Bundle; 29 import android.provider.Settings; 30 import android.util.AttributeSet; 31 import android.view.View; 32 33 import com.android.launcher3.R; 34 import com.android.launcher3.notification.NotificationListener; 35 import com.android.launcher3.util.SecureSettingsObserver; 36 37 import androidx.preference.Preference; 38 import androidx.preference.PreferenceViewHolder; 39 40 /** 41 * A {@link Preference} for indicating notification dots status. 42 * Also has utility methods for updating UI based on dots status changes. 43 */ 44 public class NotificationDotsPreference extends Preference 45 implements SecureSettingsObserver.OnChangeListener { 46 47 private boolean mWidgetFrameVisible = false; 48 49 /** Hidden field Settings.Secure.ENABLED_NOTIFICATION_LISTENERS */ 50 private static final String NOTIFICATION_ENABLED_LISTENERS = "enabled_notification_listeners"; 51 NotificationDotsPreference( Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)52 public NotificationDotsPreference( 53 Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 54 super(context, attrs, defStyleAttr, defStyleRes); 55 } 56 NotificationDotsPreference(Context context, AttributeSet attrs, int defStyleAttr)57 public NotificationDotsPreference(Context context, AttributeSet attrs, int defStyleAttr) { 58 super(context, attrs, defStyleAttr); 59 } 60 NotificationDotsPreference(Context context, AttributeSet attrs)61 public NotificationDotsPreference(Context context, AttributeSet attrs) { 62 super(context, attrs); 63 } 64 NotificationDotsPreference(Context context)65 public NotificationDotsPreference(Context context) { 66 super(context); 67 } 68 setWidgetFrameVisible(boolean isVisible)69 private void setWidgetFrameVisible(boolean isVisible) { 70 if (mWidgetFrameVisible != isVisible) { 71 mWidgetFrameVisible = isVisible; 72 notifyChanged(); 73 } 74 } 75 76 @Override onBindViewHolder(PreferenceViewHolder holder)77 public void onBindViewHolder(PreferenceViewHolder holder) { 78 super.onBindViewHolder(holder); 79 80 View widgetFrame = holder.findViewById(android.R.id.widget_frame); 81 if (widgetFrame != null) { 82 widgetFrame.setVisibility(mWidgetFrameVisible ? View.VISIBLE : View.GONE); 83 } 84 } 85 86 @Override onSettingsChanged(boolean enabled)87 public void onSettingsChanged(boolean enabled) { 88 int summary = enabled 89 ? R.string.notification_dots_desc_on 90 : R.string.notification_dots_desc_off; 91 92 boolean serviceEnabled = true; 93 if (enabled) { 94 // Check if the listener is enabled or not. 95 String enabledListeners = Settings.Secure.getString( 96 getContext().getContentResolver(), NOTIFICATION_ENABLED_LISTENERS); 97 ComponentName myListener = 98 new ComponentName(getContext(), NotificationListener.class); 99 serviceEnabled = enabledListeners != null && 100 (enabledListeners.contains(myListener.flattenToString()) || 101 enabledListeners.contains(myListener.flattenToShortString())); 102 if (!serviceEnabled) { 103 summary = R.string.title_missing_notification_access; 104 } 105 } 106 setWidgetFrameVisible(!serviceEnabled); 107 setFragment(serviceEnabled ? null : NotificationAccessConfirmation.class.getName()); 108 setSummary(summary); 109 } 110 111 public static class NotificationAccessConfirmation 112 extends DialogFragment implements DialogInterface.OnClickListener { 113 114 @Override onCreateDialog(Bundle savedInstanceState)115 public Dialog onCreateDialog(Bundle savedInstanceState) { 116 final Context context = getActivity(); 117 String msg = context.getString(R.string.msg_missing_notification_access, 118 context.getString(R.string.derived_app_name)); 119 return new AlertDialog.Builder(context) 120 .setTitle(R.string.title_missing_notification_access) 121 .setMessage(msg) 122 .setNegativeButton(android.R.string.cancel, null) 123 .setPositiveButton(R.string.title_change_settings, this) 124 .create(); 125 } 126 127 @Override onClick(DialogInterface dialogInterface, int i)128 public void onClick(DialogInterface dialogInterface, int i) { 129 ComponentName cn = new ComponentName(getActivity(), NotificationListener.class); 130 Bundle showFragmentArgs = new Bundle(); 131 showFragmentArgs.putString(EXTRA_FRAGMENT_ARG_KEY, cn.flattenToString()); 132 133 Intent intent = new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS) 134 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 135 .putExtra(EXTRA_FRAGMENT_ARG_KEY, cn.flattenToString()) 136 .putExtra(EXTRA_SHOW_FRAGMENT_ARGS, showFragmentArgs); 137 getActivity().startActivity(intent); 138 } 139 } 140 } 141