Android:アクティビティが実行されているかどうかを確認するにはどうすればよいですか?


152

特定のアクティビティがアクティブかどうかを判断する簡単な方法はありますか?どの活動が活発であるかに応じて、特定のことをしたいです。例えば:

if(activityrunning == activity1)
//do this
else if (activityrunning == activity2)
//do something else

アクティビティが実行されているかどうかを確認するには、この回答を確認できます:stackoverflow.com/a/39079627/4531507
Rahul Sharma '22

回答:


227

staticアクティビティ内で変数を使用できます。

class MyActivity extends Activity {
     static boolean active = false;

      @Override
      public void onStart() {
         super.onStart();
         active = true;
      } 

      @Override
      public void onStop() {
         super.onStop();
         active = false;
      }
}

唯一の落とし穴は、相互にリンクする2つのアクティビティで使用するとonStop、最初のアクティビティがonStart2番目のアクティビティの後に呼び出されることがあります。したがって、どちらも簡単に当てはまる可能性があります。

何をしようとしているかに応じて(サービスから現在のアクティビティを更新しますか?)。静的リスナーをサービスのアクティビティonStartメソッドに登録するだけで、サービスがUIを更新するときに正しいリスナーを利用できるようになります。


5
メモリリークの問題があるため、静的変数よりも..Sharedpreferenceの方が望ましいと指摘した人もいます。
Ayush Goyal 2013

13
同じクラスのさまざまなアクティビティが実行されている場合はどうなりますか?あなたが延長MyActivityMyChildactivity、子供がアクティブかどうかを確認したい場合はどうなりますか?
ミスタースミス

2
「実行中」のあなたの定義によっては、onResumeとonPauseでの変数の状態....変更する場合があります
G.ブレイクMeike

5
この解決策はまったく良い解決策ではありません。たとえば、アクティビティがフラグメントを呼び出すとしましょう。たとえば、フラグメントはアクティビティの上にありますが、アクティビティはonPauseを呼び出さず、フラグメントを閉じると、onStop、onStart、またはその他のライフサイクルメソッドも呼び出されません。最善の解決策は、ここで説明するように、アプリケーションクラスでの視認性をチェックすることです:stackoverflow.com/questions/18038399/...
portfoliobuilder

6
静力学を推奨すると、私から-1が返されます
Matei Suica

52

この問題はかなり古いものだと思いますが、他の人にも役立つので、私の解決策を共有する価値はあると思います。

このソリューションは、Androidアーキテクチャコンポーネントがリリースされるまでは利用できませんでした。

アクティビティは少なくとも部分的に表示されています

getLifecycle().getCurrentState().isAtLeast(STARTED)

活動は前景にあります

getLifecycle().getCurrentState().isAtLeast(RESUMED)

3
getLifecycle()。getCurrentState()。isAtLeast(Lifecycle.State.RESUMED)
Radhey '28

43

私はそのようにもっと明確だと思います:

  public boolean isRunning(Context ctx) {
        ActivityManager activityManager = (ActivityManager) ctx.getSystemService(Context.ACTIVITY_SERVICE);
        List<RunningTaskInfo> tasks = activityManager.getRunningTasks(Integer.MAX_VALUE);

        for (RunningTaskInfo task : tasks) {
            if (ctx.getPackageName().equalsIgnoreCase(task.baseActivity.getPackageName())) 
                return true;                                  
        }

        return false;
    }

2
「for」ループの前に一時変数を作成しないようにしています。for(RunningTaskInfo task:ActivityManager.getRunningTasks(Integer.MAX_VALUE)){...
mikebabcock

この関数を呼び出すにはどうすればよいですか?
Behzad

1
いつものように、クラス内で「関数」として呼び出すことができるメソッドはありますか?
Xenione

10
developer.android.com/reference/android/app/...「これは、そのような情報に基づいて異なる動作間で決定するように、アプリケーションでコアロジックのために使用すべきではありません、ここで見つけました。このような使用はサポートされていない、と意志おそらく休憩将来は。"
joe_deniable 2014

15
APIレベル21(Android 5.0 Lollipop)以降、このメソッドは廃止されました。
AxeEffect 2014

30

補助変数を使用しないオプションは次のとおりです。

activity.getWindow().getDecorView().getRootView().isShown()

ここで、アクティビティはfe:thisまたはgetActivity()です。

この式によって返される値は、onStart()/ onStop()で変化します。これは、電話でのアクティビティのレイアウトを示す開始/停止イベントです。


16
jsutを使用しないのはなぜActivity#getWindow().getDecorView().isShown()ですか?
Gianluca P.

24

私はMyActivity.classとgetCanonicalNameメソッドを使用して、答えを得ました。

protected Boolean isActivityRunning(Class activityClass)
{
        ActivityManager activityManager = (ActivityManager) getBaseContext().getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningTaskInfo> tasks = activityManager.getRunningTasks(Integer.MAX_VALUE);

        for (ActivityManager.RunningTaskInfo task : tasks) {
            if (activityClass.getCanonicalName().equalsIgnoreCase(task.baseActivity.getClassName()))
                return true;
        }

        return false;
}

1
前述のように、getRunningTasks()廃止されたため、使用することはお勧めできません。androidxref.com
Vitalii Dmitriev

21

静的変数を使用してOOPを実行するよりもはるかに良い方法

Shared Preferences変数を他のactivitiesサービスと共有したり、1つのサービスを使用したりできますapplication

    public class example extends Activity {

    @Override
    protected void onStart() {
        super.onStart();

        // Store our shared preference
        SharedPreferences sp = getSharedPreferences("OURINFO", MODE_PRIVATE);
        Editor ed = sp.edit();
        ed.putBoolean("active", true);
        ed.commit();
    }

    @Override
    protected void onStop() {
        super.onStop();

        // Store our shared preference
        SharedPreferences sp = getSharedPreferences("OURINFO", MODE_PRIVATE);
        Editor ed = sp.edit();
        ed.putBoolean("active", false);
        ed.commit();

    }
}

共有設定を使用します。最も信頼性の高い状態情報があり、アプリケーションの切り替えや破棄の問題が少ないため、さらに別の許可を求める手間が省け、アクティビティが実際に最上位のタイミングを決定するための制御が強化されます。参照詳細はこちら ABDをここにも


ありがとう。しかし、onResumeも必要ですか?

1
アクティブで何を理解しているかによります。私のコードによると、アクティビティはスタックにあり、アクティブです。そして、可視かどうかを処理したい場合は、onResumeを使用できます
Zar E Ahmer

19
これは、アクティビティを呼び出さずに終了すると壊れますonStop()
Marcel Bro

3
アプリがクラッシュするとどうなりますか?
ucMedia 2018

1
これは非常に危険な「解決策」です。
Firzen

9

これは、特定のサービスが実行されているかどうかを確認するためのコードです。getRunningAppProcesses()またはgetRunningTasks()を使用してgetRunningServicesを変更する限り、それがアクティビティでも機能することはかなり確実です。こちらをご覧くださいhttp://developer.android.com/reference/android/app/ActivityManager.html#getRunningAppProcesses()

Constants.PACKAGEおよびConstants.BACKGROUND_SERVICE_CLASSを適宜変更します

    public static boolean isServiceRunning(Context context) {

    Log.i(TAG, "Checking if service is running");

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

    List<RunningServiceInfo> services = activityManager.getRunningServices(Integer.MAX_VALUE);

    boolean isServiceFound = false;

    for (int i = 0; i < services.size(); i++) {

        if (Constants.PACKAGE.equals(services.get(i).service.getPackageName())){

            if (Constants.BACKGROUND_SERVICE_CLASS.equals(services.get(i).service.getClassName())){
                isServiceFound = true;
            }
        }
    }

    Log.i(TAG, "Service was" + (isServiceFound ? "" : " not") + " running");

    return isServiceFound;

}

1
ただし、提供するリンクには「このメソッドは、ユーザーに直接対応するプロセス管理UIのデバッグまたは構築のみを目的としている」と記載されていることに注意してください。
joe_deniable 2014

getRunningTasksは非推奨になりました。
Adi

5

上記のすべてよりもはるかに簡単な方法があり、このアプローチはandroid.permission.GET_TASKSマニフェストでの使用を必要としないか、受け入れられた回答で指摘されている競合状態またはメモリリークの問題を抱えています。

  1. メインアクティビティでSTATIC変数を作成します。Staticを使用すると、他のアクティビティが別のアクティビティからデータを受け取ることができます。onPause()この変数を設定偽をonResumeそしてonCreate()この変数を設定真実

    private static boolean mainActivityIsOpen;
  2. この変数のゲッターとセッターを割り当てます。

    public static boolean mainActivityIsOpen() {
        return mainActivityIsOpen;
    }
    
    public static void mainActivityIsOpen(boolean mainActivityIsOpen) {
        DayView.mainActivityIsOpen = mainActivityIsOpen;
    }
  3. そして、別のアクティビティまたはサービスから

    if (MainActivity.mainActivityIsOpen() == false)
    {
                    //do something
    }
    else if(MainActivity.mainActivityIsOpen() == true)
    {//or just else. . . ( or else if, does't matter)
            //do something
    }

3
アクセサーメソッドを使用する方が、生のパブリック静的変数を使用するよりも優れているとおっしゃっていますか?
IgorGanapolsky 2013

1
Javaでは、変数をプライベートに保つためにセッターとゲッターを使用することをお勧めします。ただし、Androidではパブリック変数に直接アクセスするのが一般的だと思います...
Stephen

11
アクティビティの状態はアクティビティ自体によってのみ処理されるため、パブリックセッターを使用しても意味がありません。Javaの命名規則に従う必要があります。isActivityOpenは正しいゲッターメソッドです。また、ブール== trueの場合の使用は冗長です。それ以外に、状態管理を活動に委任することが最善のアプローチです。
リサンドロ2013年

8
これが、@ coolcoolのコースに熱心に参加すべきだった理由です;)
Jerec TheSith 2013

1
また、アクティビティの複数のインスタンスが実行されている場合はどうなりますか?
nickmartens1980 2014

5
if(!activity.isFinishing() && !activity.isDestroyed())

公式ドキュメントから:

Activity#isFinishing()

このアクティビティが終了処理中であるかどうかを確認してください。このアクティビティでfinish()を呼び出したか、他の誰かが終了を要求したためです。これは、アクティビティが単に一時停止しているか、完全に終了しているかを判別するために、onPause()でよく使用されます。

Activity#isDestroyed()

アクティビティで最後のonDestroy()呼び出しが行われた場合はtrueを返します。そのため、このインスタンスは停止しています。


4

ありがとうkkudi!私はあなたの答えを活動に取り組むように適応させることができました...これが私のアプリで働いたものです。

public boolean isServiceRunning() { 

ActivityManager activityManager = (ActivityManager)Monitor.this.getSystemService (Context.ACTIVITY_SERVICE); 
    List<RunningTaskInfo> services = activityManager.getRunningTasks(Integer.MAX_VALUE); 
    isServiceFound = false; 
    for (int i = 0; i < services.size(); i++) { 
        if (services.get(i).topActivity.toString().equalsIgnoreCase("ComponentInfo{com.lyo.AutoMessage/com.lyo.AutoMessage.TextLogList}")) {
            isServiceFound = true;
        }
    } 
    return isServiceFound; 
} 

この例では、topActivityがユーザーの操作と一致する場合にtrueまたはfalseを返します。したがって、チェック対象のアクティビティが表示されていない場合(つまり、onPauseの場合)、一致は得られません。また、これを行うには、マニフェストに権限を追加する必要があります。

<uses-permission  android:name="android.permission.GET_TASKS"/>

これがお役に立てば幸いです。


1
この用途の許可は、APIレベル21で廃止されましたdeveloper.android.com/reference/android/...
ガイ・ウェストを

2
上位のアクティビティ(services [i] .topActivity)にアクセスするために回答を拒否し、APIレベルQを最小化します。以下では機能しません。
Ghosh

4

受け入れられた答えはこれを扱うひどい方法だと思います。

ユースケースはわかりませんが、基本クラスの保護されたメソッドを検討してください

@protected
void doSomething() {
}

派生クラスでオーバーライドします。

イベントが発生したら、基本クラスでこのメソッドを呼び出すだけです。正しい「アクティブ」クラスがそれを処理します。クラス自体は、そうでないかどうかを確認できPaused()ます。

さらに良いのは、GreenRobotSquareのようなイベントバスを使用することですが、これは非推奨であり、RxJavaの使用を推奨しています。


2

小切手を使用したところ、if (!a.isFinishing())必要な処理が行われたようです。aアクティビティインスタンスです。これは間違っていますか?なぜ誰もこれを試さなかったのですか?



2

ActivityLifecycleCallbacksは、アプリ内のすべてのアクティビティを追跡する優れた方法です。

public class BaseActivityLifecycleCallbacks implements Application.ActivityLifecycleCallbacks {

private ActivityState homeState, contentState;

@Override
public void onActivityCreated(Activity activity, Bundle bundle) {
    if (activity instanceof HomeActivityv2) {
        homeState = ActivityState.CREATED;
    } else if (activity instanceof ContentDisplayActivity) {
        contentState = ActivityState.CREATED;
    }
}

@Override
public void onActivityStarted(Activity activity) {
    if (activity instanceof HomeActivityv2) {
        homeState = ActivityState.STARTED;
    } else if (activity instanceof ContentDisplayActivity) {
        contentState = ActivityState.STARTED;
    }
}

@Override
public void onActivityResumed(Activity activity) {
    if (activity instanceof HomeActivityv2) {
        homeState = ActivityState.RESUMED;
    } else if (activity instanceof ContentDisplayActivity) {
        contentState = ActivityState.RESUMED;
    }
}

@Override
public void onActivityPaused(Activity activity) {
    if (activity instanceof HomeActivityv2) {
        homeState = ActivityState.PAUSED;
    } else if (activity instanceof ContentDisplayActivity) {
        contentState = ActivityState.PAUSED;
    }
}

@Override
public void onActivityStopped(Activity activity) {
    if (activity instanceof HomeActivityv2) {
        homeState = ActivityState.STOPPED;
    } else if (activity instanceof ContentDisplayActivity) {
        contentState = ActivityState.STOPPED;
    }
}

@Override
public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {
}

@Override
public void onActivityDestroyed(Activity activity) {
    if (activity instanceof HomeActivityv2) {
        homeState = ActivityState.DESTROYED;
    } else if (activity instanceof ContentDisplayActivity) {
        contentState = ActivityState.DESTROYED;
    }
}

public ActivityState getHomeState() {
    return homeState;
}

public ActivityState getContentState() {
    return contentState;
}
}

ActivityState:

public enum ActivityState {
    CREATED, STARTED, RESUMED, PAUSED, STOPPED, DESTROYED;
}

Applicationクラスを拡張し、Androidマニフェストファイルでその参照を提供します。

import android.app.Application;

public final class BaseApplication extends Application {
private BaseActivityLifecycleCallbacks baseALC;

@Override
public void onCreate() {
    super.onCreate();
    baseALC = new BaseActivityLifecycleCallbacks();
    this.registerActivityLifecycleCallbacks(baseALC);

}

public BaseActivityLifecycleCallbacks getBaseALC() {
    return baseALC;
}
}

他のアクティビティのステータスについては、アクティビティからどこでもCkeck:

private void checkAndLaunchHomeScreen() {
    Application application = getApplication();
    if (application instanceof BaseApplication) {
        BaseApplication baseApplication = (BaseApplication) application;
        if (baseApplication.getBaseALC().getHomeState() == null || baseApplication.getBaseALC().getHomeState() == ActivityState.DESTROYED) {
            //Do anything you want
        }
    }
}

https://developer.android.com/reference/android/app/Application.ActivityLifecycleCallbacks.html


1

それが「物事を行う」ための「適切な」方法であるかどうかはわかりません。
(またはa)質問を解決するためのAPIの方法が少しあるべきだと思われる場合、おそらく何かが間違っていて、代わりにもっと多くのドキュメントを読んでいる可能性があります
(静的変数はAndroidでは一般的に間違った方法です。動作する可能性はありますが、動作しない場合もあります(たとえば、本番環境では、100万台のデバイス上)。
まさにあなたのケースでは、別のアクティビティが生きているかどうかを知る必要がある理由を考えることをお勧めします。結果のために別のアクティビティを開始して、その機能を取得できます。または、クラスを派生させてその機能などを取得することもできます。
宜しくお願いします。


1

アクティビティの特定のインスタンスのライフサイクル状態に関心がある場合、siliconagleのソリューションは正しいように見えますが、新しい「アクティブ」変数は静的ではなくインスタンス変数である必要があります。


1

順序付きブロードキャストを使用します。http://android-developers.blogspot.nl/2011/01/processing-ordered-broadcasts.htmlをご覧ください

アクティビティで、onStartでレシーバーを登録し、onStopで登録解除します。たとえば、アクティビティがより良い処理を行うことができるサービスをサービスで処理する必要がある場合は、サービスから順序付きブロードキャストを送信します(サービス自体にデフォルトのハンドラーを使用)。これで、実行中にアクティビティで応答できます。サービスは結果データをチェックして、ブロードキャストが処理されたかどうかを確認し、適切でない場合は処理を実行できます。


1

承認された回答に加えてアクティビティのインスタンスが複数ある場合は、代わりにカウンターを使用できます。

class MyActivity extends Activity {

     static int activeInstances = 0;

     static boolean isActive() {
        return (activeInstance > 0)
     }

      @Override
      public void onStart() {
         super.onStart();
         activeInstances++;
      } 

      @Override
      public void onStop() {
         super.onStop();
         activeInstances--;
      }
}

戻り行に「s」と「;(セミコロン)」がありません。
Ali_dev 2018


0

次のコードで簡単な回避策を見つけました

@Override 
protected void onCreate(Bundle savedInstanceState) { 
            super.onCreate(savedInstanceState); 
            if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) { 
                // Activity is being brought to front and not being  created again, 
                // Thus finishing this activity will bring the last viewed activity to foreground
                finish(); 
            } 
    }

0

isActivity変数を使用して、アクティビティがアクティブかどうかを確認します。

private boolean activityState = true;

 @Override
protected void onDestroy() {
    super.onDestroy();
    activityState = false;
}

次に確認してください

if(activityState){
//add your code
}

0

アクティビティがバックスタックにあるかどうかを確認する場合は、次の手順に従ってください。1.アプリケーションクラスでArrayListを宣言しました[アプリケーションクラスはアプリケーションタグのmainfestファイルで定義されています]

private ArrayList<Class> runningActivities = new ArrayList<>();
  1. このリストにアクセスして変更するには、次のパブリックメソッドを追加します。

    public void addActivityToRunningActivityies (Class cls) {
    if (!runningActivities.contains(cls)) runningActivities.add(cls);
    }
    
    public void removeActivityFromRunningActivities (Class cls) {
    if (runningActivities.contains(cls)) runningActivities.remove(cls);
    }
    
    public boolean isActivityInBackStack (Class cls) {
    return runningActivities.contains(cls);
    }
  2. BaseActivityでは、すべてのアクティビティがそれを拡張するため、onCreateメソッドとonDestroyメソッドをオーバーライドして、次のようにバックスタックにアクティビティを追加および削除できるようにします。

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    
    ((MyApplicationClass)getApplication()).addActivityToRunningActivityies
    (this.getClass());
    }
    
    @Override
    protected void onDestroy() {
    super.onDestroy();
    
    ((MyApplicationClass)getApplication()).removeActivityFromRunningActivities
    (this.getClass());
    }
  3. 最後に、アクティビティがバックスタックにあるかどうかを確認する場合は、この関数isActivityInBackStackを呼び出します。

例:HomeActivityがバックスタックにあるかどうかを確認したい:

if (((MyApplicationClass) 
getApplication()).isActivityInBackStack(HomeActivity.class)) {
       // Activity is in the back stack
    } else {
       // Activity is not in the back stack
    }


-1

これは、フォアグラウンドで同じアクティビティがない場合に機能します。通知から開いて動作しない場合、いくつかの調整を行い、これが付属しています。

public static boolean ativo = false;
public static int counter = 0;

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

@Override
protected void onStart() {
    super.onStart();
    ativo = true;
}

@Override
protected void onStop() {
    super.onStop();
    if (counter==1) ativo = false;
}

@Override
protected void onDestroy() {
    counter--;
    super.onDestroy();
}

これは、複数のアクティビティを同時に開いている場合に役立ちます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.