Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 831172e9 authored by Jiashen Wang's avatar Jiashen Wang Committed by Android (Google) Code Review
Browse files

Merge "[SIM Dialog Migration] Add SIM dialogs to support screen rotation"

parents ca40e8d3 7e04453c
Loading
Loading
Loading
Loading
+68 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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.network.telephony;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.text.TextUtils;

/** Fragment to show an alert dialog which only has the positive button. */
public class AlertDialogFragment extends BaseDialogFragment
        implements DialogInterface.OnClickListener {
    private static final String TAG = "AlertDialogFragment";

    // Arguments
    private static final String ARG_TITLE = "title";
    private static final String ARG_MSG = "msg";

    /**
     * @param activity
     * @param title
     * @param msg
     */
    public static void show(Activity activity, String title, String msg) {
        AlertDialogFragment fragment = new AlertDialogFragment();
        Bundle arguments = new Bundle();
        arguments.putString(ARG_TITLE, title);
        arguments.putString(ARG_MSG, msg);
        fragment.setArguments(arguments);
        fragment.show(activity.getFragmentManager(), TAG);
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        AlertDialog.Builder builder =
                new AlertDialog.Builder(getContext())
                        .setTitle(getArguments().getString(ARG_TITLE))
                        .setPositiveButton(android.R.string.ok, this);
        if (!TextUtils.isEmpty(getArguments().getString(ARG_MSG))) {
            builder.setMessage(getArguments().getString(ARG_MSG));
        }
        return builder.show();
    }

    @Override
    public void onClick(DialogInterface dialog, int which) {
        if (getActivity() != null) {
            getActivity().finish();
        }
        super.dismiss();
    }
}
+102 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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.network.telephony;

import android.app.Activity;
import android.app.DialogFragment;
import android.app.Fragment;
import android.os.Bundle;

import androidx.annotation.Nullable;

/**
 * Base dialog fragment class with the functionality to make a fragment or an activity as a listener
 * which can survive through the activity restarts.
 */
public abstract class BaseDialogFragment extends DialogFragment {
    // Tags for the listener which receives event callbacks.
    private static final String ARG_LISTENER_TAG = "listener_tag";
    private static final String ARG_IN_CALLER_TAG = "in_caller_tag";

    /**
     * @param activity The caller activity or the activity attached with the fragment.
     * @param listener The original caller, that is, the listener. The listener can be the fragment
     *     to receive event callbacks. If it is null, will use the activity to handle the event
     *     callback instead.
     * @param callbackInterfaceClass The interface that the listener should implements.
     * @param arguments The arguments bundle of the dispatcher fragment used to store the listener's
     *     info.
     * @param tagInCaller An integer given by the listener to distinguish the action when calling
     *     the listener's callback function.
     */
    protected static <T> void setListener(
            Activity activity,
            @Nullable Fragment listener,
            Class<T> callbackInterfaceClass,
            int tagInCaller,
            Bundle arguments) {
        checkValidity(activity, listener, callbackInterfaceClass);

        if (listener != null && listener.getParentFragment() != null) {
            throw new IllegalArgumentException("The listener must be attached to an activity.");
        }
        arguments.putInt(ARG_IN_CALLER_TAG, tagInCaller);
        if (listener != null) {
            arguments.putString(ARG_LISTENER_TAG, listener.getTag());
        }
    }

    /**
     * @param callbackInterfaceClass The interface that the listener should implements.
     * @param <T> Template type.
     * @return The listener class.
     */
    @SuppressWarnings("unchecked")
    protected <T> T getListener(Class<T> callbackInterfaceClass) {
        Object listener;
        String listenerTag = getArguments().getString(ARG_LISTENER_TAG);
        if (listenerTag == null) {
            listener = getActivity();
        } else {
            listener = getActivity().getFragmentManager().findFragmentByTag(listenerTag);
        }
        if (callbackInterfaceClass.isInstance(listener)) {
            return (T) listener;
        }
        throw new IllegalArgumentException("The caller should implement the callback function.");
    }

    /** @return The tag set in the listener. */
    protected int getTagInCaller() {
        return getArguments().getInt(ARG_IN_CALLER_TAG);
    }

    private static <T> void checkValidity(
            Activity activity, @Nullable Fragment listener, Class<T> callbackInterfaceClass) {
        if (listener != null) {
            if (!callbackInterfaceClass.isInstance(listener)) {
                throw new IllegalArgumentException(
                        "The listener fragment should implement the callback function.");
            }
        } else {
            if (!callbackInterfaceClass.isInstance(activity)) {
                throw new IllegalArgumentException(
                        "The caller activity should implement the callback function.");
            }
        }
    }
}
+107 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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.network.telephony;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;

/** Fragment to show a confirm dialog. The caller should implement onConfirmListener. */
public class ConfirmDialogFragment extends BaseDialogFragment
        implements DialogInterface.OnClickListener {
    private static final String TAG = "ConfirmDialogFragment";
    private static final String ARG_TITLE = "title";
    private static final String ARG_MSG = "msg";
    private static final String ARG_POS_BUTTON_STRING = "pos_button_string";
    private static final String ARG_NEG_BUTTON_STRING = "neg_button_string";

    /**
     * Interface defining the method that will be invoked when the user has done with the dialog.
     */
    public interface OnConfirmListener {
        /**
         * @param tag The tag in the caller.
         * @param confirmed True if the user has clicked the positive button. False if the user has
         *     clicked the negative button or cancel the dialog.
         */
        void onConfirm(int tag, boolean confirmed);
    }

    /** Displays a confirmation dialog which has confirm and cancel buttons. */
    public static <T> void show(
            Activity activity,
            Class<T> callbackInterfaceClass,
            int tagInCaller,
            String title,
            String msg,
            String posButtonString,
            String negButtonString) {
        ConfirmDialogFragment fragment = new ConfirmDialogFragment();
        Bundle arguments = new Bundle();
        arguments.putString(ARG_TITLE, title);
        arguments.putCharSequence(ARG_MSG, msg);
        arguments.putString(ARG_POS_BUTTON_STRING, posButtonString);
        arguments.putString(ARG_NEG_BUTTON_STRING, negButtonString);
        setListener(activity, null, callbackInterfaceClass, tagInCaller, arguments);
        fragment.setArguments(arguments);
        fragment.show(activity.getFragmentManager(), TAG);
    }

    @Override
    public final Dialog onCreateDialog(Bundle savedInstanceState) {
        String title = getArguments().getString(ARG_TITLE);
        String message = getArguments().getString(ARG_MSG);
        String posBtnString = getArguments().getString(ARG_POS_BUTTON_STRING);
        String negBtnString = getArguments().getString(ARG_NEG_BUTTON_STRING);

        Log.i("Showing dialog with title = %s", title);
        AlertDialog.Builder builder =
                new AlertDialog.Builder(getContext())
                        .setTitle(title)
                        .setPositiveButton(posBtnString, this)
                        .setNegativeButton(negBtnString, this);

        if (!TextUtils.isEmpty(message)) {
            builder.setMessage(message);
        }
        AlertDialog dialog = builder.show();
        dialog.setCanceledOnTouchOutside(false);
        return dialog;
    }

    @Override
    public void onClick(DialogInterface dialog, int which) {
        informCaller(which == DialogInterface.BUTTON_POSITIVE);
    }

    @Override
    public void onCancel(DialogInterface dialog) {
        informCaller(false);
    }

    private void informCaller(boolean confirmed) {
        OnConfirmListener listener = getListener(OnConfirmListener.class);
        if (listener == null) {
            return;
        }
        listener.onConfirm(getTagInCaller(), confirmed);
    }
}
+106 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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.network.telephony;

import android.app.Dialog;
import android.app.DialogFragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.KeyEvent;

/** Fragment to show a progress dialog. */
public class ProgressDialogFragment extends DialogFragment {
    private static final String ARG_TITLE = "title";

    private static final String TAG = "ProgressDialogFragment";

    private OnDismissCallback mDismissCallback;

    // Host fragment is optional to implement this interface.
    public interface OnDismissCallback {
        // Action performed when the progress dialog is dismissed.
        void onProgressDialogDismiss();
    }

    /**
     * Check whether there is already a showing progress dialog. If yes and the title of the showing
     * one is the same with the new coming one, just return and do nothing. If the title of the
     * showing one is different from the new one, remove the showing one and create a new dialog for
     * the new one. If there is no progress dialog right now, just create a new one.
     */
    public static void show(FragmentManager fm, String title, OnDismissCallback dismissCallback) {
        ProgressDialogFragment fragment = (ProgressDialogFragment) fm.findFragmentByTag(TAG);
        if (fragment != null
                && TextUtils.equals(fragment.getArguments().getString(ARG_TITLE), title)) {
            return;
        }

        FragmentTransaction ft = fm.beginTransaction();
        if (fragment != null) {
            ft.remove(fragment);
        }

        fragment = new ProgressDialogFragment();
        fragment.setDismissCallback(dismissCallback);

        Bundle arguments = new Bundle();
        arguments.putString(ARG_TITLE, title);
        fragment.setArguments(arguments);
        fragment.show(ft, TAG);
    }

    /**
     * Called by the caller activity or fragment when the progress is finished.
     *
     * @param fm The fragment manager.
     */
    public static void dismiss(FragmentManager fm) {
        DialogFragment fragment = (DialogFragment) fm.findFragmentByTag(TAG);
        if (fragment != null) {
            fragment.dismiss();
        }
    }

    @Override
    @SuppressWarnings("deprecation") // ProgressDialog is deprecated but is intended UX for now
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        ProgressDialog dialog = new ProgressDialog(getActivity());
        dialog.setCancelable(false);
        dialog.setCanceledOnTouchOutside(false);
        dialog.setMessage(getArguments().getString(ARG_TITLE));
        dialog.setOnKeyListener(
                (progressDialog, keyCode, event) -> KeyEvent.KEYCODE_BACK == keyCode);

        return dialog;
    }

    @Override
    public void onDismiss(DialogInterface dialog) {
        super.onDismiss(dialog);
        if (mDismissCallback != null) {
            mDismissCallback.onProgressDialogDismiss();
        }
    }

    private void setDismissCallback(OnDismissCallback dismissCallback) {
        mDismissCallback = dismissCallback;
    }
}
+10 −42
Original line number Diff line number Diff line
@@ -16,25 +16,24 @@

package com.android.settings.network.telephony;

import android.R;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.os.Bundle;

import androidx.appcompat.app.AlertDialog;
import android.telephony.SubscriptionManager;

/** The base class for subscription action dialogs */
public class SubscriptionActionDialogActivity extends Activity {

    private static final String TAG = "SubscriptionActionDialogActivity";
    // Arguments
    protected static final String ARG_SUB_ID = "sub_id";

    private ProgressDialog mProgressDialog;
    private AlertDialog mErrorDialog;
    protected SubscriptionManager mSubscriptionManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mSubscriptionManager = getSystemService(SubscriptionManager.class);
    }

    /**
@@ -43,20 +42,12 @@ public class SubscriptionActionDialogActivity extends Activity {
     * @param message The string content should be displayed in the progress dialog.
     */
    protected void showProgressDialog(String message) {
        if (mProgressDialog == null) {
            mProgressDialog = ProgressDialog.show(this, null, message);
            mProgressDialog.setCanceledOnTouchOutside(false);
            mProgressDialog.setCancelable(false);
        }
        mProgressDialog.setMessage(message);
        mProgressDialog.show();
        ProgressDialogFragment.show(getFragmentManager(), message, null);
    }

    /** Dismisses the loading dialog. */
    protected void dismissProgressDialog() {
        if (mProgressDialog != null) {
            mProgressDialog.dismiss();
        }
        ProgressDialogFragment.dismiss(getFragmentManager());
    }

    /**
@@ -64,31 +55,8 @@ public class SubscriptionActionDialogActivity extends Activity {
     *
     * @param title The title of the error dialog.
     * @param message The body text of the error dialog.
     * @param positiveOnClickListener The callback function after users confirm with the error.
     */
    protected void showErrorDialog(
            String title, String message, DialogInterface.OnClickListener positiveOnClickListener) {
        if (mErrorDialog == null) {
            mErrorDialog =
                    new AlertDialog.Builder(this)
                            .setTitle(title)
                            .setMessage(message)
                            .setPositiveButton(
                                    R.string.ok,
                                    (dialog, which) -> {
                                        positiveOnClickListener.onClick(dialog, which);
                                        dismissErrorDialog();
                                    })
                            .create();
        }
        mErrorDialog.setMessage(message);
        mErrorDialog.show();
    }

    /** Dismisses the error dialog. */
    protected void dismissErrorDialog() {
        if (mErrorDialog != null) {
            mErrorDialog.dismiss();
        }
    protected void showErrorDialog(String title, String message) {
        AlertDialogFragment.show(this, title, message);
    }
}
Loading