Проверьте, активна ли активность

У меня проблема с слушателем в определенной деятельности.

Проблема заключается в том, что этот слушатель содержит alert.show(); который можно вызвать после того, как мы попытаемся нажать новую активность (которая затем дает исключение).

Например: я слушаю активность A для сигнала с другого телефона. Я возвращаюсь назад и пытаюсь запустить новую активность B, но программа вылетает из-за alert.show() прослушивателя.

ERROR/AndroidRuntime(3573): android.view.WindowManager$BadTokenException: Unable to add window -- token [email protected] is not valid; is your activity running?

Можно ли проверить в прослушивателе, активна ли эта активность, а затем показывать предупреждение или нет в зависимости от этого значения?

Ответ 1

Может быть, более простой способ я не могу придумать, но один из способов - реализовать его самостоятельно. На onResume() вы установите переменную-член mIsRunning в true и на onPause() обратно на false. Используя это логическое значение, вы должны знать, что не вызываете alert.show() в ваш обратный вызов.

Ответ 2

ArrayList<String> runningactivities = new ArrayList<String>();

ActivityManager activityManager = (ActivityManager)getBaseContext().getSystemService (Context.ACTIVITY_SERVICE); 

List<RunningTaskInfo> services = activityManager.getRunningTasks(Integer.MAX_VALUE); 

    for (int i1 = 0; i1 < services.size(); i1++) { 
        runningactivities.add(0,services.get(i1).topActivity.toString());  
    } 

    if(runningactivities.contains("ComponentInfo{com.app/com.app.main.MyActivity}")==true){
        Toast.makeText(getBaseContext(),"Activity is in foreground, active",1000).show(); 

        alert.show()
    }

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

Это будет работать, когда мы будем перемещаться между двумя действиями без завершения.

Ответ 3

Это происходит, когда Activity будет проходить через его уничтожение, когда фоновый поток завершит свою работу и попытается показать диалог.

Это исключение редко воспроизводится, но происходит, когда мы выполняем операцию async task/background и хотим отобразить диалог с Контекст активности и в среднем, пока наша деятельность разрушает себя по какой-то причине.

ОС Android должна справиться с этой ситуацией, но на данный момент это не так.

поэтому перед вызовом вашего диалога просто проверьте, запущена ли работа, а не в фазе ее уничтожения.

if(!isFinishing()){
 callDialog();
}

Ответ 4

Фоновый поток после завершения сетевых задач вызывает обратный вызов onSuccess()/onFailure() в основном потоке. И если в то время активность, инициировавшая эту задачу фонового потока, не была на переднем плане и вы пытаетесь использовать getActivity() в onSuccess()/onFailure(), это даст вам исключение. Поэтому попробуйте добавить эту проверку перед выполнением каких-либо операций пользовательского интерфейса.

if(!((Activity) context).isFinishing())
{
    //show alert
}

Ответ 5

Да, вы можете проверить, активна ли активность: Обновление активности из службы при активном

Кроме того, если вы ничего не делаете, когда ваша активность неактивна, вам, вероятно, следует отменить регистрацию слушателя, когда ваша активность деактивируется.

Ответ 6

У меня было 2 действия A и B, я просто хотел узнать, работает ли операция B или нет.

Изначально я следил за "RunningTaskInfo" для решения проблемы, он не работал на 100%.

Итак, я создал собственное решение, я опубликую свое решение. Использование классов HashMap и AtomicBoolean.

public class ActivityStateTracker {
final private Map<String, AtomicBoolean> mMap = new HashMap<String, AtomicBoolean>();

private static ActivityStateTracker instance = null;
/**
 * SingletonClass
 * */
private ActivityStateTracker() {

}

public static ActivityStateTracker getInstance(String activityName, boolean defaultVal) {

    if(instance == null) {
        instance = new ActivityStateTracker();
    }
    instance.setDefaultValue(activityName, defaultVal);
    return instance;
}

private void setDefaultValue(String activityName, boolean defaultVal) {
    mMap.put(activityName, new AtomicBoolean(defaultVal));
}

public boolean isRunning(String activityName) {
    final AtomicBoolean atomicBool = mMap.get(activityName);
    return (mMap.get(activityName) == null) ? false : atomicBool.get();
}

public void setChangeState(String activityName, boolean value) {
    final AtomicBoolean atomicBool = mMap.get(activityName);

    if(atomicBool == null) {
        setDefaultValue(activityName, value);
    } else {
        atomicBool.set(value);
        mMap.put(activityName, atomicBool);
    }
}

}

Теперь в действии B.

 public static final String TAG = "EditScreenPopupActivity";

static ActivityStateTracker mActivityState = ActivityStateTracker.getInstance(TAG, false);

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mActivityState.setChangeState(TAG, true);

    requestWindowFeature(Window.FEATURE_NO_TITLE);

    setContentView(R.layout.activity_traslucent);

}

@Override
protected void onDestroy() {
    mActivityState.setChangeState(TAG, false);
    super.onDestroy();
}

Теперь в действии A.

public static final String TAG = "ToolTipPopupActivity";

static ActivityStateTracker mActivityState = ActivityStateTracker.getInstance(TAG, false);

   /** Check Edit screen activity is running or not? */
   if(mActivityState.isRunning("EditScreenPopupActivity")) {
        finish();
    }

......................................

Это решение работает правильно в моем случае.. Я надеюсь, что это тоже поможет вам.

Ответ 7

Для уровня API> = 23 вы можете использовать свойство активности "жизненный цикл" для определения состояния активности. Это дает очень компактный код. Вот пример кода в Kotlin, как расширение класса:

fun FragmentActivity.isRunning() = lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)

// ...
// Here 'myActivity' can be inherited from different activity-like classes, 
// for example, from class AppCompatActivity:
if (myActivity.isRunning()) {
    Log.d("log", "Activity is running!")
}