Làm cách nào để biết ứng dụng Android có đang chạy ở nền trước hay không?


83

Tôi đang thực hiện một thông báo trên thanh trạng thái trong ứng dụng Android được kích hoạt bởi c2dm. Tôi không muốn hiển thị thông báo nếu ứng dụng đang chạy. Làm cách nào để xác định xem ứng dụng có đang chạy hay không và đang ở nền trước?



Đó là một câu hỏi tương tự ... mặc dù tôi đã thử gắn cờ onStart / onStop và nó không hoạt động. Tôi vẫn không hiểu sự khác biệt giữa dừng / bắt đầu và tạm dừng / tiếp tục.
Andrew Thomas,

1
Bạn nên sử dụng giải pháp này: stackoverflow.com/questions/3667022/…
Informatic0re

Kể từ API 16 có một cách đơn giản bằng ActivityManager.getMyMemoryState
Juozas Kontvainis

Vì thư viện hỗ trợ phiên bản 26, bạn chỉ cần truy vấn ProcessLifecycleOwner bất cứ khi nào bạn muốn. Kiểm tra stackoverflow.com/a/52678290/6600000
Keivan Esbati

Câu trả lời:


55

Tạo một biến toàn cục như private boolean mIsInForegroundMode;và gán một falsegiá trị trong onPause()và một truegiá trị trong onResume().

Mã mẫu:

private boolean mIsInForegroundMode;

@Override
protected void onPause() {
    super.onPause();
    mIsInForegroundMode = false;
}

@Override
protected void onResume() {
    super.onResume();
    mIsInForegroundMode = true;
}

// Some function.
public boolean isInForeground() {
    return mIsInForegroundMode;
}

2
@MurVotema: Đúng vậy. Nhưng chúng tôi có thể tự do chuyển biến này xung quanh, ví dụ như tùy chọn hoặc cơ sở dữ liệu bất cứ khi nào thay đổi diễn ra.
Wroclai

19
@Shelly Nhưng biến của bạn sẽ chuyển thành True / False / True rất nhiều khi chuyển đổi qua các hoạt động trong cùng một ứng dụng. Điều này có nghĩa là bạn phải có độ trễ để thực sự phát hiện khi ứng dụng của bạn mất nền trước.
Radu

10
Đây không phải là giải pháp tốt nhất. Kiểm tra giải pháp @Gadenkan bên dưới.
Felipe Lima,

Nó hoạt động cho các tình huống đơn giản, nhưng nếu bạn có onActivityResult () trên hoạt động của mình, mọi thứ sẽ trở nên phức tạp. Tôi muốn chạy một dịch vụ nền nếu và chỉ khi tất cả các hoạt động của ứng dụng của tôi đều ở chế độ nền và giải pháp này ở trên không thành công.
Josh

1
@Tima Nếu bạn muốn cung cấp nó cho tất cả các hoạt động, bạn có thể tạo một MyOwnActivity mới mở rộng AppCompatActivity ... Sau đó, bên trong MyOwnActivity, ghi đè cả onResume () / onPause () và cuối cùng bạn mở rộng tất cả các hoạt động ứng dụng của mình từ MyOwnActivity thay vì AppCompatActivity. Vấn đề đã được giải quyết. ; )
elliotching

112

Ngoài ra, bạn có thể kiểm tra các ActivityManagertác vụ đang chạy bằng getRunningTasksphương pháp nào. Sau đó, kiểm tra nhiệm vụ đầu tiên (nhiệm vụ ở phía trước) trong Danh sách nhiệm vụ được trả về, nếu đó là nhiệm vụ của bạn.
Đây là ví dụ mã:

public Notification buildNotification(String arg0, Map<String, String> arg1) {

    ActivityManager activityManager = (ActivityManager) appContext.getSystemService(Context.ACTIVITY_SERVICE);
    List<RunningTaskInfo> services = activityManager
            .getRunningTasks(Integer.MAX_VALUE);
    boolean isActivityFound = false;

    if (services.get(0).topActivity.getPackageName().toString()
            .equalsIgnoreCase(appContext.getPackageName().toString())) {
        isActivityFound = true;
    }

    if (isActivityFound) {
        return null;
    } else {
        // write your code to build a notification.
        // return the notification you built here
    }

}

Và đừng quên thêm GET_TASKSquyền vào tệp manifest.xml để có thể chạy getRunningTasks()phương thức trong đoạn mã trên:

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

p / s: Nếu đồng ý theo cách này, xin lưu ý rằng quyền này hiện không được chấp nhận.


24
Nếu bạn muốn sử dụng mã này không quên để thêm <dụng-phép android: name = "android.permission.GET_TASKS" />
Lakshmanan

13
Nitpicks: Gọi toString()trên một Chuỗi được trả về getPackageName()là dư thừa. Ngoài ra, vì chúng tôi chỉ quan tâm đến nhiệm vụ đầu tiên được trả lại getRunningTasks(), chúng tôi có thể vượt qua 1thay vì Integer.MAX_VALUE.
Jonik

14
Lưu ý: phương pháp này chỉ nhằm gỡ lỗi và trình bày giao diện người dùng quản lý tác vụ. Đ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. Việc sử dụng như vậy không được hỗ trợ và có thể sẽ bị hỏng trong tương lai. Ví dụ: nếu nhiều ứng dụng có thể tích cực chạy cùng một lúc, các giả định được đưa ra về ý nghĩa của dữ liệu ở đây cho mục đích của luồng điều khiển sẽ không chính xác.
Informatic0re

5
Rất tiếc, getRunningTasks () đã không được dùng nữa kể từ Android L (API 20). Kể từ L, phương pháp này không còn khả dụng cho các ứng dụng của bên thứ ba nữa: việc giới thiệu các tài liệu gần đây có nghĩa là nó có thể làm rò rỉ thông tin người cho người gọi. Đối với khả năng tương thích ngược, nó vẫn sẽ trả về một tập hợp con nhỏ dữ liệu của nó: ít nhất là các tác vụ của riêng người gọi và có thể là một số tác vụ khác như home được biết là không nhạy cảm.
Sam Lu

2
Có lẽ nếu nó chỉ hiển thị các nhiệm vụ của người gọi, thì tác vụ đầu tiên và hoạt động hàng đầu sẽ luôn là của bạn, có nghĩa là điều này sẽ luôn trả về true post-lollipop.
Mike Holler

46

Đây là một bài khá cũ nhưng vẫn còn khá phù hợp. Giải pháp được chấp nhận ở trên có thể hoạt động nhưng sai.Như Dianne Hackborn đã viết:

Các API này không ở đó để các ứng dụng dựa trên luồng giao diện người dùng của chúng, mà để thực hiện những việc như hiển thị cho người dùng các ứng dụng đang chạy hoặc trình quản lý tác vụ, v.v.

Vâng, có một danh sách được lưu trong bộ nhớ cho những điều này. Tuy nhiên, nó bị tắt trong một quy trình khác, được quản lý bởi các chuỗi chạy riêng biệt với của bạn và không phải là điều bạn có thể tin tưởng (a) nhìn thấy kịp thời để đưa ra quyết định chính xác hoặc (b) có một bức tranh nhất quán vào thời điểm bạn quay lại. Thêm vào đó, quyết định về hoạt động "tiếp theo" sẽ luôn được thực hiện tại thời điểm chuyển đổi sẽ xảy ra và phải đến thời điểm chính xác đó (nơi trạng thái hoạt động được khóa lại trong thời gian ngắn để thực hiện chuyển đổi), chúng tôi thực sự biết điều tiếp theo sẽ là gì.

Và việc thực hiện và hành vi toàn cầu ở đây không được đảm bảo sẽ giữ nguyên trong tương lai.

Giải pháp chính xác là thực hiện: ActivityLifeCycleCallbacks .

Về cơ bản, điều này cần một Lớp ứng dụng và trình xử lý có thể được đặt trong đó để xác định trạng thái hoạt động của bạn trong ứng dụng.


7
Đây là một ví dụ về cách sử dụng nó baroqueworksdev.blogspot.com/2012/12/…
JK

2
Tôi nghĩ đây là giải pháp tốt nhất và có lẽ sẽ không bị phá vỡ trong tương lai. Tự hỏi tại sao nó không nhận được đủ phiếu bầu.
Rohan Kandwal

2
Nếu bạn viết một mã ví dụ, bạn sẽ nhận được nhiều phiếu bầu vì một số người bỏ qua các câu trả lời mà không cần ví dụ ... nhưng đó là giải pháp tốt nhất ...
Saman Salehi

điều này khác với phương pháp ghi đè onPauseonResumephương pháp được sử dụng trong câu trả lời được chấp nhận như thế nào?
Saitama

24

Như Vinay nói, có lẽ giải pháp tốt nhất (để hỗ trợ các phiên bản android mới hơn, 14+) là sử dụng ActivityLifecycleCallbackstrong việc Applicationtriển khai lớp.

package com.telcel.contenedor.appdelegate;

import android.app.Activity;
import android.app.Application.ActivityLifecycleCallbacks;
import android.os.Bundle;

/** Determines global app lifecycle states. 
 * 
 * The following is the reference of activities states:
 * 
 * The <b>visible</b> lifetime of an activity happens between a call to onStart()
 * until a corresponding call to onStop(). During this time the user can see the
 * activity on-screen, though it may not be in the foreground and interacting with 
 * the user. The onStart() and onStop() methods can be called multiple times, as 
 * the activity becomes visible and hidden to the user.
 * 
 * The <b>foreground</b> lifetime of an activity happens between a call to onResume()
 * until a corresponding call to onPause(). During this time the activity is in front
 * of all other activities and interacting with the user. An activity can frequently
 * go between the resumed and paused states -- for example when the device goes to
 * sleep, when an activity result is delivered, when a new intent is delivered -- 
 * so the code in these methods should be fairly lightweight. 
 * 
 * */
public class ApplicationLifecycleManager implements ActivityLifecycleCallbacks {

    /** Manages the state of opened vs closed activities, should be 0 or 1. 
     * It will be 2 if this value is checked between activity B onStart() and
     * activity A onStop().
     * It could be greater if the top activities are not fullscreen or have
     * transparent backgrounds.
     */
    private static int visibleActivityCount = 0;

    /** Manages the state of opened vs closed activities, should be 0 or 1
     * because only one can be in foreground at a time. It will be 2 if this 
     * value is checked between activity B onResume() and activity A onPause().
     */
    private static int foregroundActivityCount = 0;

    /** Returns true if app has foreground */
    public static boolean isAppInForeground(){
        return foregroundActivityCount > 0;
    }

    /** Returns true if any activity of app is visible (or device is sleep when
     * an activity was visible) */
    public static boolean isAppVisible(){
        return visibleActivityCount > 0;
    }

    public void onActivityCreated(Activity activity, Bundle bundle) {
    }

    public void onActivityDestroyed(Activity activity) {
    }

    public void onActivityResumed(Activity activity) {
        foregroundActivityCount ++;
    }

    public void onActivityPaused(Activity activity) {
        foregroundActivityCount --;
    }


    public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
    }

    public void onActivityStarted(Activity activity) {
        visibleActivityCount ++;
    }

    public void onActivityStopped(Activity activity) {
        visibleActivityCount --;
    }
}

Và trong onCreate()phương pháp Ứng dụng :

registerActivityLifecycleCallbacks(new ApplicationLifecycleManager());

Sau đó ApplicationLifecycleManager.isAppVisible()hoặc ApplicationLifecycleManager.isAppInForeground()sẽ được sử dụng để biết trạng thái mong muốn.


Nó sẽ chỉ hoạt động với isAppVosystem (). Nếu bạn đóng ứng dụng, gửi lên nền trước thì nó sẽ không có tác dụng
AlwaysConfused,

19

Kể từ API 16, bạn có thể làm như thế này:

static boolean shouldShowNotification(Context context) {
    RunningAppProcessInfo myProcess = new RunningAppProcessInfo();
    ActivityManager.getMyMemoryState(myProcess);
    if (myProcess.importance != RunningAppProcessInfo.IMPORTANCE_FOREGROUND)
        return true;

    KeyguardManager km = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
    // app is in foreground, but if screen is locked show notification anyway
    return km.inKeyguardRestrictedInputMode();
}

Giải pháp hiệu quả. Cảm ơn :)
Md. Sajedul Karim

Giải pháp rất hay. Không cần quyền.
user3144836

Tuyệt vời! Tôi đang sử dụng danh sách Nhiệm vụ nhưng nó yêu cầu TASK .. thực sự đánh giá cao điều này!
hexagod

15

FYI, nếu bạn sử dụng giải pháp Gadenkan (thật tuyệt vời !!), đừng quên thêm

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

vào tệp kê khai.


9
Trong android Lollipop, quyền này không được chấp nhận
Mussa

14

Một chút phiên bản làm sạch của giải pháp Gadenkan . Đặt nó bất kỳ Hoạt động nào, hoặc có thể là một lớp cơ sở cho tất cả các Hoạt động của bạn.

protected boolean isRunningInForeground() {
    ActivityManager manager = 
         (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
    List<ActivityManager.RunningTaskInfo> tasks = manager.getRunningTasks(1);
    if (tasks.isEmpty()) {
        return false;
    }
    String topActivityName = tasks.get(0).topActivity.getPackageName();
    return topActivityName.equalsIgnoreCase(getPackageName());
}

Để có thể gọi getRunningTasks(), bạn cần thêm điều này vào AndroidManifest.xml:

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

Hãy lưu ý những gì ActivityManager.getRunningTasks() Javadoc nói:

Lưu ý: phương pháp này chỉ nhằm gỡ lỗi và trình bày giao diện người dùng quản lý tác vụ. Đ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. Việc sử dụng như vậy không được hỗ trợ và có thể sẽ bị hỏng trong tương lai.

Cập nhật (tháng 2 năm 2015)

Lưu ý rằng tính năng getRunningTasks()này không được dùng nữa trong API cấp 21 !

Kể từ khi LOLLIPOP, phương pháp này không còn khả dụng cho các ứng dụng của bên thứ ba: việc giới thiệu các nội dung gần đây tập trung vào tài liệu có nghĩa là nó có thể làm rò rỉ thông tin người cho người gọi. Đối với khả năng tương thích ngược, nó vẫn sẽ trả về một tập hợp con nhỏ dữ liệu của nó: ít nhất là các tác vụ của riêng người gọi và có thể là một số tác vụ khác như home được biết là không nhạy cảm.

Vì vậy, những gì tôi đã viết trước đó thậm chí còn phù hợp hơn:

Trong nhiều trường hợp, bạn có thể đưa ra một giải pháp tốt hơn. Ví dụ: làm điều gì đó trong onPause()onResume()có thể là trong BaseActivity cho tất cả các Hoạt động của bạn.

(Trong trường hợp của chúng tôi, chúng tôi không muốn một hoạt động cảnh báo ngoại tuyến được khởi chạy nếu chúng tôi không ở trong nền trước, vì vậy trong BaseActivity, onPause()chúng tôi chỉ cần hủy đăng ký nhận RxJava Subscriptionnghe tín hiệu "đã ngoại tuyến".)


bạn có thể vui lòng đăng mã RxJava mà bạn đã sử dụng không? Tôi muốn sử dụng RxJava và tôi không muốn dành nhiều thời gian cho việc học RxJava vào lúc này :(
MBH

@MBH: Sử dụng RxJava có lẽ sẽ không hiệu quả nếu không dành thời gian làm quen với các khái niệm cơ bản ... :-) Trong mọi trường hợp, đây là một ví dụ nhỏ .
Jonik

9

Theo dõi câu trả lời của Gadenkan, tôi cần một cái gì đó như thế này để tôi có thể biết liệu ứng dụng của mình không chạy ở nền trước hay không, nhưng tôi cần một cái gì đó rộng rãi ứng dụng và không yêu cầu tôi phải cài đặt / gỡ bỏ cờ trong ứng dụng của mình.

Mã của Gadenkan khá ấn tượng nhưng nó không theo phong cách riêng của tôi và tôi cảm thấy nó có thể gọn gàng hơn, vì vậy trong ứng dụng của tôi, nó được cô đọng lại thành phần này.

if (!context.getPackageName().equalsIgnoreCase(((ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE)).getRunningTasks(1).get(0).topActivity.getPackageName()))
{
// App is not in the foreground
}

(Lưu ý bên: Bạn chỉ có thể bỏ dấu! Nếu bạn muốn séc hoạt động theo cách khác)

Mặc dù với cách tiếp cận này bạn cần sự GET_TASKScho phép.


3

Bắt đầu thư viện hỗ trợ phiên bản 26, bạn có thể sử dụng ProcessLifecycleOwner để xác định trạng thái hiện tại của ứng dụng, chỉ cần thêm nó vào các phần phụ thuộc của bạn như được mô tả ở đây , ví dụ:

dependencies {
    def lifecycle_version = "1.1.1"

    // ViewModel and LiveData
    implementation "android.arch.lifecycle:extensions:$lifecycle_version"
    // alternatively - Lifecycles only (no ViewModel or LiveData).
    //     Support library depends on this lightweight import
    implementation "android.arch.lifecycle:runtime:$lifecycle_version"
    annotationProcessor "android.arch.lifecycle:compiler:$lifecycle_version" // use kapt for Kotlin
}

, Bây giờ bạn có thể truy vấn ProcessLifecycleOwnerbất cứ khi nào bạn muốn kiểm tra trạng thái ứng dụng, chẳng hạn như để kiểm tra xem ứng dụng có đang chạy ở nền trước hay không, bạn chỉ cần thực hiện điều này:

 boolean isAppInForeground = ProcessLifecycleOwner.get().getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED);
 if(!isAppInForeground)
    //Show Notification in status bar

1
Đây là câu trả lời đúng. Rất nhiều cái khác nên được coi là không được dùng nữa
giờ 00

Đối với AndroidX, sử dụng Java implementation 'androidx.lifecycle:lifecycle-process:2.2.0'trong gradle dự án của bạn.
Jonathan

1

Dựa trên các câu trả lời và nhận xét khác nhau, đây là một phiên bản nội tuyến hơn mà bạn có thể thêm vào lớp trợ giúp:

public static boolean isAppInForeground(Context context) {
  List<RunningTaskInfo> task =
      ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE))
          .getRunningTasks(1);
  if (task.isEmpty()) {
    return false;
  }
  return task
      .get(0)
      .topActivity
      .getPackageName()
      .equalsIgnoreCase(context.getPackageName());
}

Như đã đề cập trong các câu trả lời khác, bạn cần thêm quyền sau vào của bạn AndroidManifest.xml.

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

Trong android Lollipop, quyền này không được dùng nữa
Mussa

1

Tôi muốn nói thêm rằng một cách an toàn hơn để làm điều này - ngoài việc kiểm tra xem ứng dụng của bạn có ở chế độ nền hay không trước khi tạo thông báo - là chỉ cần tắt và bật Bộ thu phát sóng lần lượt onPause () và onResume ().

Phương pháp này cho phép bạn kiểm soát nhiều hơn trong logic ứng dụng thực tế và không có khả năng thay đổi trong tương lai.

@Override
protected void onPause() {
    unregisterReceiver(mHandleMessageReceiver);
    super.onPause();
}

@Override
protected void onResume() {
    super.onResume();
    registerReceiver(mHandleMessageReceiver, new IntentFilter(DISPLAY_MESSAGE_ACTION));
}

1

Tôi đã tìm thấy một cách đơn giản và chính xác hơn để kiểm tra xem ứng dụng đang ở chế độ nền hay nền bằng cách ánh xạ các hoạt động tới boolean.

Kiểm tra ý chính đầy đủ tại đây


1

Đây là mã cho giải pháp đơn giản tuyệt vời được mô tả ở trên bởi @ user2690455. Mặc dù có vẻ hơi dài dòng nhưng bạn sẽ thấy nó thực sự khá nhẹ

Trong trường hợp của tôi, chúng tôi cũng sử dụng AppCompatActivity, vì vậy tôi phải có 2 lớp cơ sở.

public class BaseActivity extends Activity {

    /**
     * Let field be set only in base class
     * All callers must use accessors,
     * and then it's not up to them to manage state.
     *
     * Making it static since ..
     * 1. It needs to be used across two base classes
     * 2. It's a singleton state in the app
     */
    private static boolean IS_APP_IN_BACKGROUND = false;

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

        BaseActivity.onResumeAppTracking(this);

        BaseActivity.setAppInBackgroundFalse();
    }

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

        BaseActivity.setAppInBackgroundTrue();
    }

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

        BaseActivity.setAppInBackgroundFalse();
    }

    protected static void onResumeAppTracking(Activity activity) {

        if (BaseActivity.isAppInBackground()) {

            // do requirements for returning app to foreground
        }

    }

    protected static void setAppInBackgroundFalse() {

        IS_APP_IN_BACKGROUND = false;
    }

    protected static void setAppInBackgroundTrue() {

        IS_APP_IN_BACKGROUND = true;
    }

    protected static boolean isAppInBackground() {

        return IS_APP_IN_BACKGROUND;
    }
}

1

Điều này chỉ hữu ích khi bạn muốn thực hiện một số hành động ngay khi hoạt động của bạn bắt đầu và nơi bạn muốn kiểm tra xem ứng dụng đang ở nền trước hay nền.

Thay vì sử dụng Trình quản lý hoạt động, có một thủ thuật đơn giản mà bạn có thể thực hiện thông qua mã. Nếu bạn quan sát kỹ chu trình hoạt động, dòng chảy giữa hai hoạt động và tiền cảnh đến hậu cảnh như sau. Giả sử A và B là hai hoạt động.

Khi chuyển từ A sang B: 1. onPause () của A được gọi là 2. onResume () của B được gọi là 3. onStop () của A được gọi khi B được tiếp tục hoàn toàn

Khi ứng dụng chuyển sang chế độ nền: 1. onPause () của A được gọi là 2. onStop () của A được gọi

Bạn có thể phát hiện sự kiện nền của mình bằng cách chỉ cần đặt một lá cờ trong hoạt động.

Thực hiện một hoạt động trừu tượng và mở rộng nó khỏi các hoạt động khác của bạn, để bạn không phải sao chép, dán mã cho tất cả các hoạt động khác ở bất cứ đâu bạn cần sự kiện nền.

Trong hoạt động trừu tượng, tạo cờ isAppInBackground.

Trong phương thức onCreate (): isAppInBackground = false;

Trong phương thức onPause (): isAppInBackground = false;

Trong phương thức onStop (): isAppInBackground = true;

Bạn chỉ cần kiểm tra onResume () của mình nếu isAppInBackground là true. n sau khi bạn kiểm tra cờ của mình rồi đặt lại isAppInBackground = false

Đối với quá trình chuyển đổi giữa hai hoạt động vì onSTop () của hoạt động đầu tiên sẽ luôn được gọi sau khi hoạt động thứ hai tiếp tục, cờ sẽ không bao giờ đúng và khi ứng dụng ở chế độ nền, hoạt động onStop () sẽ được gọi ngay sau onPause và do đó cờ sẽ đúng khi bạn mở ứng dụng sau này.

Có một kịch bản nữa mặc dù trong cách tiếp cận này. Nếu bất kỳ màn hình ứng dụng nào của bạn đã mở và bạn để thiết bị di động không hoạt động thì sau một thời gian, thiết bị di động sẽ chuyển sang chế độ ngủ và khi bạn mở khóa thiết bị di động, nó sẽ được xử lý ở sự kiện nền.


1

Đây là một phương pháp mà tôi sử dụng (và phương pháp hỗ trợ):

private boolean checkIfAppIsRunningInForeground() {
    ActivityManager activityManager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
    for(ActivityManager.RunningAppProcessInfo appProcessInfo : activityManager.getRunningAppProcesses()) {
        if(appProcessInfo.processName.contains(this.getPackageName())) {
            return checkIfAppIsRunningInForegroundByAppImportance(appProcessInfo.importance);
        }
    }
    return false;
}

private boolean checkIfAppIsRunningInForegroundByAppImportance(int appImportance) {
    switch (appImportance) {
        //user is aware of app
        case ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND:
        case ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE:
            return true;
        //user is not aware of app
        case ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND:
        case ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY:
        case ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE:
        case ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE:
        default:
            return false;
    }
}

có vẻ như tôi đã bỏ phiếu cho giải pháp đã được đăng hai năm trước. Phương pháp này không còn hoạt động sau các bản cập nhật bảo mật khác nhau trong Android.
Droid Chris

0

Không có lệnh gọi lại toàn cầu cho điều này, nhưng đối với mỗi hoạt động, nó là onStop (). Bạn không cần phải rắc rối với một int nguyên tử. Chỉ cần có một int toàn cục với số lượng các hoạt động đã bắt đầu, trong mỗi hoạt động, hãy tăng nó trong onStart () và giảm nó trong onStop ().

Theo dõi cái này


0
     public static boolean isAppRunning(Context context) {

 // check with the first task(task in the foreground)
 // in the returned list of tasks

   ActivityManager activityManager = (ActivityManager)
   context.getSystemService(Context.ACTIVITY_SERVICE);
 List<RunningTaskInfo> services =
 activityManager.getRunningTasks(Integer.MAX_VALUE);
     if
     (services.get(0).topActivity.getPackageName().toString().equalsIgnoreCase(context.getPackageName().toString()))
     {
     return true;
     }
     return false;
     }

getRunningTasks không còn là một tùy chọn nữa - mô hình bảo mật mới hơn khiến điều này hầu như vô dụng và nó không còn được dùng nữa.
Tony Maro

@AnaghHegde Xem câu trả lời ở trên của Gadenkan bằng cách kéo danh sách các hoạt động đang chạy từ hệ thống.
Tony Maro

0

Các cách tiếp cận trước đây được đề cập ở đây không phải là tối ưu. Cách tiếp cận dựa trên nhiệm vụ yêu cầu một sự cho phép có thể không được mong muốn và cách tiếp cận "Boolean" dễ gây ra sự cố sửa đổi đồng thời.

Cách tiếp cận mà tôi sử dụng và (tôi tin rằng) hoạt động khá tốt trong hầu hết các trường hợp:

Có một lớp "MainApplication" để theo dõi số lượng hoạt động trong AtomicInteger :

import android.app.Application;

import java.util.concurrent.atomic.AtomicInteger;

public class MainApplication extends Application {
    static class ActivityCounter {
        private static AtomicInteger ACTIVITY_COUNT = new AtomicInteger(0);

        public static boolean isAppActive() {
            return ACTIVITY_COUNT.get() > 0;
        }

        public static void activityStarted() {
            ACTIVITY_COUNT.incrementAndGet();
        }

        public static void activityStopped() {
            ACTIVITY_COUNT.decrementAndGet();
        }
    }
}

Và tạo một lớp Hoạt động cơ sở mà các hoạt động khác sẽ mở rộng:

import android.app.Activity;
import android.support.annotation.CallSuper;

public class TestActivity extends Activity {
    @Override
    @CallSuper
    protected void onStart() {
        MainApplication.ActivityCounter.activityStarted();
        super.onStart();
    }

    @Override
    @CallSuper
    protected void onStop() {
        MainApplication.ActivityCounter.activityStopped();
        super.onStop();
    }
}

Được rồi ... nhưng hãy cân nhắc sử dụng ACTIVITY_COUNT.decrementAndGet (); trong activityStopped ().
ChrisCarneiro
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.