android.view.WindowManager $ BadTokenException ошибка при создании диалогового окна - PullRequest
0 голосов
/ 26 мая 2018

Я пытаюсь создать диалоговое окно из неактивного класса.

Это мой код

  public static void ShowDialogBox(final Context con, final Listener list) {
        AlertDialog.Builder dlgAlert = new AlertDialog.Builder(con);
        dlgAlert.setMessage("TEXT");
        dlgAlert.setTitle("TEXT");
        dlgAlert.setPositiveButton("TEXT"),
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {

                    }
                });
        dlgAlert.setCancelable(false);
        dlgAlert.create().show(); // THIS LINE GIVES ME AN ERROR
    }

Это ошибка, которую я получаю

android.view.WindowManager $ BadTokenException: в android.view.ViewRootImpl.setView (ViewRootImpl.java:574) в android.view.WindowManagerGlobal.addView (WindowManagerGlobal.java:282) в android.view.l.MadanWindowManagerImpl.java:85)
at android.app.Dialog.show (Dialog.java:298) в ИМЯ ПАКЕТА И ИМ КЛАССА И ИМ КЛАССА В ПАКЕТЕ И ИМ КЛАССА И ИМ КЛАССА ПАКЕТА НА ИМЯ ПАКЕТА И КЛАСС.onBackPressed (Class.java:95) на android.app.Activity.onKeyUp (Activity.java:2465) на android.view.KeyEvent.dispatch (KeyEvent.java:2646) на android.app.Activity.dispatchKeyEvent (Activity.java:2716) в android.support.v7.internal.view.WindowCallbackWrapper.dispatchKeyEvent (WindowCallbackWrapper.java:50) в android.support.v7.app.AppCompatDelegateImplBase $ AppCompatWindowCallbackBase.dispatchKeyEvent (AppCompatDelegateImplBase.java:224) на com.android.internal.policy.impl.PhoneWindow $ DecorView.dispatchKeyEvent (PhoneWindow.java:2280) на android.view.ViewRootImpl $ ViewPostImeInputStage.processKroidIotIotIo40).view.ViewRootImpl $ ViewPostImeInputStage.onProcess (ViewRootImpl.java:4000) в android.view.ViewRootImpl $ InputStage.deliver (ViewRootImpl.java:3562) в android.view.ViewRootImpl $ InputStage.otIeItlandroid.view.ViewRootImpl $ InputStage.forward (ViewRootImpl.java:3581) в android.view.ViewRootImpl $ AsyncInputStage.forward (ViewRootImpl.java:3698) в android.view.ViewRootImpl $ InputStage.appmp.jpg35 (View)
в android.view.ViewRootImpl $ AsyncInputStage.apply (ViewRootImpl.java:3755) в android.view.ViewRootImpl $ InputStage.deliver (ViewRootImpl.java:3562) в android.view.ViewRootImplext.Java: 3615) на android.view.ViewRootImpl $ InputStage.forward (ViewRootImpl.java:3581) в android.view.ViewRootImpl $ InputStage.apply (ViewRootImpl.java:3589) в android.view.ViewRootImpl $ InputStage.deliver (ViewRootImpl.java:3562) в android.view.ViewRootImpl $ InputStage.onImpl.jpg: 3615) в android.view.ViewRootImpl $ InputStage.forward (ViewRootImpl.java:3581) в android.view.ViewRootImpl $ AsyncInputStage.forward (ViewRootImpl.java:3731) в android.view.ViewRootImpl.Java: 3892) в android.view.inputmethod.InputMethodManager $ PendingEvent.run (InputMethodManager.java:2208) в android.view.inputmethod.InputMethodManager.invokeFinishedInputEventCallback (InputMetroiddhoin.putinvent.putinvent.putinvent.putinvent.putinvent.putinvent.putinvent.putinvent.putinvent.putinvent.putinvent.putinvent.putinvent.putinvent.putinput.putinvent.putinvent.putinvent.putinvent.putinvent.putinput.putinvent.putinvent.putinput.ventinput.ventinput.ventinput.ventinput.ventin.in.put.ventinput.ventinput.ventin.put.ventin.put.ventin.put.ventin.put.ventin.put.ventinput.ventin.put.ventin.put.(InputMethodManager.java:1840) в android.view.inputmethod.InputMethodManager $ ImeInputEventSender.onInputEventFinished (InputMethodManager.java:2185) в android.view.InputEventSender.dispatchInputEvent:SQ.jpg.jjSQMueue.nativePollOnce (собственный метод) в android.os.MessageQueue.next (MessageQueue.java:143) в android.os.Looper.loop (Looper.java:122) в android.app.ActivityThread.main (ActivityThread.java:5254) в java.lang.reflect.Method.invoke (собственный метод) в java.lang.reflect.Method.invoke (Method.java:372) в com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run (ZygoteInit.Java: 902) на com.android.internal.os.ZygoteInit.main (ZygoteInit.java:697)

Вот сценарий пользователя

Упражнение A-> Открывает занятие B -> Пользователь нажимает кнопку «Назад» в занятии B -> При нажатии кнопки «Назад» слушатель отправляется на занятие A -> И затем вызывается показанное диалоговое окно.

Ответы [ 3 ]

0 голосов
/ 26 мая 2018

Проблема

Вы можете отображать диалоги только из контекста действия. кроме TYPE_SYSTEM_ALERT или TYPE_APPLICATION_OVERLAY, что не рекомендуется, если ваше приложение не показывает экстренные уведомления пользователю.

Решение

Если у вас есть доступный контекст активностизатем вы можете показать диалог из любого класса, например service, broadcast receiver, или даже из любого класса, который вы себе представляете.

Вот мой обходной путь, который может показать диалог из любого класса, как я сказал.

Вот фрагмент, который я делаю, чтобы показать диалоги из любого класса.( Может ли быть проще! )

import android.app.Dialog;
import android.content.DialogInterface;

public class SampleClass {
    void anyMethod() {
        Dialog dialog = ApplicationContext.getInstance().showDialog("title", "yourMessage", "Cancel", "Ok", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                // TODO: handle button 1 clicked 
            }
        }, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                // TODO: handle button 2 clicked
            }
        });
    }
}

Теперь вы реализуете эту работу.

1.Создайте класс приложения, который вы зарегистрируете в теге приложения android manifest

  <application
    android:name=".ApplicationContext"
    ...
    >
      ...
  </application>

2.В этом классе приложения вы будете держать объект живой активности.это будет полезно для отображения диалогового окна.

ApplicationContext.java

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Application;
import android.content.DialogInterface;


public class ApplicationContext extends Application {
    private static ApplicationContext mInstance;
    private Activity liveActivity;

    @Override
    public void onCreate() {
        super.onCreate();
        mInstance = this;
    }

    @Override
    public void onTerminate() {
        super.onTerminate();
        mInstance = null;
    }

    public static synchronized ApplicationContext getInstance() {
        return mInstance;
    }

    public Activity getLiveActivity() {
        return liveActivity;
    }

    public void setLiveActivity(Activity liveActivity) {
        this.liveActivity = liveActivity;
    }

    /*
     * Show Dialog with Title, Message, Button1, Button2 with Button1 and Button2 Listener
     */
    public AlertDialog showDialog(String title, String msg,
                                  String btn1, String btn2,
                                  DialogInterface.OnClickListener listener1,
                                  DialogInterface.OnClickListener listener2) {
        if (liveActivity == null) return null;
        AlertDialog.Builder builder = new AlertDialog.Builder(liveActivity)
                .setTitle(title)
                .setMessage(msg)
                .setCancelable(false)
                .setPositiveButton(btn1, listener1);
        if (btn2 != null)
            builder.setNegativeButton(btn2, listener2);

        AlertDialog alert = builder.create();
        alert.show();
        return alert;
    }
}

Еще один шаг

3.Вы расширите всю свою активность этим базовым классом активности (Вы можете редактировать свою базовую активность, если она у вас уже есть.)

import android.support.v7.app.AppCompatActivity;

public class BaseActivity extends AppCompatActivity {
    @Override
    protected void onResume() {
        super.onResume();
        ApplicationContext.getInstance().setLiveActivity(this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        ApplicationContext.getInstance().setLiveActivity(null);
    }
}

Вот, пожалуйста, *

0 голосов
/ 27 мая 2018

Проблема, с которой вы столкнулись при попытке построить ваш AlertDialog в отдельном классе, заключается в том, что вы передаете AlertDialog Context вашего Activity.Вы получаете ошибку, потому что AlertDialog требует WindowManager от Activity, который имеет макет, а не Context.Это потому, что Activit расширяет Context ... не наоборот.

Для того, чтобы ваш код работал, вам необходимо предоставить AlertDialog.Builder доступ к Activity.Поэтому измените ваш код на что-то вроде этого:

public class TestDialog {

    private static final String TAG = TestDialog.class.getSimpleName();

    Activity mActivity;

    public TestDialog(Activity activity){
        mActivity = activity;
    }


    public void showDialog(){
        AlertDialog.Builder b = new AlertDialog.Builder(mActivity);
        b.setTitle("Title");
        b.setMessage("message");
        b.setPositiveButton("OK", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                Log.e(TAG, "showDialog : onClick");
            }
        });
        b.create().show();
    }
}

Теперь вы можете вызвать AlertDialog из Activity, скажем, в этом случае MainActivity, например:

TestDialog testDialog = new TestDialog(MainActivity.this);
testDialog.showDialog();

Я не пробовал это с Fragment, поэтому я не знаю, работает ли это с Fragment или у вас будут проблемы с определенными устройствами.По этим причинам я (и Google!) По-прежнему настоятельно рекомендую вместо этого использовать DialogFragment, поскольку он был специально разработан для этого сценария.Посмотрите на Google Docs.:

https://developer.android.com/guide/topics/ui/dialogs

0 голосов
/ 26 мая 2018

Я обычно предпочитаю использовать DialogFragment вместо того, что вы пытались сократить количество повторений.Вот пример DialogFragment с пользовательским макетом, который я назвал R.layout.fragment_alert_dialog:

public class AlertDialogFragment extends DialogFragment {

    private static final String ARG_TITLE = "title";
    private static final String ARG_MESSAGE = "message";

    private String title;
    private String message;
    boolean endSuccess = false;

    private AlertFinishedDialogListener mListener;

    public AlertDialogFragment() {
    }

    public static AlertDialogFragment newInstance(String title, String message) {
        AlertDialogFragment fragment = new AlertDialogFragment();
        Bundle args = new Bundle();
        args.putString(ARG_TITLE, title);
        args.putString(ARG_MESSAGE, message);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            title = getArguments().getString(ARG_TITLE);
            message = getArguments().getString(ARG_MESSAGE);
        }
    }

    @Override
    public Dialog onCreateDialog(Bundle saveIntsanceState){

        final Context context = getActivity();

        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

        LayoutInflater inflater = getActivity().getLayoutInflater();

        View rootView = inflater.inflate(R.layout.fragment_alert_dialog, null, false);
        final TextView titleView = (TextView)rootView.findViewById(R.id.tvTitle);
        final TextView messView = (TextView)rootView.findViewById(R.id.tvMessage);

        titleView.setText(title);
        messView.setText(message);

        builder.setView(rootView)
//                .setTitle(title)
                .setPositiveButton(R.string.ok_button_dialog_title, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {

                        endSuccess = true;
                        if(mListener == null) mListener = (AlertFinishedDialogListener) context;
                        mListener.onAlertFinishedDialog();
                    }
                });
        return builder.create();
    }


    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        try {
            if(mListener == null) mListener = (AlertFinishedDialogListener) context;
        }
        catch (Exception ex){
            throw new RuntimeException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    public interface AlertFinishedDialogListener {
        void onAlertFinishedDialog();
    }
}

. Он включает Listener на тот случай, если вам нужно получить уведомление, когда DialogFragmentзавершено.

Сначала вам необходимо реализовать обратный вызов: implements AlertDialogFragment.AlertFinishedDialogListener{

Чтобы позвонить на AlertDialogFragment, вы делаете это из своего Activity (также Fragment, если необходимо).

private void startAlertDialogFragment(String title, String mess){
    AlertDialogFragment alert = AlertDialogFragment.newInstance(title, mess);
    alert.show(getFragmentManager(), "alertDialogFragment132");
}

@Override
public void onAlertFinishedDialog() {
    Log.e(TAG, "onAlertFinishedDialog");
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...