blob: ac5571f70b0e66f6af10dccad4b53ba0e26e752f [file] [log] [blame]
/*
* 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.settings;
import static com.android.launcher3.settings.SettingsActivity.EXTRA_FRAGMENT_HIGHLIGHT_KEY;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.SettingsCache.NOTIFICATION_BADGING_URI;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.ContentObserver;
import android.os.Bundle;
import android.provider.Settings;
import android.util.AttributeSet;
import android.view.View;
import androidx.fragment.app.DialogFragment;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
import com.android.launcher3.R;
import com.android.launcher3.notification.NotificationListener;
import com.android.launcher3.util.SettingsCache;
/**
* A {@link Preference} for indicating notification dots status.
* Also has utility methods for updating UI based on dots status changes.
*/
public class NotificationDotsPreference extends Preference
implements SettingsCache.OnChangeListener {
private boolean mWidgetFrameVisible = false;
/** Hidden field Settings.Secure.ENABLED_NOTIFICATION_LISTENERS */
private static final String NOTIFICATION_ENABLED_LISTENERS = "enabled_notification_listeners";
private static final String EXTRA_SHOW_FRAGMENT_ARGS = ":settings:show_fragment_args";
private final ContentObserver mListenerListObserver =
new ContentObserver(MAIN_EXECUTOR.getHandler()) {
@Override
public void onChange(boolean selfChange) {
updateUI();
}
};
public NotificationDotsPreference(
Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public NotificationDotsPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public NotificationDotsPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public NotificationDotsPreference(Context context) {
super(context);
}
@Override
public void onAttached() {
super.onAttached();
SettingsCache.INSTANCE.get(getContext()).register(NOTIFICATION_BADGING_URI, this);
getContext().getContentResolver().registerContentObserver(
Settings.Secure.getUriFor(NOTIFICATION_ENABLED_LISTENERS),
false, mListenerListObserver);
updateUI();
// Update intent
Bundle extras = new Bundle();
extras.putString(EXTRA_FRAGMENT_HIGHLIGHT_KEY, "notification_badging");
setIntent(new Intent("android.settings.NOTIFICATION_SETTINGS")
.putExtra(EXTRA_SHOW_FRAGMENT_ARGS, extras));
}
private void updateUI() {
onSettingsChanged(SettingsCache.INSTANCE.get(getContext())
.getValue(NOTIFICATION_BADGING_URI));
}
@Override
public void onDetached() {
super.onDetached();
SettingsCache.INSTANCE.get(getContext()).unregister(NOTIFICATION_BADGING_URI, this);
getContext().getContentResolver().unregisterContentObserver(mListenerListObserver);
}
private void setWidgetFrameVisible(boolean isVisible) {
if (mWidgetFrameVisible != isVisible) {
mWidgetFrameVisible = isVisible;
notifyChanged();
}
}
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
View widgetFrame = holder.findViewById(android.R.id.widget_frame);
if (widgetFrame != null) {
widgetFrame.setVisibility(mWidgetFrameVisible ? View.VISIBLE : View.GONE);
}
}
@Override
public void onSettingsChanged(boolean enabled) {
int summary = enabled
? R.string.notification_dots_desc_on
: R.string.notification_dots_desc_off;
boolean serviceEnabled = true;
if (enabled) {
// Check if the listener is enabled or not.
String enabledListeners = Settings.Secure.getString(
getContext().getContentResolver(), NOTIFICATION_ENABLED_LISTENERS);
ComponentName myListener =
new ComponentName(getContext(), NotificationListener.class);
serviceEnabled = enabledListeners != null &&
(enabledListeners.contains(myListener.flattenToString()) ||
enabledListeners.contains(myListener.flattenToShortString()));
if (!serviceEnabled) {
summary = R.string.title_missing_notification_access;
}
}
setWidgetFrameVisible(!serviceEnabled);
setFragment(serviceEnabled ? null : NotificationAccessConfirmation.class.getName());
setSummary(summary);
}
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);
Bundle showFragmentArgs = new Bundle();
showFragmentArgs.putString(EXTRA_FRAGMENT_HIGHLIGHT_KEY, cn.flattenToString());
Intent intent = new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra(EXTRA_FRAGMENT_HIGHLIGHT_KEY, cn.flattenToString())
.putExtra(EXTRA_SHOW_FRAGMENT_ARGS, showFragmentArgs);
getActivity().startActivity(intent);
}
}
}