android 检查活动是否有效

8ljdwjyq  于 2022-11-27  发布在  Android
关注(0)|答案(9)|浏览(134)

我在某个活动中遇到了听众问题。
问题是这个侦听器包含一个alert.show();,在我们尝试推送一个新活动之后可以调用该侦听器(然后会出现异常)。
例如:我在Activity A中侦听来自另一部电话的信号。我按下返回键并尝试运行新Activity B,但由于alert.show()A的侦听器,程序崩溃。

ERROR/AndroidRuntime(3573): android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@476c21c0 is not valid; is your activity running?

我是否可以在A的侦听器中检查此活动是否处于活动状态,然后根据此值是否显示警报?

cgfeq70w

cgfeq70w1#

可能有一个更简单的方法,我想不出来,但有一个方法是自己实现它。在onResume()上,你设置一个成员变量mIsRunning为true,在onPause()上,你设置回false。使用这个布尔值,你应该知道不要在回调时调用alert.show()

r1zhe5dt

r1zhe5dt2#

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()
    }

这样,您就可以知道所指向的活动是否是当前可见的活动,否则您的警报将不会显示。
只有当我们在两个没有完成的活动之间导航时,这才起作用。

6kkfgxo0

6kkfgxo03#

当后台线程完成其工作并尝试显示对话框时,“活动”将经历其销毁,此时会发生这种情况。
此异常很少重现,但当我们执行一些异步任务/后台操作,并希望显示一个带有Activity上下文的对话框,同时Activity由于某种原因正在自行销毁时,就会发生此异常。
Android OS应该可以处理这种情况,但截至目前还没有。
因此在调用对话框之前,只需检查Activity是否正在运行,而不是处于其销毁阶段。

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

gcmastyq4#

后台线程在完成其网络任务后,会在主线程上调用回调onSuccess()/onFailure()。如果此时,启动此后台线程任务的Activity不在前台,并且您尝试在onSuccess()/onFailure()中使用getActivity(),则会给予异常。因此,请尝试在执行任何UI操作之前添加此检查。

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

slsn1g295#

是,您可以检查活动是否处于活动状态:Refreshing an Activity from service when Active
此外,如果在“活动”处于非活动状态时未执行任何操作,则可能应该在“活动”停用时取消注册侦听器。

5jdjgkvh

5jdjgkvh6#

对于API level〉= 23,你可以使用activity的'lifecycle'属性来检测activity的状态。这给出了一个非常紧凑的代码。下面是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!")
}
vohkndzv

vohkndzv7#

我有两个活动A和B,我只是想知道活动B是否从A运行。
最初我遵循“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();
    }

......................................
这个解决方案在我的情况下工作正常。。我希望它对你也有帮助。

o2g1uqev

o2g1uqev8#

如果你不想在关闭活动后显示警报对话框或其他操作,请使用此代码。它工作100%准确。

if(!(DownloadVideoActivity.this.isDestroyed()))
{
   //show alert dialog or other things
}
z18hc3ub

z18hc3ub9#

当Activity被销毁,但未完成的业务逻辑仍在运行,并且当它完成时,其逻辑已准备好在UI中显示结果时,就会发生这种错误。例如,显示对话框窗口或显示后台任务的结果支持新旧Android版本,并避免兼容性问题以确定您的Activity是否仍在运行的最佳方法如下:

//check if activity is running. if so, display a dialog or what ever 
        final Boolean isAlive = isActivityRunning("com.example.mypackage.MyActivity.this");
        if (isAlive) {
            //Activity is running, you can show a dialog here or do what ever you like here
           
        }

public static Boolean isActivityRunning(Context context) {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
        ActivityManager am = (ActivityManager) context.getSystemService(ACTIVITY_SERVICE);
        ActivityManager.RunningTaskInfo foregroundTaskInfo = am.getRunningTasks(1).get(0);
        String foregroundTaskPackageName = foregroundTaskInfo.topActivity.getPackageName();

        return foregroundTaskPackageName.toLowerCase().equals(context.getPackageName().toLowerCase());
    } else {
        ActivityManager.RunningAppProcessInfo appProcessInfo = new ActivityManager.RunningAppProcessInfo();
        ActivityManager.getMyMemoryState(appProcessInfo);
        if (appProcessInfo.importance == IMPORTANCE_FOREGROUND || appProcessInfo.importance == IMPORTANCE_VISIBLE) {
            return true;
        }

        KeyguardManager km = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
        // App is foreground, but screen is locked, so show notification
        return km.inKeyguardRestrictedInputMode();
    }

}

相关问题