Android: làm cách nào để kiểm tra xem hoạt động có đang chạy không?


152

Có cách nào đơn giản để xác định xem một hoạt động nhất định có hoạt động hay không? Tôi muốn làm một số việc tùy thuộc vào hoạt động nào đang hoạt động. ví dụ:

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

Để kiểm tra xem một Hoạt động có đang chạy hay không, bạn có thể xem câu trả lời sau: stackoverflow.com/a/39079627/4531507
Rahul Sharma

Câu trả lời:


227

Bạn có thể sử dụng một staticbiến trong hoạt động.

class MyActivity extends Activity {
     static boolean active = false;

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

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

Gotcha duy nhất là nếu bạn sử dụng nó trong hai hoạt động liên kết với nhau thì onStoplần đầu tiên đôi khi được gọi sau onStarttrong giây. Vì vậy, cả hai có thể là sự thật ngắn gọn.

Tùy thuộc vào những gì bạn đang cố gắng làm (cập nhật hoạt động hiện tại từ một dịch vụ?). Bạn chỉ có thể đăng ký một trình lắng nghe tĩnh trong dịch vụ trong onStartphương thức hoạt động của mình thì trình nghe chính xác sẽ có sẵn khi dịch vụ của bạn muốn cập nhật giao diện người dùng.


5
Một số người đã chỉ ra điều này cho tôi rằng..Sharedpreference nên được ưu tiên hơn một biến tĩnh do các vấn đề rò rỉ bộ nhớ.
Ayush G lòng

13
Điều gì nếu có các hoạt động khác nhau của cùng một lớp chạy? Điều gì nếu bạn mở rộng MyActivityvới MyChildactivityvà muốn kiểm tra xem đứa trẻ đang hoạt động?
Smith

2
Tùy thuộc vào định nghĩa của bạn về "chạy", bạn có thể muốn thay đổi trạng thái của biến trong onResume và onPause ....
G. Blake Meike

5
Giải pháp này không phải là một giải pháp tốt cả. Giả sử Hoạt động của bạn gọi một Đoạn, ví dụ, đoạn đó sẽ kết thúc Hoạt động nhưng Hoạt động sẽ không gọi onPause và nếu bạn đóng đoạn trênStop, onStart hoặc bất kỳ phương thức vòng đời nào khác cũng sẽ không được gọi. Giải pháp tốt nhất là kiểm tra trong lớp Ứng dụng của bạn khả năng hiển thị như được mô tả ở đây: stackoverflow.com/questions/18038399/ Lời
portfoliobuilder

6
Nếu bạn đề xuất số liệu thống kê, bạn nhận được -1 từ tôi
Matei Suica

52

Tôi nhận ra vấn đề này khá cũ, nhưng tôi nghĩ vẫn đáng để chia sẻ giải pháp của mình vì nó có thể hữu ích cho người khác.

Giải pháp này không khả dụng trước khi Cấu trúc kiến ​​trúc Android được phát hành.

Hoạt động ít nhất là một phần có thể nhìn thấy

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

Hoạt động ở phía trước

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

3
getLifecycle (). getCienState (). isAtLeast (Vòng
đời.State.RESUMED

43

Tôi nghĩ rõ ràng hơn như thế:

  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
Tôi cố gắng tránh tạo các biến tạm thời trước vòng lặp 'for'; cho (tác vụ RunningTaskInfo: ActivityManager.getRastyT task (Integer.MAX_VALUE)) {...
mikebabcock

Làm thế nào tôi có thể gọi chức năng này?
Behzad

1
như thường lệ, là một methode mà bạn có thể gọi bên trong lớp của mình là một 'hàm', bạn có cần một ví dụ không?
Xenione

10
Từ developer.android.com/reference/android/app/ cường "Điều này không bao giờ được sử dụng cho logic cốt lõi trong một ứng dụng, chẳng hạn như quyết định giữa các hành vi khác nhau dựa trên thông tin tìm thấy ở đây. trong tương lai."
joe_deniable

15
Kể từ API cấp 21 (Android 5.0 Lollipop), phương pháp này đã không được chấp nhận.
AxeEffect

30

Một tùy chọn mà không sử dụng bất kỳ biến phụ thuộc nào là:

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

trong đó hoạt động là fe: this hoặc getActivity ().

Giá trị được trả về bởi biểu thức này thay đổi trong onStart () / onStop (), là các sự kiện bắt đầu / dừng hiển thị bố cục của hoạt động trên điện thoại.


16
Tại sao không sử dụng jsut Activity#getWindow().getDecorView().isShown()?
Gianluca P.

24

Tôi đã sử dụng phương pháp MyActivity. Class và getCanonicalName và tôi đã có câu trả lời.

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
Như đã đề cập trước đây, có thể không nên sử dụng getRunningTasks()vì nó không được dùng nữa: androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/iêu
Vitalii Dmitriev

21

Cách tốt hơn nhiều so với sử dụng biến tĩnh và theo OOP

Shared Preferencescó thể được sử dụng để chia sẻ các biến với nhau activitiesvà các dịch vụ từ mộtapplication

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

    }
}

Sử dụng sở thích chung. Nó có thông tin trạng thái đáng tin cậy nhất, ít sự cố chuyển đổi / hủy ứng dụng hơn, giúp chúng tôi yêu cầu một quyền khác và nó cho phép chúng tôi kiểm soát nhiều hơn để quyết định khi nào hoạt động của chúng tôi thực sự là trên cùng. xem chi tiết ở đây abd ở đây cũng


Cảm ơn. Nhưng onResume cũng cần bro?

1
Nó phụ thuộc vào những gì bạn hiểu bằng hoạt động. Theo mã của tôi, Activity nằm trong stack rồi nó hoạt động. Và nếu bạn muốn xử lý có thể nhìn thấy hay không thì bạn có thể sử dụng onResume
Zar E Ahmer

19
Điều này bị phá vỡ khi hoạt động bị giết mà không gọionStop()
Marcel Bro

3
Điều gì xảy ra nếu ứng dụng gặp sự cố?
ucMedia

1
Đây là một "giải pháp" rất nguy hiểm.
Firzen

9

Đây là mã để kiểm tra xem một dịch vụ cụ thể có đang chạy hay không. Tôi khá chắc chắn rằng nó có thể hoạt động cho một hoạt động miễn là bạn thay đổi getRastyService bằng getRastyAppProcesses () hoặc getRastyT task (). Hãy xem tại đây http://developer.android.com/reference/android/app/ActivityManager.html#getRastyAppProcesses ()

Thay đổi hằng số.PACKAGE và hằng số.BACKGROUND_SERVICE_CLASS tương ứng

    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
Nhưng hãy nhớ rằng liên kết bạn cung cấp cho biết "phương pháp này chỉ dành cho gỡ lỗi hoặc xây dựng giao diện người dùng quản lý quy trình hướng tới người dùng."
joe_deniable

getRastyT Nhiệm vụ hiện không được chấp nhận.
Adi

5

Có một cách dễ dàng hơn nhiều so với mọi thứ ở trên và cách tiếp cận này không yêu cầu sử dụng android.permission.GET_TASKStrong bảng kê khai, hoặc có vấn đề về điều kiện chủng tộc hoặc rò rỉ bộ nhớ được chỉ ra trong câu trả lời được chấp nhận.

  1. Tạo một biến STATIC trong Hoạt động chính. Tĩnh cho phép các hoạt động khác nhận dữ liệu từ hoạt động khác. onPause()đặt biến này sai , onResumeonCreate()thiết lập biến này đúng .

    private static boolean mainActivityIsOpen;
  2. Chỉ định getters và setters của biến này.

    public static boolean mainActivityIsOpen() {
        return mainActivityIsOpen;
    }
    
    public static void mainActivityIsOpen(boolean mainActivityIsOpen) {
        DayView.mainActivityIsOpen = mainActivityIsOpen;
    }
  3. Và sau đó từ một hoạt động hoặc Dịch vụ khác

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

3
Bạn đang nói rằng sử dụng các phương thức accessor tốt hơn là sử dụng các biến tĩnh công khai thô?
IgorGanapolsky

1
Trong Java, tốt hơn là sử dụng setters và getters để giữ các biến của bạn ở chế độ riêng tư. Tuy nhiên, tôi tin rằng trong Android, người ta thường truy cập trực tiếp vào các biến công khai ...
Stephen

11
Thật vô nghĩa khi có một setter công khai vì trạng thái hoạt động chỉ nên được xử lý bởi chính hoạt động đó. Bạn nên gắn bó với các quy ước đặt tên java: isActivityOpen sẽ là một phương thức getter chính xác. Cũng sử dụng if boolean == true là dự phòng. Bên cạnh đó, ủy thác quản lý nhà nước cho hoạt động là cách tiếp cận tốt nhất.
Lisandro

8
đây là lý do tại sao bạn nên tham gia các khóa học của bạn một cách siêng năng hơn @coolcool;)
Jerec TheSith

1
Và nếu bạn có nhiều phiên bản của hoạt động đang chạy thì sao?
nickmartens1980

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

Từ các tài liệu chính thức:

Hoạt động # isFinishing ()

Kiểm tra xem liệu hoạt động này đang trong quá trình hoàn thiện, bởi vì bạn đã gọi kết thúc () trên đó hoặc người khác đã yêu cầu rằng nó đã kết thúc. Điều này thường được sử dụng trong onPause () để xác định xem hoạt động chỉ đơn giản là tạm dừng hoặc hoàn thành hoàn toàn.

Hoạt động # isDestroyed ()

Trả về true nếu lệnh gọi onDestroy () cuối cùng đã được thực hiện trên Activity, vì vậy trường hợp này đã chết.


4

cảm ơn kkudi! Tôi đã có thể điều chỉnh câu trả lời của bạn để hoạt động cho một hoạt động ... đây là những gì hoạt động trong ứng dụng của tôi ..

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; 
} 

ví dụ này sẽ cung cấp cho bạn đúng hoặc sai nếu topActivity khớp với những gì người dùng đang làm. Vì vậy, nếu hoạt động mà việc kiểm tra của bạn không được hiển thị (tức là onPause) thì bạn sẽ không nhận được kết quả khớp. Ngoài ra, để làm điều này, bạn cần thêm quyền vào bảng kê khai của bạn ..

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

Tôi hy vọng nó sẽ có ích!


1
Quyền sử dụng này không được chấp nhận ở cấp độ API 21. developer.android.com/reference/android/
Guy West

2
Downvote annswer becuase để truy cập hoạt động hàng đầu (dịch vụ [i] .topActivity) chúng tôi min API cấp Q .Bowow không hoạt động.
Debasish Ghosh

4

Tôi nghĩ rằng câu trả lời được chấp nhận là một cách xử lý khủng khiếp này.

Tôi không biết trường hợp sử dụng là gì, nhưng vui lòng xem xét một phương thức được bảo vệ trong lớp cơ sở

@protected
void doSomething() {
}

và ghi đè nó trong lớp dẫn xuất.

Khi sự kiện xảy ra, chỉ cần gọi phương thức này trong lớp cơ sở. Lớp 'hoạt động' chính xác sẽ xử lý nó sau đó. Các lớp sau đó có thể kiểm tra nếu nó không Paused().

Tốt hơn hết, hãy sử dụng một xe buýt sự kiện như GreenRobot's , Square's , nhưng cái đó không được dùng nữa và đề nghị sử dụng RxJava


2

Tôi đã sử dụng một kiểm tra if (!a.isFinishing())và nó dường như làm những gì tôi cần. alà ví dụ hoạt động. Điều này có sai không? Tại sao không ai thử cái này?


2

Thế còn activity.isFinishing()


Đó không phải là một giải pháp tốt gây ra isFinishing cho biết nếu có hoạt động trong quá trình giết chóc.
VelocityPulse

2

ActivityLifecyclCallbacks là một cách tuyệt vời để theo dõi tất cả các hoạt động trong Ứng dụng:

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;
}

Mở rộng lớp Ứng dụng và cung cấp tài liệu tham khảo trong tệp Bản kê khai 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 bất cứ nơi nào từ Hoạt động cho trạng thái của hoạt động khác:

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.ActivityLifecyclCallbacks.html


1

Không chắc chắn đó là một cách "thích hợp" để "làm mọi việc".
Nếu không có cách API nào để giải quyết câu hỏi (hoặc a) hơn bạn nghĩ một chút, có thể bạn đang làm gì đó sai và đọc nhiều tài liệu hơn, v.v.
(Theo tôi hiểu các biến tĩnh là một cách thường sai trong Android. nó có thể hoạt động, nhưng chắc chắn sẽ có trường hợp khi nó không hoạt động [ví dụ, trong sản xuất, trên hàng triệu thiết bị]).
Chính xác trong trường hợp của bạn, tôi đề nghị suy nghĩ tại sao bạn cần biết nếu một hoạt động khác còn sống? .. bạn có thể bắt đầu một hoạt động khác để có kết quả để có được chức năng của nó. Hoặc bạn có thể lấy được lớp để có được chức năng của nó và cứ thế.
Trân trọng.


1

Nếu bạn quan tâm đến trạng thái vòng đời của trường hợp cụ thể của hoạt động, giải pháp của siliconeagle có vẻ đúng ngoại trừ biến "hoạt động" mới phải là biến đối tượng, thay vì tĩnh.


1

Sử dụng một phát sóng theo thứ tự. Xem http://android-developers.blogspot.nl/2011/01/ Processing -ordered-broadcasts.html

Trong hoạt động của bạn, hãy đăng ký một người nhận trong onStart, hủy đăng ký trong onStop. Bây giờ, ví dụ, khi một dịch vụ cần xử lý một cái gì đó mà hoạt động có thể có thể làm tốt hơn, hãy gửi một phát sóng theo thứ tự từ dịch vụ (với một trình xử lý mặc định trong chính dịch vụ). Bây giờ bạn có thể trả lời trong hoạt động khi nó đang chạy. Dịch vụ có thể kiểm tra dữ liệu kết quả để xem truyền phát đã được xử lý chưa và nếu không có hành động thích hợp.


1

Ngoài câu trả lời được chấp nhận , nếu bạn có nhiều phiên bản của hoạt động, bạn có thể sử dụng bộ đếm thay thế:

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--;
      }
}

thiếu "s" và "; (dấu hai chấm)" trong dòng trả về.
Ali_dev

1

Bạn đã thử chưa ..

    if (getActivity() instanceof NameOfYourActivity){
        //Do something
    }

0

Tìm thấy một cách giải quyết dễ dàng với mã sau đây

@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

Sử dụng biến isActivity để kiểm tra xem hoạt động có còn sống hay không.

private boolean activityState = true;

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

Sau đó kiểm tra

if(activityState){
//add your code
}

0

Nếu bạn muốn kiểm tra xem hoạt động có ở ngăn sau không, chỉ cần làm theo các bước tiếp theo. 1. Khai báo một ArrayList trong lớp Ứng dụng của bạn [Lớp ứng dụng được xác định trong tệp chính của bạn trong thẻ ứng dụng]

private ArrayList<Class> runningActivities = new ArrayList<>();
  1. Và thêm các phương thức công khai sau đây để truy cập và sửa đổi danh sách này.

    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. Trong BaseActivity của bạn, nơi tất cả các hoạt động mở rộng nó, ghi đè các phương thức onCreate và onDestroy để bạn có thể thêm và xóa các hoạt động khỏi ngăn xếp trở lại như sau.

    @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. Cuối cùng, nếu bạn muốn kiểm tra xem hoạt động có nằm trong ngăn xếp phía sau hay không, chỉ cần gọi hàm này làActivityInBackStack.

Ví dụ: Tôi muốn kiểm tra xem HomeActivityis trong ngăn xếp phía sau hay không:

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

0
public static boolean isActivityActive(Activity activity) {
    return !activity.isFinishing() &&
            (SDK_INT < JELLY_BEAN_MR1 || !activity.isDestroyed());
}

-1

Công việc này nếu bạn không có hoạt động tương tự ở phía trước. Nếu bạn mở từ thông báo không hoạt động, tôi đã thực hiện một số điều chỉnh và đi kèm với điều này:

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

Điều đó làm việc cho tôi với một số hoạt động mở cùng một lúc.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.