Làm thế nào để kiểm tra xem hoạt động ở nền trước hay trong nền hiển thị?


104

Tôi có một màn hình giật gân trên bộ hẹn giờ. Vấn đề của tôi là trước khi thực hiện finish()hoạt động của mình, tôi cần kiểm tra xem hoạt động tiếp theo đã bắt đầu chưa vì một hộp thoại hệ thống bật lên và tôi chỉ muốn finish(); khi người dùng đã chọn một tùy chọn từ hộp thoại?

Tôi biết rằng có nhiều câu hỏi về cách xem hoạt động của bạn có ở phía trước hay không nhưng tôi không biết liệu điều này có cho phép các hộp thoại ở phía trên hoạt động hay không.

Đây là vấn đề, màu đỏ là hoạt động của tôi ở nền trong khi đối thoại ở phía trước:

màu đỏ là hoạt động của tôi ở phía sau trong khi cuộc đối thoại ở phía trước

CHỈNH SỬA: Tôi đã thử không sử dụng finish()nhưng sau đó hoạt động của tôi có thể quay trở lại trong chồng ứng dụng mà tôi đang cố gắng tránh.



Để làm rõ, bạn muốn khởi chạy trình chọn mục đích và đợi ứng dụng của bạn hoàn thành () cho đến khi người dùng nhấn vào một trong các lựa chọn? Có vẻ như bạn cần Intent.createChooser () và startActivityForResult () theo sau bởi finish () khi nhận được kết quả.
alanv


ProcessLifecycleOwner là giải pháp mới nhất
SR

Câu trả lời:


189

Đây là những gì được khuyến nghị là giải pháp phù hợp :

Giải pháp phù hợp (tín dụng đến Dan, CommonsWare và NeTeInStEiN) Tự theo dõi khả năng hiển thị ứng dụng của bạn bằng cách sử dụng các phương thức Activity.onPause, Activity.onResume. Lưu trữ trạng thái "khả năng hiển thị" trong một số lớp khác. Lựa chọn tốt là việc triển khai Ứng dụng hoặc Dịch vụ của chính bạn (cũng có một vài biến thể của giải pháp này nếu bạn muốn kiểm tra khả năng hiển thị hoạt động từ dịch vụ).

Ví dụ Triển khai lớp Ứng dụng tùy chỉnh (lưu ý phương thức tĩnh isActivityVible ()):

public class MyApplication extends Application {

  public static boolean isActivityVisible() {
    return activityVisible;
  }  

  public static void activityResumed() {
    activityVisible = true;
  }

  public static void activityPaused() {
    activityVisible = false;
  }

  private static boolean activityVisible;
}

Đăng ký lớp ứng dụng của bạn trong AndroidManifest.xml:

<application
    android:name="your.app.package.MyApplication"
    android:icon="@drawable/icon"
    android:label="@string/app_name" >

Thêm onPause và onResume vào mọi Hoạt động trong dự án (bạn có thể tạo tổ tiên chung cho các Hoạt động của mình nếu bạn muốn, nhưng nếu hoạt động của bạn đã được mở rộng từ MapActivity / ListActivity, v.v. thì bạn vẫn cần phải viết tay như sau) :

@Override
protected void onResume() {
  super.onResume();
  MyApplication.activityResumed();
}

@Override
protected void onPause() {
  super.onPause();
  MyApplication.activityPaused();
}

Trong của bạn finish() phương pháp , bạn muốn sử dụngisActivityVisible() để kiểm tra xem hoạt động có hiển thị hay không. Ở đó, bạn cũng có thể kiểm tra xem người dùng đã chọn một tùy chọn hay chưa. Tiếp tục khi cả hai điều kiện được đáp ứng.

Nguồn cũng đề cập đến hai giải pháp sai ... vì vậy hãy tránh làm điều đó.

Nguồn: stackoverflow


Có một khoảnh khắc nhỏ giữa kết thúc và bắt đầu hoạt động và tôi mỏng cần phải thêm một số chậm trễ và truy cập
sagus_helgy

28
Điều này không hoạt động đáng tin cậy. Bạn có thể gặp trường hợp sau: Tiếp tục A Tiếp tục B Tạm dừng A. Hiện hoạt động Có thể thay đổi là sai trong khi ứng dụng hiển thị. Có lẽ bạn sử dụng bộ đếm khả năng hiển thị: opensCounter ++ trong onResume và opensCounter - trong onPause.
Joris Weimar

4
Đồng ý với Joris Weimar rằng đây không phải là một giải pháp hoàn hảo. Một kịch bản là nếu người dùng kéo xuống bảng thông báo, sau đó không phải là onPause, onStop, cũng không phải là onResumesự kiện được gọi. Vậy bạn sẽ làm gì nếu không có sự kiện nào bị sa thải ?!

1
Trên thực tế, không có câu trả lời nào khác hoạt động 100%.

2
Nếu ứng dụng có nhiều Hoạt động, lược đồ này sẽ không hoạt động. Thay thế bằng bộ đếm ít nhất
ruX

70

Nếu nhắm mục tiêu API cấp 14 trở lên, người ta có thể sử dụng android.app.Application.ActivityLifecycleCallbacks

public class MyApplication extends Application implements ActivityLifecycleCallbacks {
    private static boolean isInterestingActivityVisible;

    @Override
    public void onCreate() {
        super.onCreate();

        // Register to be notified of activity state changes
        registerActivityLifecycleCallbacks(this);
        ....
    }

    public boolean isInterestingActivityVisible() {
        return isInterestingActivityVisible;
    }

    @Override
    public void onActivityResumed(Activity activity) {
        if (activity instanceof MyInterestingActivity) {
             isInterestingActivityVisible = true;
        }
    }

    @Override
    public void onActivityStopped(Activity activity) {
        if (activity instanceof MyInterestingActivity) {
             isInterestingActivityVisible = false;
        }
    }

    // Other state change callback stubs
    ....
}

18
Bạn chỉ có thể làm điều này trong các lệnh gọi lại vòng đời hoạt động thông thường (onResume (), onStop ()), tôi sẽ nói.
Daniel Wilson

5
@DanielWilson Tôi nghĩ vấn đề không phải là xây dựng một hệ thống để thực hiện điều gì đó mà một hệ thống đã tồn tại. IMHO đây phải là câu trả lời được chấp nhận.
Jeffrey Blattman

26

UPD : cập nhật lên trạng thái Lifecycle.State.RESUMED. Cảm ơn @htafoya vì điều đó.

Vào năm 2019 với sự trợ giúp của thư viện hỗ trợ mới 28+hoặc AndroidX, bạn có thể chỉ cần sử dụng:

val isActivityInForeground = activity.lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)

Bạn có thể đọc thêm trong tài liệu để hiểu điều gì đã xảy ra.


2
Không thực sự, có lẽ tốt hơn là đặt activity.lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED) hoặc BẮT ĐẦU. INITIALIZEDkhông đảm bảo rằng nó ở phía trước.
htafoya

11

Activity :: hasWindowFocus () trả về boolean bạn cần.

public class ActivityForegroundChecker extends TimerTask
{
    private static final long FOREGROUND_CHECK_PERIOD = 5000;
    private static final long FIRST_DELAY             = 3000;

    private Activity m_activity;
    private Timer    m_timer;

    public ActivityForegroundChecker (Activity p_activity)
    {
        m_activity = p_activity;
    }

    @Override
    public void run()
    {
        if (m_activity.hasWindowFocus() == true) {
            // Activity is on foreground
            return;
        }
        // Activity is on background.
    }

    public void start ()
    {
        if (m_timer != null) {
            return;
        }
        m_timer = new Timer();
        m_timer.schedule(this, FIRST_DELAY, FOREGROUND_CHECK_PERIOD);
    }

    public void stop ()
    {
        if (m_timer == null) {
            return;
        }
        m_timer.cancel();
        m_timer.purge();
        m_timer = null;
    }
}

Đây là một lớp mẫu để kiểm tra khả năng hiển thị của các hoạt động của bạn từ mọi nơi.

Hãy nhớ rằng nếu bạn hiển thị một hộp thoại , kết quả sẽ là false vì hộp thoại sẽ có tiêu điểm chính. Ngoài ra, nó thực sự tiện dụng và đáng tin cậy hơn các giải pháp được đề xuất.


1
Cảm ơn bạn đã sửa đổi câu trả lời @Burak Day, nó thực sự là một câu trả lời
Nick

Điều này không hoạt động, tôi muốn sử dụng một thuộc tính boolean trong lớp, được đặt thành true trong OnResume và đặt thành false trong OnPause ();
Chandler

@Chandler vấn đề chính xác mà bạn đang gặp phải với mã này là gì? Ngoài ra phiên bản nào?
Ngày Burak

@Chandler cũng vậy, điều gì sẽ xảy ra nếu bạn không có quyền truy cập vào các phương thức vòng đời hoạt động. Hãy xem xét bạn chỉ đang kiểm tra khả năng hiển thị của hoạt động từ thư viện.
Ngày Burak

Vấn đề thực sự của câu trả lời này là nó KHÔNG hoạt động, activity.hasWindowFocus là true không thể đảm bảo hoạt động nằm giữa trạng thái onResume và onPause. Tôi muốn khuyên bạn nên thêm thuộc tính bool isResumed vào hoạt động đó, đặt giá trị theo cách thủ công và thêm phương thức get.
Chandler

10

Đó chính xác là sự khác biệt giữa onPauseonStopcác sự kiện của hoạt động như được mô tả trong tài liệu lớp Hoạt động .

Nếu tôi hiểu đúng về bạn, điều bạn muốn làm là kêu gọi finish()từ hoạt động của bạn onStopđể chấm dứt nó. Xem hình ảnh đính kèm của Ứng dụng Demo Vòng đời Hoạt động . Đây là cách nó trông giống như khi Hoạt động B được khởi chạy từ Hoạt động A. Thứ tự của các sự kiện từ dưới lên trên nên bạn có thể thấy rằng Hoạt động A onStopđược gọi sau khi Hoạt động B onResumeđã được gọi.

Bản trình diễn vòng đời hoạt động

Trong trường hợp hộp thoại được hiển thị, hoạt động của bạn bị mờ trong nền và chỉ onPauseđược gọi.


7

Hai giải pháp khả thi:

1) Gọi lại vòng đời hoạt động

Sử dụng một Ứng dụng triển khai ActivityLifecycleCallbacks và sử dụng nó để theo dõi các sự kiện vòng đời Hoạt động trong ứng dụng của bạn. Lưu ý rằng ActivityLifecycleCallbacks dành cho Android api> = 14. Đối với Android api trước đó, bạn sẽ cần phải tự triển khai nó trong tất cả các hoạt động của mình ;-)

Sử dụng Ứng dụng khi bạn cần chia sẻ / lưu trữ trạng thái trong các hoạt động.

2) Kiểm tra thông tin quy trình đang chạy

Bạn có thể kiểm tra trạng thái của một tiến trình đang chạy với lớp RunningAppProcessInfo lớp này

Tìm nạp danh sách quy trình đang chạy với ActivityManager.getRunningAppProcesses () và lọc danh sách kết quả để kiểm tra RunningAppProcessInfo mong muốn và kiểm tra "tầm quan trọng" của nó



3

Sử dụng khoảng cách thời gian giữa tạm dừng và tiếp tục ở chế độ nền để xác định xem nó có hoạt động ở chế độ nền hay không

Trong ứng dụng tùy chỉnh

private static boolean isInBackground;
private static boolean isAwakeFromBackground;
private static final int backgroundAllowance = 10000;

public static void activityPaused() {
    isInBackground = true;
    final Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            if (isInBackground) {
                isAwakeFromBackground = true;
            }
        }
    }, backgroundAllowance);
    Log.v("activity status", "activityPaused");
}

public static void activityResumed() {
    isInBackground = false;
    if(isAwakeFromBackground){
        // do something when awake from background
        Log.v("activity status", "isAwakeFromBackground");
    }
    isAwakeFromBackground = false;
    Log.v("activity status", "activityResumed");
}

Trong lớp BaseActivity

@Override
protected void onResume() {
  super.onResume();
  MyApplication.activityResumed();
}

@Override
protected void onPause() {
  super.onPause();
  MyApplication.activityPaused();
}

3

Tôi nghĩ rằng tôi có giải pháp tốt hơn. Bởi vì bạn có thể xây dựng đơn giản trong MyApplication.activityResumed (); cho mọi Hoạt động của một lần mở rộng.

Đầu tiên bạn phải tạo (như CyberneticTwerkGuruOrc)

public class MyApplication extends Application {

  public static boolean isActivityVisible() {
    return activityVisible;
  }  

  public static void activityResumed() {
    activityVisible = true;
  }

  public static void activityPaused() {
    activityVisible = false;
  }

  private static boolean activityVisible;
}

Tiếp theo, bạn phải thêm lớp Ứng dụng vào AndroidManifest.xml

<application
    android:name="your.app.package.MyApplication"
    android:icon="@drawable/icon"
    android:label="@string/app_name" >

Sau đó, tạo ActivityBase lớp

public class ActivityBase extends Activity {

    @Override
    protected void onPause() {
        super.onPause();
        MyApplication.activityPaused();
    }

    @Override
    protected void onResume() {
        super.onResume();
        MyApplication.activityResumed();
    }
}

Cuối cùng, khi xếp Hoạt động mới, bạn chỉ cần mở rộng nó bằng ActivityBase thay vì Activity.

public class Main extends ActivityBase {
    @Override
    protected void onResume() {
        super.onResume();
    }

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

Đối với tôi, đó là phương pháp tốt hơn vì bạn chỉ cần nhớ về việc mở rộng bằng ActivityBase. Ngoài ra, bạn có thể mở rộng chức năng cơ sở của mình trong tương lai. Trong trường hợp của tôi, tôi đã thêm bộ thu cho dịch vụ của mình và cảnh báo về mạng trong một lớp.

Nếu bạn muốn kiểm tra mức độ hiển thị của Ứng dụng của mình, bạn có thể chỉ cần gọi

MyApplication.isActivityVisible()

Điều gì xảy ra nếu tôi cần Hoạt động của mình để mở rộng AppCombatActivity?
winklerrr

2

Điều này có thể đạt được điều này một cách hiệu quả bằng cách sử dụng Application.ActivityLifecycleCallbacks

Ví dụ, cho phép lấy tên lớp Activity làm ProfileActivity cho phép tìm xem nó ở nền trước hay nền

trước tiên, chúng ta cần tạo lớp ứng dụng của mình bằng cách mở rộng Lớp ứng dụng

cái nào thực hiện

Application.ActivityLifecycleCallbacks

Hãy trở thành lớp Ứng dụng của tôi như sau

Lớp ứng dụng

public class AppController extends Application implements Application.ActivityLifecycleCallbacks {


private boolean activityInForeground;

@Override
public void onCreate() {
    super.onCreate();

//register ActivityLifecycleCallbacks  

    registerActivityLifecycleCallbacks(this);

}



public static boolean isActivityVisible() {
    return activityVisible;
}

public static void activityResumed() {
    activityVisible = true;
}

public static void activityPaused() {
    activityVisible = false;
}

private static boolean activityVisible;

@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {

}

@Override
public void onActivityStarted(Activity activity) {

}

@Override
public void onActivityResumed(Activity activity) {
    //Here you can add all Activity class you need to check whether its on screen or not

    activityInForeground = activity instanceof ProfileActivity;
}

@Override
public void onActivityPaused(Activity activity) {

}

@Override
public void onActivityStopped(Activity activity) {

}

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

}

@Override
public void onActivityDestroyed(Activity activity) {

}

public boolean isActivityInForeground() {
    return activityInForeground;
}
}

trong lớp trên có ghi đè methord onActivityResumed of ActivityLifecycleCallbacks

 @Override
public void onActivityResumed(Activity activity) {
    //Here you can add all Activity class you need to check whether its on screen or not

    activityInForeground = activity instanceof ProfileActivity;
}

nơi có thể tìm thấy tất cả phiên bản hoạt động hiện đang hiển thị trên màn hình, chỉ cần kiểm tra xem Hoạt động của bạn có trên Màn hình hay không bằng phương pháp trên.

Đăng ký lớp Ứng dụng của bạn trong tệp kê khai.xml

<application
    android:name=".AppController" />

Để kiểm tra thời tiết Hoạt động là Tiền cảnh hay hậu cảnh theo giải pháp trên, hãy gọi phương thức sau ở những nơi bạn cần kiểm tra

AppController applicationControl = (AppController) getApplicationContext();
    if(applicationControl.isActivityInForeground()){
     Log.d("TAG","Activity is in foreground")
    }
    else
    {
      Log.d("TAG","Activity is in background")
    }

1

Nếu bạn muốn biết liệu bất kỳ hoạt động nào của ứng dụng của bạn có hiển thị trên màn hình hay không, bạn có thể làm như sau:

public class MyAppActivityCallbacks implements Application.ActivityLifecycleCallbacks {
private Set<Class<Activity>> visibleActivities = new HashSet<>();

@Override
public void onActivityResumed(Activity activity) {
    visibleActivities.add((Class<Activity>) activity.getClass());
}

@Override
public void onActivityStopped(Activity activity) {
     visibleActivities.remove(activity.getClass());
}

public boolean isAnyActivityVisible() {
    return !visibleActivities.isEmpty();
}

@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {}

@Override
public void onActivityStarted(Activity activity) {}

@Override
public void onActivityPaused(Activity activity) {}

@Override
public void onActivityDestroyed(Activity activity) {}

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

Chỉ cần tạo một singleton của lớp này và đặt nó trong cá thể Ứng dụng của bạn như dưới đây:

class App extends Application{
     @Override
     public void onCreate() {
         registerActivityLifecycleCallbacks(myAppActivityCallbacks);
     }
}

Sau đó, bạn có thể sử dụng phương thức isAnyActivityVbroken () của phiên bản MyAppActivityCallbacks của bạn ở mọi nơi!


0

bạn đã thử gọi xong chưa và đặt "android: noHistory =" true "trong tệp kê khai? điều này sẽ ngăn hoạt động đi vào ngăn xếp.


0

Tôi phải nói rằng quy trình làm việc của bạn không theo cách chuẩn của Android. Trong Android, bạn không cần đến finish()hoạt động của mình nếu bạn muốn mở một hoạt động khác từ Intent. Để thuận tiện cho người dùng, Android cho phép người dùng sử dụng phím 'quay lại' để quay lại từ hoạt động bạn đã mở ứng dụng của mình.

Vì vậy, chỉ cần để hệ thống ngừng hoạt động của bạn và lưu mọi thứ cần thiết khi hoạt động của bạn được gọi lại.


Tôi thực sự không biết tại sao điều này bị đánh giá thấp. Ít nhất hãy đưa ra một bình luận vì một lý do là những gì tôi muốn.
Owen Zhao

3
Các câu trả lời theo cách "buu đây không phải là android" khiến bạn mệt mỏi và không trả lời được câu hỏi được đặt ra ngay từ đầu. hơn nữa, có những lý do hợp lệ để kết thúc (); - ví dụ, có thể hình dung được rằng việc quay lại nó sau khi hành động đã được thực hiện không phục vụ mục đích gì. nói cách khác, bạn có nghĩ rằng họ đặt finish () ở đó cho vui không? nó ở trên stack là chính xác những gì Asker câu hỏi muốn tránh
Lassi Kinnunen

0

Lưu cờ nếu bạn bị tạm dừng hoặc tiếp tục. Nếu bạn được tiếp tục, điều đó có nghĩa là bạn đang ở phía trước

boolean  isResumed = false;

@Override
public void onPause() {
  super.onPause();    
  isResumed = false;
}

@Override
public void onResume() {
  super.onResume();    
  isResumed = true;
}

private void finishIfForeground() {
  if (isResumed) {
    finish();
  }
}

0

Một giải pháp khả thi có thể là đặt cờ trong khi hiển thị hộp thoại hệ thống và sau đó trong phương pháp onStop của vòng đời hoạt động, hãy kiểm tra cờ, nếu đúng, hãy kết thúc hoạt động.

Ví dụ: nếu hộp thoại hệ thống được kích hoạt bởi một số lần nhấp nút, thì trình nghe onclick có thể giống như

private OnClickListener btnClickListener = new OnClickListener() {

    @Override
    public void onClick(View v) {           
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_SEND);
        intent.setType("text/plain");
        CheckActivity.this.startActivity(Intent.createChooser(intent, "Complete action using"));
        checkFlag = true;  //flag used to check

    }
};

và khi ngừng hoạt động:

@Override
protected void onStop() {
    if(checkFlag){
        finish();
    }
    super.onStop();
}

0

Tại sao không sử dụng chương trình phát sóng cho việc này? hoạt động thứ hai (hoạt động cần được nâng cấp) có thể gửi một chương trình phát sóng cục bộ như thế này:

//put this in onCreate(..) or any other lifecycle method that suits you best
//notice the string sent to the intent, it will be used to register a receiver!
Intent result = new Intent("broadcast identifier");
result.putString("some message");//this is optional
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(result);

sau đó viết một bộ thu đơn giản trong hoạt động giật gân:

//this goes on the class level (like a class/instance variable, not in a method) of your splash activity:
private BroadcastReceiver receiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        //kill activity here!!!
        //mission accomplished!
    }
};

và đăng ký bộ thu mới của bạn với LocalBroadcastManager để nghe chương trình phát sóng từ hoạt động thứ hai của bạn:

//notice the string sent to the intent filter, this is where you tell the BroadcastManager which broadcasts you want to listen to!
LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(receiver, new IntentFilter("broadcast identifier"));

LƯU Ý rằng bạn có thể sử dụng một hằng số hoặc một tài nguyên chuỗi cho chuỗi "mã định danh quảng bá".


Cho tốt hơn an ninh hiệu quả quảng cáo sử dụng LocalBroadcastManagerở đây
Alexander Farber

0

Nếu bạn sử dụng finish()chỉ để tránh ứng dụng mới bắt đầu trong ngăn xếp (tác vụ) của ứng dụng, bạn có thể sử dụng Intent.FLAG_ACTIVITY_NEW_TASKcờ, khi khởi động ứng dụng mới và hoàn toàn không gọi finish(). Theo tài liệu , đây là cờ được sử dụng để thực hiện hành vi kiểu "launcher".

// just add this line before you start an activity
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

0

Sử dụng các phương pháp này bên trong của một Activity.

isDestroyed()

Đã thêm trong Api 17
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 phiên bản này hiện đã chết.

isFinishing()

Đã thêm vào Api 1
Kiểm tra xem liệu hoạt động này có đang trong quá trình hoàn tất hay không, do bạn đã gọi finish () trên nó hoặc ai đó đã yêu cầu nó hoàn thành. Đ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 hay hoàn toàn kết thúc.


Từ Tài liệu Rò rỉ Bộ nhớ

Một lỗi thường gặp AsyncTasklà nắm bắt một tham chiếu mạnh đến máy chủ Activity(hoặc Fragment):

class MyActivity extends Activity {
  private AsyncTask<Void, Void, Void> myTask = new AsyncTask<Void, Void, Void>() {
    // Don't do this! Inner classes implicitly keep a pointer to their
    // parent, which in this case is the Activity!
  }
}

Đây là một vấn đề vì AsyncTaskcó thể dễ dàng tồn tại lâu hơn phụ huynh Activity, ví dụ: nếu một thay đổi cấu hình xảy ra trong khi tác vụ đang chạy.

Cách đúng đắn để làm điều này là đặt tác vụ của bạn thành một staticlớp, lớp này không nắm bắt phần tử cha và giữ một tham chiếu yếu đến máy chủ Activity:

class MyActivity extends Activity {
  static class MyTask extends AsyncTask<Void, Void, Void> {
    // Weak references will still allow the Activity to be garbage-collected
    private final WeakReference<MyActivity> weakActivity;

    MyTask(MyActivity myActivity) {
      this.weakActivity = new WeakReference<>(myActivity);
    }

    @Override
    public Void doInBackground(Void... params) {
      // do async stuff here
    }

    @Override
    public void onPostExecute(Void result) {
      // Re-acquire a strong reference to the activity, and verify
      // that it still exists and is active.
      MyActivity activity = weakActivity.get();
      if (activity == null
          || activity.isFinishing()
          || activity.isDestroyed()) {
        // activity is no longer valid, don't do anything!
        return;
      }

      // The activity is still valid, do main-thread stuff here
    }
  }
}

0

Đây là một giải pháp sử dụng Applicationlớp.

public class AppSingleton extends Application implements Application.ActivityLifecycleCallbacks {

private WeakReference<Context> foregroundActivity;


@Override
public void onActivityResumed(Activity activity) {
    foregroundActivity=new WeakReference<Context>(activity);
}

@Override
public void onActivityPaused(Activity activity) {
    String class_name_activity=activity.getClass().getCanonicalName();
    if (foregroundActivity != null && 
            foregroundActivity.get().getClass().getCanonicalName().equals(class_name_activity)) {
        foregroundActivity = null;
    }
}

//............................

public boolean isOnForeground(@NonNull Context activity_cntxt) {
    return isOnForeground(activity_cntxt.getClass().getCanonicalName());
}

public boolean isOnForeground(@NonNull String activity_canonical_name) {
    if (foregroundActivity != null && foregroundActivity.get() != null) {
        return foregroundActivity.get().getClass().getCanonicalName().equals(activity_canonical_name);
    }
    return false;
}
}

Bạn có thể đơn giản sử dụng nó như sau,

((AppSingleton)context.getApplicationContext()).isOnForeground(context_activity);

Nếu bạn có tham chiếu đến Hoạt động bắt buộc hoặc sử dụng tên chuẩn của Hoạt động, bạn có thể tìm hiểu xem nó có ở phía trước hay không. Giải pháp này có thể không hiệu quả. Do đó ý kiến ​​của bạn thực sự được hoan nghênh.


0

Tôi không biết tại sao không ai nói về sharedPreferences, đối với Activity A, đặt SharedPreference như vậy (ví dụ: trong onPause ()):

SharedPreferences pref = context.getSharedPreferences(SHARED_PREF, 0);
SharedPreferences.Editor editor = pref.edit();
editor.putBoolean("is_activity_paused_a", true);
editor.commit();

Tôi nghĩ đây là cách đáng tin cậy để theo dõi các hoạt động trực quan.


0

Sẽ Activity.onWindowFocusChanged(boolean hasFocus)hữu ích ở đây? Điều đó, cộng với một lá cờ cấp lớp, tương tự như isFocusedvậyonWindowFocusChanged , sẽ là một cách dễ dàng để biết tại bất kỳ thời điểm nào trong hoạt động của bạn nếu nó được tập trung hay không. Từ việc đọc tài liệu, có vẻ như nó sẽ được đặt đúng "false" trong bất kỳ tình huống nào mà hoạt động không trực tiếp ở "nền trước" vật lý, chẳng hạn như nếu hộp thoại đang được hiển thị hoặc khay thông báo được kéo xuống.

Thí dụ:

boolean isFocused;
@Override
void onWindowFocusChanged (boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    isFocused = hasFocus;
}

void someMethod() {
    if (isFocused) {
        // The activity is the foremost object on the screen
    } else {
        // The activity is obscured or otherwise not visible
    }
}

0

Nếu bạn đang sử dụng EventBus , nó như một phương thức được gọi hasSubscriberForEventcó thể được sử dụng để kiểm tra xem một có Activityđược tiêu điểm hay không.


-3

Tôi đã từng làm như,

nếu hoạt động không ở phía trước

getIntent ()

sẽ trả về null. : = P

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.