/* * 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.settings.accounts; import android.accounts.Account; import android.accounts.AccountManager; import android.accounts.AccountManagerCallback; import android.accounts.AccountManagerFuture; import android.accounts.AuthenticatorException; import android.accounts.OperationCanceledException; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.app.Fragment; import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; import android.os.Process; import android.support.v7.preference.PreferenceScreen; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import com.android.internal.logging.nano.MetricsProto; import com.android.settings.R; import com.android.settings.applications.LayoutPreference; import com.android.settings.core.PreferenceController; import com.android.settings.core.instrumentation.InstrumentedDialogFragment; import java.io.IOException; public class RemoveAccountPreferenceController extends PreferenceController implements OnClickListener { private static final String KEY_REMOVE_ACCOUNT = "remove_account"; private Account mAccount; private Fragment mParentFragment; public RemoveAccountPreferenceController(Context context, Fragment parent) { super(context); mParentFragment = parent; } @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); final LayoutPreference removeAccountPreference = (LayoutPreference) screen.findPreference(KEY_REMOVE_ACCOUNT); Button removeAccountButton = (Button) removeAccountPreference.findViewById(R.id.button); removeAccountButton.setOnClickListener(this); } @Override public boolean isAvailable() { return true; } @Override public String getPreferenceKey() { return KEY_REMOVE_ACCOUNT; } @Override public void onClick(View v) { ConfirmRemoveAccountDialog.show(mParentFragment, mAccount); } public void setAccount(Account account) { mAccount = account; } /** * Dialog to confirm with user about account removal */ public static class ConfirmRemoveAccountDialog extends InstrumentedDialogFragment implements DialogInterface.OnClickListener { private static final String SAVE_ACCOUNT = "account"; private static final String REMOVE_ACCOUNT_DIALOG = "confirmRemoveAccount"; private Account mAccount; public static ConfirmRemoveAccountDialog show(Fragment parent, Account account) { if (!parent.isAdded()) { return null; } final ConfirmRemoveAccountDialog dialog = new ConfirmRemoveAccountDialog(); dialog.mAccount = account; dialog.setTargetFragment(parent, 0); dialog.show(parent.getFragmentManager(), REMOVE_ACCOUNT_DIALOG); return dialog; } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { final Context context = getActivity(); if (savedInstanceState != null) { mAccount = (Account) savedInstanceState.getParcelable(SAVE_ACCOUNT); } return new AlertDialog.Builder(context) .setTitle(R.string.really_remove_account_title) .setMessage(R.string.really_remove_account_message) .setNegativeButton(android.R.string.cancel, null) .setPositiveButton(R.string.remove_account_label, this) .create(); } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putParcelable(SAVE_ACCOUNT, mAccount); } @Override public int getMetricsCategory() { return MetricsProto.MetricsEvent.DIALOG_ACCOUNT_SYNC_REMOVE; } @Override public void onClick(DialogInterface dialog, int which) { Activity activity = getTargetFragment().getActivity(); AccountManager.get(activity).removeAccountAsUser(mAccount, activity, new AccountManagerCallback() { @Override public void run(AccountManagerFuture future) { // If already out of this screen, don't proceed. if (!getTargetFragment().isResumed()) { return; } boolean failed = true; try { if (future.getResult() .getBoolean(AccountManager.KEY_BOOLEAN_RESULT)) { failed = false; } } catch (OperationCanceledException e) { // handled below } catch (IOException e) { // handled below } catch (AuthenticatorException e) { // handled below } final Activity activity = getTargetFragment().getActivity(); if (failed && activity != null && !activity.isFinishing()) { RemoveAccountFailureDialog.show(getTargetFragment()); } else { activity.finish(); } } }, null, Process.myUserHandle()); } } /** * Dialog to tell user about account removal failure */ public static class RemoveAccountFailureDialog extends InstrumentedDialogFragment { private static final String FAILED_REMOVAL_DIALOG = "removeAccountFailed"; public static void show(Fragment parent) { if (!parent.isAdded()) { return; } final RemoveAccountFailureDialog dialog = new RemoveAccountFailureDialog(); dialog.setTargetFragment(parent, 0); dialog.show(parent.getFragmentManager(), FAILED_REMOVAL_DIALOG); } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { final Context context = getActivity(); return new AlertDialog.Builder(context) .setTitle(R.string.really_remove_account_title) .setMessage(R.string.remove_account_failed) .setPositiveButton(android.R.string.ok, null) .create(); } @Override public int getMetricsCategory() { return MetricsProto.MetricsEvent.DIALOG_ACCOUNT_SYNC_FAILED_REMOVAL; } } }