WindowManager BadTokenException: сбой моего приложения на некоторых устройствах

Я разрабатываю приложение, позволяющее пользователю активировать функцию. когда мой пользователь не использовал приложение до 15 минут ... тогда он автоматически покажет диалоговое окно с предупреждением о неактивности сеанса в том последнем действии, которое использовал пользователь.

В этом случае я обрабатываюсь с помощью этого класса BaseActivity:

public class MyBaseActivity extends AppCompatActivity {

    public AlertDialog alertDialog;

    Context context;

    String strCheck = "";
    public Long min = 0L;
    public int min1 = 0;

    public static final long DISCONNECT_TIMEOUT = 900000; // 15 min = 15 * 60 * 1000 ms

    private  Handler disconnectHandler = new Handler(){
        public void handleMessage(Message msg) {
        }
    };

    private Runnable disconnectCallback = new Runnable() {
        @Override
        public void run() {

            AlertDialog.Builder builder = new AlertDialog.Builder(MyBaseActivity.this,R.style.DialogLevelsStyle);
            builder.setTitle("USER IN-ACTIVE");
            builder.setMessage("Due to user is inactive from last 15 minutes. Please Login Again")
                    .setCancelable(false)
                    .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            //do things
                            Intent i = new Intent(MyBaseActivity.this, SignInActivity.class);
                            i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                            startActivity(i);
                            finish();
                            Constant.val = 1;
                            AccountUtils.setValue("1");
                            AccountUtils.setTime("0");
                        }
                    });
            alertDialog = builder.create();
            alertDialog.show();  ///// Crash coming here  // this is line number 77

        }
    };

    public void resetDisconnectTimer(){
        Log.i("Main", "Invoking logout timer");
        //disconnectHandler.removeCallbacks(disconnectCallback);
        disconnectHandler.postDelayed(disconnectCallback, DISCONNECT_TIMEOUT);
    }

    public void stopDisconnectTimer(){
        Log.i("Main", "cancel timer");
        disconnectHandler.removeCallbacks(disconnectCallback);
    }

    @Override
    public void onUserInteraction(){
        resetDisconnectTimer();
    }

    @Override
    public void onResume() {
        super.onResume();
        stopDisconnectTimer();
        resetDisconnectTimer();
        checktimings(getCurrentTime(),AccountUtils.getTime());
        System.out.println("Main : start"+ AccountUtils.getTime());
        if (min1 >= 15){
            System.out.println("Main : Conditionnnnn"+0);
            AccountUtils.setTime("0");
            AlertDialog.Builder builder = new AlertDialog.Builder(MyBaseActivity.this,R.style.DialogLevelsStyle);
            builder.setTitle("USER IN-ACTIVE");
            builder.setMessage("Due to user is inactive from last 15 minutes. Please Login Again")
                    .setCancelable(false)
                    .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            //do things
                            Intent i = new Intent(MyBaseActivity.this, SignInActivity.class);
                            //i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                            startActivity(i);
                            finish();
                            Constant.val = 1;
                            AccountUtils.setValue("1");
                            AccountUtils.setTime("0");

                        }
                    });
            alertDialog = builder.create();
            alertDialog.show();
        }else {
            System.out.println("Main : Condition"+ min1);
            AccountUtils.setTime("0");
        }
        //System.out.println("Main : Start");

    }

    @Override
    public void onStop() {
        if (isAppIsInBackground(this)) {
            AccountUtils.setTime(getCurrentTime());
            System.out.println("Main : Stop"+ getCurrentTime());
            stopDisconnectTimer();
            resetDisconnectTimer();
        }else {
            stopDisconnectTimer();
        }
        super.onStop();
        //stopDisconnectTimer();
    }

    public static boolean isAppIsInBackground(Context context) {
        boolean isInBackground = true;
        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT_WATCH) {
            List<ActivityManager.RunningAppProcessInfo> runningProcesses = am.getRunningAppProcesses();
            for (ActivityManager.RunningAppProcessInfo processInfo : runningProcesses) {
                if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
                    for (String activeProcess : processInfo.pkgList) {
                        if (activeProcess.equals(context.getPackageName())) {
                            isInBackground = false;
                        }
                    }
                }
            }
        } else {
            List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
            ComponentName componentInfo = taskInfo.get(0).topActivity;
            if (componentInfo.getPackageName().equals(context.getPackageName())) {
                isInBackground = false;
            }
        }

        return isInBackground;
    }

    public static String getCurrentTime() {
        //date output format
        DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
        Calendar cal = Calendar.getInstance();
        return dateFormat.format(cal.getTime());
    }

    public  void checktimings(String time, String endtime) {
        try{
            SimpleDateFormat in = new SimpleDateFormat("HH:mm:ss");
            Date tempDate = in.parse(time);
            Date tempDate1 = in.parse(endtime);

            long diff = tempDate.getTime() - tempDate1.getTime();
            min = TimeUnit.MINUTES.convert(diff, TimeUnit.MILLISECONDS);
            min1 = min.intValue();
            System.out.println("Main "+min1);

        }catch (Exception e){

        }
    }

    @Override
    public void onDestroy(){
        super.onDestroy();
        if (alertDialog != null && alertDialog.isShowing()){
            alertDialog.dismiss();
            //SignInActivity.alertDialog.dismiss();
        }
    }
}

Когда время сеанса истекло, это диалоговое окно с предупреждением отображается в моем последнем использованном действии, в это время я получаю сообщение об ошибке ниже: (В основном ошибка произошла на устройствах Samsung)

android.view.WindowManager$BadTokenException: 
  at android.view.ViewRootImpl.setView (ViewRootImpl.java:878)
  at android.view.WindowManagerGlobal.addView (WindowManagerGlobal.java:342)
  at android.view.WindowManagerImpl.addView (WindowManagerImpl.java:97)
  at android.app.Dialog.show (Dialog.java:556)
  at com.Forewarn.ForewarnApp.MyBaseActivity$2.run (MyBaseActivity.java:77)
  at android.os.Handler.handleCallback (Handler.java:751)
  at android.os.Handler.dispatchMessage (Handler.java:95)
  at android.os.Looper.loop (Looper.java:154)
  at android.app.ActivityThread.main (ActivityThread.java:6692)
  at java.lang.reflect.Method.invoke (Native Method)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:1468)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1358)

Я попытался с уже добавленным дистрибутивом всех окон в действии, прежде чем перейти к другому действию, используя этот код:

@Override
    public void onDestroy(){
        super.onDestroy();
        if (alertDialog != null && alertDialog.isShowing()){
            alertDialog.dismiss();
            //SignInActivity.alertDialog.dismiss();
        }
    }

Я не могу исправить эту ошибку на некоторых моих устройствах Android

вам, вероятно, нужно проверить, запущено ли действие, прежде чем показывать диалоговое окно

Vladyslav Matviienko 30.03.2018 13:55

Нет ... я уже проверил ... после отображения диалога, когда я нажимаю "ОК", только действие переходит в действие входа в систему .. в противном случае оно не запускается ..

Dolly 30.03.2018 14:18
1
2
254
1

Ответы 1

Я столкнулся с той же проблемой в своих приложениях, ее трудно воспроизвести, вы можете использовать это, чтобы предотвратить сбой:

if (!((AppCompatActivity)YourActivity).isFinishing()) {
   try {
         AlertDialog alert = builder.create();
         alert.show();
   }
   catch (WindowManager.BadTokenException e) {
           e.printStackTrace();
   }
 }

Другие вопросы по теме