Theo nền tảng, ý tôi là không có hoạt động nào của ứng dụng hiện đang hiển thị cho người dùng?
Theo nền tảng, ý tôi là không có hoạt động nào của ứng dụng hiện đang hiển thị cho người dùng?
Câu trả lời:
Có một số cách để phát hiện xem ứng dụng của bạn có chạy nền hay không, nhưng chỉ một trong số đó là hoàn toàn đáng tin cậy:
Các giải pháp phù hợp (các khoản tín dụng đi đến Dan , CommonsWare và NeTeInStEiN )
Theo dõi tầm nhìn của ứng dụng của bạn bằng cách sử dụng bản thân Activity.onPause
, Activity.onResume
phương pháp này. Lưu trữ trạng thái "khả năng hiển thị" trong một số lớp khác. Các lựa chọn tốt là việc bạn tự thực hiện Application
hoặc Service
(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 mức độ hiển thị của hoạt động từ dịch vụ).
Ví dụ
Triển khai Application
lớp tùy chỉnh (lưu ý isActivityVisible()
phương thức tĩnh):
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 tại AndroidManifest.xml
:
<application
android:name="your.app.package.MyApplication"
android:icon="@drawable/icon"
android:label="@string/app_name" >
Thêm onPause
và onResume
cho mọi người Activity
trong dự án (bạn có thể tạo tổ tiên chung cho 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. bạn vẫn cần phải viết bằng tay sau):
@Override
protected void onResume() {
super.onResume();
MyApplication.activityResumed();
}
@Override
protected void onPause() {
super.onPause();
MyApplication.activityPaused();
}
Cập nhật
ActivityLifecyclCallbacks đã được thêm vào trong API cấp 14 (Android 4.0). Bạn có thể sử dụng chúng để theo dõi xem một hoạt động của ứng dụng của bạn hiện đang hiển thị cho người dùng. Kiểm tra câu trả lời của Cornstalks bên dưới để biết chi tiết.
Một sai
tôi đã sử dụng để đề xuất giải pháp sau đây:
Bạn có thể phát hiện ứng dụng tiền cảnh / nền hiện đang
ActivityManager.getRunningAppProcesses()
trả về danh sách cácRunningAppProcessInfo
bản ghi. Để xác định xem ứng dụng của bạn là trên tờ séc foregroundRunningAppProcessInfo.importance
lĩnh vực bình đẳng đếnRunningAppProcessInfo.IMPORTANCE_FOREGROUND
khiRunningAppProcessInfo.processName
bằng tên gói ứng dụng của bạn.Ngoài ra nếu bạn gọi
ActivityManager.getRunningAppProcesses()
từ luồng UI ứng dụng của bạn, nó sẽ trả lại tầm quan trọngIMPORTANCE_FOREGROUND
cho nhiệm vụ của bạn cho dù nó có thực sự ở phía trước hay không. Gọi nó trong luồng nền (ví dụ thông quaAsyncTask
) và nó sẽ trả về kết quả chính xác.
Mặc dù giải pháp này có thể hoạt động (và nó thực sự hoạt động hầu hết thời gian), tôi thực sự khuyên bạn không nên sử dụng nó. Và đây là lý do. Như Dianne Hackborn đã viết :
Các API này không có cho các ứng dụng dựa trên luồng UI của chúng, nhưng để 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.
Có một danh sách 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 luồng chạy riêng biệt với bạn và không phải là thứ bạn có thể tin tưởng (a) 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 khi bạn quay lại. Cộng với quyết định về hoạt động "tiếp theo" sẽ luôn được thực hiện tại thời điểm xảy ra chuyển đổi và phải đến thời điểm chính xác đó (nơi trạng thái hoạt động bị khóa nhanh để thực hiện chuyển đổi) thực sự biết chắc chắn đ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.
Tôi ước tôi đã đọc được điều này trước khi tôi đăng câu trả lời lên SO, nhưng hy vọng vẫn chưa quá muộn để thừa nhận lỗi của mình.
Một giải pháp sai khác Thư viện
Droid-Fu được đề cập trong một trong những câu trả lời sử dụng ActivityManager.getRunningTasks
cho isApplicationBroughtToBackground
phương pháp của nó . Xem bình luận của Dianne ở trên và không sử dụng phương pháp đó.
OnStop
yêu cầu isActivityVisible
.
Câu trả lời của user1269737 là cách thích hợp (được Google / Android phê duyệt) để làm điều này . Đi đọc câu trả lời của họ và cho họ +1.
Tôi sẽ để lại câu trả lời ban đầu của tôi ở đây vì lợi ích của hậu thế. Đây là phiên bản tốt nhất có sẵn trong năm 2012, nhưng bây giờ Android đã hỗ trợ thích hợp cho việc này.
Chìa khóa đang sử dụng ActivityLifecycleCallbacks
(lưu ý rằng điều này yêu cầu API Android cấp 14 (Android 4.0)). Chỉ cần kiểm tra xem số lượng hoạt động dừng lại có bằng số lượng hoạt động bắt đầu không. Nếu chúng bằng nhau, ứng dụng của bạn đang được làm nền. Nếu có nhiều hoạt động bắt đầu, ứng dụng của bạn vẫn hiển thị. Nếu có nhiều hoạt động trở lại hơn các hoạt động bị tạm dừng, ứng dụng của bạn không chỉ hiển thị mà còn ở phía trước. Có 3 trạng thái chính mà hoạt động của bạn có thể ở, sau đó: hiển thị và ở phía trước, hiển thị nhưng không ở phía trước và không hiển thị và không ở phía trước (tức là trong nền).
Điều thực sự thú vị về phương pháp này là nó không có vấn đề không đồng bộ getRunningTasks()
, nhưng bạn cũng không phải sửa đổi mọi thứ Activity
trong ứng dụng của mình để đặt / hủy đặt cái gì đó trong onResumed()
/ onPaused()
. Đó chỉ là một vài dòng mã độc lập và nó hoạt động trong toàn bộ ứng dụng của bạn. Thêm vào đó, không có quyền yêu cầu sôi nổi.
MyLifecyclHandler.java:
public class MyLifecycleHandler implements ActivityLifecycleCallbacks {
// I use four separate variables here. You can, of course, just use two and
// increment/decrement them instead of using four and incrementing them all.
private int resumed;
private int paused;
private int started;
private int stopped;
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
}
@Override
public void onActivityResumed(Activity activity) {
++resumed;
}
@Override
public void onActivityPaused(Activity activity) {
++paused;
android.util.Log.w("test", "application is in foreground: " + (resumed > paused));
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityStarted(Activity activity) {
++started;
}
@Override
public void onActivityStopped(Activity activity) {
++stopped;
android.util.Log.w("test", "application is visible: " + (started > stopped));
}
// If you want a static function you can use to check if your application is
// foreground/background, you can use the following:
/*
// Replace the four variables above with these four
private static int resumed;
private static int paused;
private static int started;
private static int stopped;
// And these two public static functions
public static boolean isApplicationVisible() {
return started > stopped;
}
public static boolean isApplicationInForeground() {
return resumed > paused;
}
*/
}
MyApplication.java:
// Don't forget to add it to your manifest by doing
// <application android:name="your.package.MyApplication" ...
public class MyApplication extends Application {
@Override
public void onCreate() {
// Simply add the handler, and that's it! No need to add any code
// to every activity. Everything is contained in MyLifecycleHandler
// with just a few lines of code. Now *that's* nice.
registerActivityLifecycleCallbacks(new MyLifecycleHandler());
}
}
@Mewzer đã hỏi một số câu hỏi hay về phương pháp này mà tôi muốn trả lời trong câu trả lời này cho mọi người:
onStop()
không được gọi trong các tình huống bộ nhớ thấp; đó có phải là một vấn đề ở đây không?
Không. Các tài liệu để onStop()
nói:
Lưu ý rằng phương thức này có thể không bao giờ được gọi, trong các tình huống bộ nhớ thấp trong đó hệ thống không có đủ bộ nhớ để duy trì quá trình hoạt động của bạn sau khi phương thức onPause () của nó được gọi.
Chìa khóa ở đây là "giữ cho quá trình hoạt động của bạn hoạt động ..." Nếu đạt đến tình trạng bộ nhớ thấp này, quá trình của bạn thực sự bị giết (không chỉ hoạt động của bạn). Điều này có nghĩa là phương pháp kiểm tra nền này vẫn còn hiệu lực vì a) dù sao bạn cũng không thể kiểm tra nền nếu quy trình của bạn bị giết và b) nếu quy trình của bạn bắt đầu lại (vì một hoạt động mới được tạo), thành viên các biến (cho dù tĩnh hay không) MyLifecycleHandler
sẽ được đặt lại thành 0
.
Điều này có làm việc để thay đổi cấu hình?
Theo mặc định, không. Bạn phải đặt rõ ràng configChanges=orientation|screensize
( |
với bất kỳ thứ gì bạn muốn) trong tệp kê khai của bạn và xử lý các thay đổi cấu hình, nếu không hoạt động của bạn sẽ bị hủy và được tạo lại. Nếu bạn không đặt điều này, các phương thức của hoạt động của bạn sẽ được gọi theo thứ tự này : onCreate -> onStart -> onResume -> (now rotate) -> onPause -> onStop -> onDestroy -> onCreate -> onStart -> onResume
. Như bạn có thể thấy, không có sự trùng lặp (thông thường, hai hoạt động chồng chéo rất ngắn khi chuyển đổi giữa hai, đó là cách phương thức phát hiện nền này hoạt động). Để giải quyết vấn đề này, bạn phải thiết lập configChanges
để hoạt động của bạn không bị phá hủy. May mắn thay, tôi đã phải thiết lậpconfigChanges
đã có trong tất cả các dự án của tôi vì không mong muốn toàn bộ hoạt động của tôi bị phá hủy khi xoay / thay đổi kích thước màn hình, vì vậy tôi chưa bao giờ thấy điều này có vấn đề. (cảm ơn dpimka vì đã làm mới trí nhớ của tôi về điều này và sửa lỗi cho tôi!)
Một lưu ý:
Khi tôi nói "nền" ở đây trong câu trả lời này, tôi có nghĩa là "ứng dụng của bạn không còn hiển thị nữa". Các hoạt động của Android có thể hiển thị nhưng không ở phía trước (ví dụ: nếu có lớp phủ thông báo trong suốt). Đó là lý do tại sao tôi đã cập nhật câu trả lời này để phản ánh điều đó.
Điều quan trọng cần biết là Android có một khoảnh khắc lấp lửng kỳ lạ khi chuyển đổi các hoạt động mà không có gì ở phía trước . Vì lý do này, nếu bạn kiểm tra xem ứng dụng của bạn có ở phía trước hay không khi chuyển đổi giữa các hoạt động (trong cùng một ứng dụng), bạn sẽ được thông báo rằng bạn không ở trong nền trước (mặc dù ứng dụng của bạn vẫn là ứng dụng đang hoạt động và hiển thị ).
Bạn có thể kiểm tra xem ứng dụng của bạn ở phía trước trong của bạn Activity
's onPause()
phương pháp sau super.onPause()
. Chỉ cần nhớ trạng thái limbo kỳ lạ mà tôi vừa nói.
Bạn có thể kiểm tra xem ứng dụng của bạn được hiển thị (tức là nếu nó không ở chế độ nền) trong của bạn Activity
's onStop()
phương pháp sau super.onStop()
.
onStop()
sau super.onStop()
. Không kiểm tra nền onPause()
.
GIẢI PHÁP GOOGLE - không phải là hack, như các giải pháp trước đây. Sử dụng ProcessLifecyclOwner
Kotlin:
class ArchLifecycleApp : Application(), LifecycleObserver {
override fun onCreate() {
super.onCreate()
ProcessLifecycleOwner.get().lifecycle.addObserver(this)
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun onAppBackgrounded() {
//App in background
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun onAppForegrounded() {
// App in foreground
}
}
Java:
public class ArchLifecycleApp extends Application implements LifecycleObserver {
@Override
public void onCreate() {
super.onCreate();
ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
public void onAppBackgrounded() {
//App in background
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
public void onAppForegrounded() {
// App in foreground
}
}
trong app.gradle
dependencies {
...
implementation "android.arch.lifecycle:extensions:1.1.0"
//New Android X dependency is this -
implementation "androidx.lifecycle:lifecycle-extensions:2.0.0"
}
allprojects {
repositories {
...
google()
jcenter()
maven { url 'https://maven.google.com' }
}
}
Bạn có thể đọc thêm về các thành phần kiến trúc liên quan đến Vòng đời tại đây - https://developer.android.com/topic/l library / arch architecture / lifecycle
companion object { private var foreground = false fun isForeground() : Boolean { return foreground } }
sau đó bạn có thể có trạng thái nền trước vớiArchLifecycleApp.isForeground()
The LifecycleOwner for the whole application process. Note that if your application has multiple processes, this provider does not know about other processes.
, điều này không hoạt động cho multiple processes
các ứng dụng, có một số api chúng ta có thể đạt được một cách thanh lịch?
Bắt đầu thư viện hỗ trợ phiên bản 26, bạn có thể sử dụng ProcessLifecycleOwner , chỉ cần thêm nó vào 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
}
Và sau đó chỉ cần truy vấn ProcessLifecycleOwner
bất cứ khi nào bạn muốn cho trạng thái ứng dụng, ví dụ:
//Check if app is in background
ProcessLifecycleOwner.get().getLifecycle().getCurrentState() == Lifecycle.State.CREATED;
//Check if app is in foreground
ProcessLifecycleOwner.get().getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED);
Vì API Android 16, có một cách đơn giản để kiểm tra xem ứng dụng có ở phía trước không. Nó có thể không phải là hoàn hảo, nhưng không có phương pháp nào trên Android là hoàn hảo. Phương pháp này đủ tốt để sử dụng khi dịch vụ của bạn nhận được cập nhật từ máy chủ và phải quyết định có hiển thị thông báo hay không (vì nếu UI là tiền cảnh, người dùng sẽ thông báo cập nhật mà không cần thông báo).
RunningAppProcessInfo myProcess = new RunningAppProcessInfo();
ActivityManager.getMyMemoryState(myProcess);
isInBackground = myProcess.importance != RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
JobService
để phát hiện dịch vụ đang chạy ẩn.
Câu trả lời của Idolon dễ bị lỗi và phức tạp hơn nhiều mặc dù có lặp lại ở đây kiểm tra ứng dụng Android có ở phía trước hay không? và ở đây Xác định ứng dụng tiền cảnh hiện tại từ một tác vụ hoặc dịch vụ nền
Có một cách tiếp cận đơn giản hơn nhiều:
Trên BaseActivity mà tất cả các Hoạt động mở rộng:
protected static boolean isVisible = false;
@Override
public void onResume()
{
super.onResume();
setVisible(true);
}
@Override
public void onPause()
{
super.onPause();
setVisible(false);
}
Bất cứ khi nào bạn cần kiểm tra xem có bất kỳ hoạt động ứng dụng nào của bạn ở phía trước hay không, chỉ cần kiểm tra isVisible()
;
Để hiểu cách tiếp cận này, hãy kiểm tra câu trả lời này của vòng đời hoạt động song song: Vòng đời hoạt động song song
Idolon's answer is error prone
- tiếc là tôi phải đồng ý với bạn. Dựa trên nhận xét của Dianne Hackborn trong Nhóm Google tôi đã cập nhật câu trả lời của mình. Kiểm tra nó xin vui lòng cho các chi tiết.
onPause
, onStop
, cũng không phải là onResume
sự kiện được gọi. Vậy bạn sẽ làm gì sau đó nếu không có sự kiện nào trong số này bị sa thải?!
Tôi đã thử giải pháp được đề xuất sử dụng Application.ActivityLifecyclCallbacks và nhiều giải pháp khác, nhưng chúng không hoạt động như mong đợi. Nhờ có Sarge , tôi đã đưa ra một giải pháp khá dễ dàng và đơn giản mà tôi đang mô tả dưới đây.
Chìa khóa của giải pháp là thực tế hiểu rằng nếu chúng ta có ActivityA và ActivityB và chúng ta gọi ActivityB từ ActivityA (và không gọi
ActivityA.finish
), thì ActivityBonStart()
sẽ được gọi trước ActivityAonStop()
.
Đó cũng là điểm khác biệt chính giữa onStop()
và onPause()
không ai đề cập đến trong các bài báo tôi đọc.
Vì vậy, dựa trên hành vi Vòng đời của Hoạt động này, bạn chỉ cần đếm số lần thực hiện onStart()
và onPause()
được gọi trong chương trình của mình. Lưu ý rằng đối với mỗi Activity
chương trình của bạn, bạn phải ghi đè onStart()
và onStop()
, để tăng / giảm biến tĩnh được sử dụng để đếm. Dưới đây là mã thực hiện logic này. Lưu ý rằng tôi đang sử dụng một lớp mở rộng Application
, vì vậy đừng quên khai báo Manifest.xml
bên trong thẻ Ứng dụng: android:name=".Utilities"
mặc dù nó cũng có thể được thực hiện bằng một lớp tùy chỉnh đơn giản.
public class Utilities extends Application
{
private static int stateCounter;
public void onCreate()
{
super.onCreate();
stateCounter = 0;
}
/**
* @return true if application is on background
* */
public static boolean isApplicationOnBackground()
{
return stateCounter == 0;
}
//to be called on each Activity onStart()
public static void activityStarted()
{
stateCounter++;
}
//to be called on each Activity onStop()
public static void activityStopped()
{
stateCounter--;
}
}
Bây giờ trên mỗi Hoạt động của chương trình của chúng tôi, chúng ta nên ghi đè onStart()
và onStop()
và tăng / giảm như hình dưới đây:
@Override
public void onStart()
{
super.onStart();
Utilities.activityStarted();
}
@Override
public void onStop()
{
Utilities.activityStopped();
if(Utilities.isApplicationOnBackground())
{
//you should want to check here if your application is on background
}
super.onStop();
}
Với logic này, có 2 trường hợp có thể xảy ra:
stateCounter = 0
: Số lượng dừng bằng với số lượng Hoạt động bắt đầu, có nghĩa là ứng dụng đang chạy trên nền.stateCounter > 0
: Số lượng bắt đầu lớn hơn số lượng dừng, có nghĩa là ứng dụng đang chạy trên nền trước.Lưu ý: stateCounter < 0
sẽ có nghĩa là có nhiều Hoạt động bị dừng hơn là bắt đầu, điều này là không thể. Nếu bạn gặp trường hợp này, thì điều đó có nghĩa là bạn không tăng / giảm bộ đếm như bạn nên.
Bạn đã sẵn sàng để đi. Bạn nên kiểm tra xem ứng dụng của bạn có ở trên nền không onStop()
.
if(Utilities.isApplicationOnBackground()) …
đến Utilities
. Bởi vì nếu không thì chỉ một hoạt động cụ thể sẽ phản ứng với sự kiện.
Không có cách nào, bạn tự mình theo dõi nó, để xác định xem có bất kỳ hoạt động nào của bạn có thể nhìn thấy hay không. Có lẽ bạn nên xem xét việc đặt câu hỏi StackOverflow mới, giải thích những gì bạn đang cố gắng đạt được từ trải nghiệm người dùng, vì vậy chúng tôi có thể cung cấp cho bạn các ý tưởng triển khai thay thế.
Service
. Nếu vậy, yêu cầu các hoạt động của bạn thông báo cho dịch vụ khi chúng xuất hiện và biến mất. Nếu Service
xác định rằng không có hoạt động nào hiển thị và vẫn duy trì như vậy trong một khoảng thời gian, hãy dừng truyền dữ liệu tại điểm dừng logic tiếp theo. Có, điều này sẽ yêu cầu mã cho từng hoạt động của bạn, nhưng ngay bây giờ, đó là điều không thể tránh khỏi AFAIK.
MyActivityClass
kế thừa từ Activity
và thực hiện các phương thức vòng đời và làm cho tất cả các hoạt động của bạn được kế thừa từ đó MyActivityClass
. Điều này sẽ không hoạt động PreferenceActivity
hoặc MapActivity
mặc dù (xem câu hỏi này )
Bạn có thể sử dụng ElementCallbacks2 để phát hiện xem ứng dụng có ở chế độ nền không. BTW cuộc gọi lại này chỉ khả dụng trong API Cấp 14 (Ice Cream Sandwich) trở lên.
Bạn sẽ nhận được một cuộc gọi đến phương thức:
public abstract void onTrimMemory (int level)
nếu cấp độ ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
thì ứng dụng ở chế độ nền.
Bạn có thể thực hiện giao diện này để một activity
, service
vv
public class MainActivity extends AppCompatActivity implements ComponentCallbacks2 {
@Override
public void onConfigurationChanged(final Configuration newConfig) {
}
@Override
public void onLowMemory() {
}
@Override
public void onTrimMemory(final int level) {
if (level == ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
// app is in background
}
}
}
Xây dựng trên câu trả lời @Cornstalks để bao gồm một vài tính năng hữu ích.
Các tính năng bổ sung:
App.java
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(AppLifecycleHandler.getInstance());
}
}
AppLifecyclHandler.java
public class AppLifecycleHandler implements Application.ActivityLifecycleCallbacks {
private int resumed;
private int started;
private final String DebugName = "AppLifecycleHandler";
private boolean isVisible = false;
private boolean isInForeground = false;
private static AppLifecycleHandler instance;
public static AppLifecycleHandler getInstance() {
if (instance == null) {
instance = new AppLifecycleHandler();
}
return instance;
}
private AppLifecycleHandler() {
}
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
}
@Override
public void onActivityResumed(Activity activity) {
++resumed;
android.util.Log.w(DebugName, "onActivityResumed -> application is in foreground: " + (resumed > 0) + " (" + activity.getClass() + ")");
setForeground((resumed > 0));
}
@Override
public void onActivityPaused(Activity activity) {
--resumed;
android.util.Log.w(DebugName, "onActivityPaused -> application is in foreground: " + (resumed > 0) + " (" + activity.getClass() + ")");
setForeground((resumed > 0));
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityStarted(Activity activity) {
++started;
android.util.Log.w(DebugName, "onActivityStarted -> application is visible: " + (started > 0) + " (" + activity.getClass() + ")");
setVisible((started > 0));
}
@Override
public void onActivityStopped(Activity activity) {
--started;
android.util.Log.w(DebugName, "onActivityStopped -> application is visible: " + (started > 0) + " (" + activity.getClass() + ")");
setVisible((started > 0));
}
private void setVisible(boolean visible) {
if (isVisible == visible) {
// no change
return;
}
// visibility changed
isVisible = visible;
android.util.Log.w(DebugName, "App Visiblility Changed -> application is visible: " + isVisible);
// take some action on change of visibility
}
private void setForeground(boolean inForeground) {
if (isInForeground == inForeground) {
// no change
return;
}
// in foreground changed
isInForeground = inForeground;
android.util.Log.w(DebugName, "App In Foreground Changed -> application is in foreground: " + isInForeground);
// take some action on change of in foreground
}
public static boolean isApplicationVisible() {
return AppLifecycleHandler.getInstance().started > 0;
}
public static boolean isApplicationInForeground() {
return AppLifecycleHandler.getInstance().resumed > 0;
}
}
Giải pháp tốt nhất tôi đã đưa ra với việc sử dụng bộ tính giờ.
Bạn đã bắt đầu bộ hẹn giờ trong onPause () và hủy cùng bộ hẹn giờ trong onResume (), có 1 phiên bản của Timer (thường được xác định trong lớp Ứng dụng). Bản thân bộ hẹn giờ được đặt để chạy Runnable sau 2 giây (hoặc bất kỳ khoảng thời gian nào bạn nghĩ là phù hợp), khi bộ hẹn giờ kích hoạt bạn đặt cờ đánh dấu ứng dụng ở chế độ nền.
Trong phương thức onResume () trước khi bạn hủy bộ hẹn giờ, bạn có thể truy vấn cờ nền để thực hiện bất kỳ thao tác khởi động nào (ví dụ: bắt đầu tải xuống hoặc bật dịch vụ định vị).
Giải pháp này cho phép bạn có một số hoạt động trên ngăn xếp phía sau và không yêu cầu bất kỳ quyền nào để thực hiện.
Giải pháp này hoạt động tốt nếu bạn cũng sử dụng xe buýt sự kiện, vì bộ đếm thời gian của bạn chỉ đơn giản có thể kích hoạt một sự kiện và các phần khác nhau trong ứng dụng của bạn có thể đáp ứng tương ứng.
Nếu bạn bật cài đặt dành cho nhà phát triển "Đừng giữ hành động" - chỉ kiểm tra số lượng kích hoạt đã tạo là không đủ. Bạn cũng phải kiểm tra isSaveInstanceState . My phương pháp tùy chỉnh isApplicationRunning () kiểm tra là ứng dụng Android đang chạy:
Đây là mã công việc của tôi:
public class AppLifecycleService implements Application.ActivityLifecycleCallbacks {
private int created;
private boolean isSaveInstanceState;
private static AppLifecycleService instance;
private final static String TAG = AppLifecycleService.class.getName();
public static AppLifecycleService getInstance() {
if (instance == null) {
instance = new AppLifecycleService();
}
return instance;
}
public static boolean isApplicationRunning() {
boolean isApplicationRunning = true;
if (getCountCreatedActvities() == 0 && !isSaveInstanceState()) {
isApplicationRunning = false;
}
return isApplicationRunning;
}
public static boolean isSaveInstanceState() {
return AppLifecycleService.getInstance().isSaveInstanceState;
}
public static int getCountCreatedActvities() {
return AppLifecycleService.getInstance().created;
}
private AppLifecycleService() {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
this.isSaveInstanceState = true;
}
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
++created;
}
@Override
public void onActivityDestroyed(Activity activity) {
--created;
}
@Override
public void onActivityResumed(Activity activity) { }
@Override
public void onActivityPaused(Activity activity) { }
@Override
public void onActivityStarted(Activity activity) { }
@Override
public void onActivityStopped(Activity activity) { }
}
Chỉ có một giải pháp đúng:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
MyApp.mainActivity = this;
super.onCreate(savedInstanceState);
...
}
public class MyApp extends Application implements LifecycleObserver {
public static MainActivity mainActivity = null;
@Override
public void onCreate() {
super.onCreate();
ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
void onAppBackgrounded() {
// app in background
if (mainActivity != null) {
...
}
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
void onAppForegrounded() {
// app in foreground
if (mainActivity != null) {
...
}
}
}
Để cõng những gì CommonsWare và Key đã nói, có lẽ bạn có thể mở rộng lớp Ứng dụng và có tất cả các hoạt động của bạn gọi đó là phương thức onPause / onResume của chúng. Điều này sẽ cho phép bạn biết (các) Hoạt động nào có thể nhìn thấy, nhưng điều này có thể được xử lý tốt hơn.
Bạn có thể giải thích chính xác những gì bạn có trong tâm trí? Khi bạn nói chạy trong nền, bạn có nghĩa là chỉ cần ứng dụng của bạn vẫn còn trong bộ nhớ mặc dù hiện tại nó không có trên màn hình? Bạn đã xem xét việc sử dụng Dịch vụ như một cách liên tục hơn để quản lý ứng dụng của mình khi ứng dụng không tập trung chưa?
Application
không có onPause()
hoặc onResume()
.
Tôi đã tự thực hiện ActivityLifecycleCallbacks. Tôi đang sử dụng SherlockActivity, nhưng đối với lớp Activity bình thường có thể hoạt động.
Đầu tiên, tôi đang tạo một giao diện có tất cả các phương thức để theo dõi vòng đời hoạt động:
public interface ActivityLifecycleCallbacks{
public void onActivityStopped(Activity activity);
public void onActivityStarted(Activity activity);
public void onActivitySaveInstanceState(Activity activity, Bundle outState);
public void onActivityResumed(Activity activity);
public void onActivityPaused(Activity activity);
public void onActivityDestroyed(Activity activity);
public void onActivityCreated(Activity activity, Bundle savedInstanceState);
}
Thứ hai, tôi đã triển khai giao diện này trong lớp Ứng dụng của mình:
public class MyApplication extends Application implements my.package.ActivityLifecycleCallbacks{
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onActivityStopped(Activity activity) {
Log.i("Tracking Activity Stopped", activity.getLocalClassName());
}
@Override
public void onActivityStarted(Activity activity) {
Log.i("Tracking Activity Started", activity.getLocalClassName());
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
Log.i("Tracking Activity SaveInstanceState", activity.getLocalClassName());
}
@Override
public void onActivityResumed(Activity activity) {
Log.i("Tracking Activity Resumed", activity.getLocalClassName());
}
@Override
public void onActivityPaused(Activity activity) {
Log.i("Tracking Activity Paused", activity.getLocalClassName());
}
@Override
public void onActivityDestroyed(Activity activity) {
Log.i("Tracking Activity Destroyed", activity.getLocalClassName());
}
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
Log.i("Tracking Activity Created", activity.getLocalClassName());
}
}
Thứ ba, tôi đang tạo một lớp học mở rộng từ SherlockActivity:
public class MySherlockActivity extends SherlockActivity {
protected MyApplication nMyApplication;
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
nMyApplication = (MyApplication) getApplication();
nMyApplication.onActivityCreated(this, savedInstanceState);
}
protected void onResume() {
// TODO Auto-generated method stub
nMyApplication.onActivityResumed(this);
super.onResume();
}
@Override
protected void onPause() {
// TODO Auto-generated method stub
nMyApplication.onActivityPaused(this);
super.onPause();
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
nMyApplication.onActivityDestroyed(this);
super.onDestroy();
}
@Override
protected void onStart() {
nMyApplication.onActivityStarted(this);
super.onStart();
}
@Override
protected void onStop() {
nMyApplication.onActivityStopped(this);
super.onStop();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
nMyApplication.onActivitySaveInstanceState(this, outState);
super.onSaveInstanceState(outState);
}
}
Thứ tư, tất cả các lớp mở rộng từ SherlockActivity, tôi đã thay thế cho MySherlockActivity:
public class MainActivity extends MySherlockActivity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
Bây giờ, trong logcat, bạn sẽ thấy các bản ghi được lập trình trong triển khai Giao diện được thực hiện trong MyApplication.
Vì nó chưa được đề cập, tôi sẽ đề nghị độc giả khám phá ProcessLifecycleOwner có sẵn thông qua các thành phần Kiến trúc Android
Hệ thống phân biệt giữa các ứng dụng nền trước và nền. (Định nghĩa nền cho mục đích giới hạn dịch vụ khác với định nghĩa được sử dụng bởi quản lý bộ nhớ; một ứng dụng có thể ở chế độ nền liên quan đến quản lý bộ nhớ , nhưng ở phía trước liên quan đến khả năng khởi chạy dịch vụ của nó.) Một ứng dụng là được coi là ở phía trước nếu bất kỳ điều nào sau đây là đúng:
Nếu không có điều kiện nào là đúng, ứng dụng được coi là ở chế độ nền.
Một giải pháp khác cho bài viết cũ này (đối với những bài viết có thể giúp ích):
<application android:name=".BaseApplication" ... >
public class BaseApplication extends Application {
private class Status {
public boolean isVisible = true;
public boolean isFocused = true;
}
private Map<Activity, Status> activities;
@Override
public void onCreate() {
activities = new HashMap<Activity, Status>();
super.onCreate();
}
private boolean hasVisibleActivity() {
for (Status status : activities.values())
if (status.isVisible)
return true;
return false;
}
private boolean hasFocusedActivity() {
for (Status status : activities.values())
if (status.isFocused)
return true;
return false;
}
public void onActivityCreate(Activity activity, boolean isStarting) {
if (isStarting && activities.isEmpty())
onApplicationStart();
activities.put(activity, new Status());
}
public void onActivityStart(Activity activity) {
if (!hasVisibleActivity() && !hasFocusedActivity())
onApplicationForeground();
activities.get(activity).isVisible = true;
}
public void onActivityWindowFocusChanged(Activity activity, boolean hasFocus) {
activities.get(activity).isFocused = hasFocus;
}
public void onActivityStop(Activity activity, boolean isFinishing) {
activities.get(activity).isVisible = false;
if (!isFinishing && !hasVisibleActivity() && !hasFocusedActivity())
onApplicationBackground();
}
public void onActivityDestroy(Activity activity, boolean isFinishing) {
activities.remove(activity);
if(isFinishing && activities.isEmpty())
onApplicationStop();
}
private void onApplicationStart() {Log.i(null, "Start");}
private void onApplicationBackground() {Log.i(null, "Background");}
private void onApplicationForeground() {Log.i(null, "Foreground");}
private void onApplicationStop() {Log.i(null, "Stop");}
}
public class MyActivity extends BaseActivity {...}
public class BaseActivity extends Activity {
private BaseApplication application;
@Override
protected void onCreate(Bundle state) {
application = (BaseApplication) getApplication();
application.onActivityCreate(this, state == null);
super.onCreate(state);
}
@Override
protected void onStart() {
application.onActivityStart(this);
super.onStart();
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
application.onActivityWindowFocusChanged(this, hasFocus);
super.onWindowFocusChanged(hasFocus);
}
@Override
protected void onStop() {
application.onActivityStop(this, isFinishing());
super.onStop();
}
@Override
protected void onDestroy() {
application.onActivityDestroy(this, isFinishing());
super.onDestroy();
}
}
Xem bình luận trong hàm onActivityDestroyed.
Hoạt động với SDK mục tiêu phiên bản 14>:
import android.app.Activity;
import android.app.Application;
import android.os.Bundle;
import android.util.Log;
public class AppLifecycleHandler implements Application.ActivityLifecycleCallbacks {
public static int active = 0;
@Override
public void onActivityStopped(Activity activity) {
Log.i("Tracking Activity Stopped", activity.getLocalClassName());
active--;
}
@Override
public void onActivityStarted(Activity activity) {
Log.i("Tracking Activity Started", activity.getLocalClassName());
active++;
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
Log.i("Tracking Activity SaveInstanceState", activity.getLocalClassName());
}
@Override
public void onActivityResumed(Activity activity) {
Log.i("Tracking Activity Resumed", activity.getLocalClassName());
active++;
}
@Override
public void onActivityPaused(Activity activity) {
Log.i("Tracking Activity Paused", activity.getLocalClassName());
active--;
}
@Override
public void onActivityDestroyed(Activity activity) {
Log.i("Tracking Activity Destroyed", activity.getLocalClassName());
active--;
// if active var here ever becomes zero, the app is closed or in background
if(active == 0){
...
}
}
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
Log.i("Tracking Activity Created", activity.getLocalClassName());
active++;
}
}
Bạn nên sử dụng tùy chọn chia sẻ để lưu trữ tài sản và hành động theo sở hữu đó bằng cách sử dụng ràng buộc dịch vụ từ các hoạt động của bạn. Nếu bạn chỉ sử dụng ràng buộc, (không bao giờ sử dụng startService), thì dịch vụ của bạn sẽ chỉ chạy khi bạn liên kết với nó, (liên kết onResume và hủy liên kết) sẽ khiến nó chỉ chạy trên nền trước và nếu bạn muốn làm việc trên nền bạn có thể sử dụng dịch vụ dừng bắt đầu thường xuyên.
Tôi nghĩ rằng câu hỏi này nên rõ ràng hơn. Khi nào? Ở đâu? Tình huống cụ thể của bạn mà bạn muốn konw là gì nếu ứng dụng của bạn ở chế độ nền?
Tôi chỉ giới thiệu giải pháp của tôi theo cách của tôi.
Tôi thực hiện điều này bằng cách sử dụng trường "tầm quan trọng" của RunningAppProcessInfo
lớp trong onStop
phương thức của mọi hoạt động trong ứng dụng của tôi, có thể đạt được một cách đơn giản bằng cách cung cấp BaseActivity
cho các hoạt động khác để mở rộng onStop
phương thức kiểm tra giá trị của "mức độ quan trọng". Đây là mã:
public static boolean isAppRunning(Context context) {
ActivityManager activityManager = (ActivityManager) context
.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningAppProcessInfo> appProcesses = activityManager
.getRunningAppProcesses();
for (RunningAppProcessInfo appProcess : appProcesses) {
if (appProcess.processName.equals(context.getPackageName())) {
if (appProcess.importance != RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE) {
return true;
}
}
}
return false;
}
Tôi khuyên bạn nên đọc qua trang này: http://developer.android.com/reference/android/app/Activity.html
Nói tóm lại, hoạt động của bạn không còn hiển thị sau khi onStop()
đã được gọi.
onStop
; giữa onPause
và onStop
nó có thể nhìn thấy , nhưng không phải ở phía trước .
onStop()
được gọi, được liên kết với những gì bạn đã viết.
onPause
được gọi: một chỉnh sửa gần đây đã sửa bạn.
Theo tôi, nhiều câu trả lời giới thiệu một tải nặng mã và mang lại nhiều sự phức tạp và không dễ đọc.
Khi mọi người hỏi về SO làm thế nào để giao tiếp giữa a Service
và a Activity
, tôi thường khuyên bạn nên sử dụng LocalBroadcastManager .
Tại sao?
Vâng, bằng cách trích dẫn các tài liệu:
Bạn biết rằng dữ liệu bạn đang phát sẽ không rời khỏi ứng dụng của bạn, vì vậy đừng lo lắng về việc rò rỉ dữ liệu riêng tư.
Các ứng dụng khác không thể gửi các chương trình phát sóng này đến ứng dụng của bạn, vì vậy bạn không cần phải lo lắng về việc có các lỗ hổng bảo mật mà chúng có thể khai thác.
Nó hiệu quả hơn gửi một chương trình phát sóng toàn cầu thông qua hệ thống.
Không có trong các tài liệu:
Activity
, Application
...Sự miêu tả
Vì vậy, bạn muốn kiểm tra xem có bất kỳ cái nào Activity
hiện đang ở phía trước không. Bạn thường làm điều đó trong một Service
, hoặc Application
lớp học của bạn .
Điều này có nghĩa, các Activity
đối tượng của bạn trở thành người gửi tín hiệu (Tôi đang bật / Tôi tắt). Của bạn Service
, mặt khác, trở thành Receiver
.
Có hai khoảnh khắc mà bạn Activity
nói với bạn nếu nó ở phía trước hoặc phía sau (có chỉ hai ... không phải 6).
Khi Activity
đi vào nền trước, onResume()
phương thức được kích hoạt (còn được gọi là sau onCreate()
).
Khi Activity
đi ở phía sau, onPause()
được gọi.
Đây là những khoảnh khắc mà bạn Activity
nên gửi tín hiệu đến Service
để mô tả trạng thái của nó.
Trong trường hợp nhiều người Activity
, hãy nhớ một cái Activity
đi vào nền trước, sau đó một cái khác đi vào nền trước.
Vì vậy, tình huống sẽ là: *
Activity1 -- send --> Signal:OFF
Activity2 -- send --> Signal:ON
Các Service
/ Application
sẽ chỉ đơn giản là hãy tiếp tục nghe những tín hiệu và hành động phù hợp.
Mã (TLDR)
Bạn Service
phải thực hiện một BroadcastReceiver
để lắng nghe tín hiệu.
this.localBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// received data if Activity is on / off
}
}
public static final IntentFilter SIGNAL_FILTER = new IntentFilter("com.you.yourapp.MY_SIGNAL")
Đăng ký Receiver
tạiService::onCreate()
@Override
protected void onCreate() {
LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(this.localBroadcastReceiver, SIGNAL_FILTER);
}
Hủy đăng ký nó trong Service::onDestroy()
@Override
protected void onDestroy() {
// I'm dead, no need to listen to anything anymore.
LocalBroadcastManager.getInstance(getApplicationContext()).unregisterReceiver(this.localBroadcastReceiver);
}
Bây giờ bạn Activity
phải truyền đạt trạng thái của họ.
Trong Activity::onResume()
Intent intent = new Intent();
intent.setAction(SomeActivity.SIGNAL_FILTER); // put ON boolean in intent
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
Trong Activity::onPause()
Intent intent = new Intent();
intent.setAction(SomeActivity.SIGNAL_FILTER); // put OFF boolean in intent
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
Một tình huống rất, rất phổ biến
Nhà phát triển: Tôi muốn gửi dữ liệu từ tôi
Service
và cập nhậtActivity
. Làm cách nào để kiểm tra xem cáiActivity
này có ở phía trước không?
Thường không cần phải kiểm tra xem Activity
có ở phía trước hay không. Chỉ cần gửi dữ liệu LocalBroadcastManager
từ của bạn Service
. Nếu Activity
là trên, sau đó nó sẽ đáp ứng và hành động.
Đối với tình huống rất phổ biến này, người Service
trở thành người gửi và Activity
thực hiện BroadcastReceiver
.
Vì vậy, tạo một Receiver
trong của bạn Activity
. Đăng ký onResume()
và không đăng ký onPause()
. Không cần phải sử dụng các phương pháp vòng đời khác .
Xác định Receiver
hành vi trong onReceive()
(cập nhật ListView, làm điều này, làm điều đó, ...).
Bằng cách này, Activity
ý chí chỉ lắng nghe nếu nó ở phía trước và sẽ không có gì xảy ra nếu nó ở phía sau hoặc bị phá hủy.
Trong trường hợp nhiều người Activity
, bất cứ ai Activity
đang bật sẽ trả lời (nếu họ cũng thực hiện Receiver
).
Nếu tất cả đều ở trong nền, không ai sẽ phản hồi và tín hiệu sẽ bị mất.
Gửi dữ liệu từ Service
thông qua Intent
(xem mã ở trên) bằng cách chỉ định ID tín hiệu.
fun isAppInForeground(): Boolean {
val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager ?: return false
val appProcesses = activityManager.runningAppProcesses ?: return false
val packageName = packageName
for (appProcess in appProcesses) {
if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND && appProcess.processName == packageName) {
return true
}
}
return false
}
Không có câu trả lời nào phù hợp với trường hợp cụ thể nếu bạn muốn biết liệu một hoạt động cụ thể có ở trong khu vực không và nếu bạn là SDK mà không truy cập trực tiếp vào Ứng dụng. Đối với tôi, tôi đang ở trong chủ đề nền khi vừa nhận được thông báo đẩy cho một tin nhắn trò chuyện mới và chỉ muốn hiển thị thông báo hệ thống nếu màn hình trò chuyện không ở phía trước.
Sử dụng ActivityLifecycleCallbacks
điều đó như được khuyến nghị trong các câu trả lời khác, tôi đã tạo ra một lớp sử dụng nhỏ chứa logic để xem MyActivity
có ở trong Tiền cảnh hay không.
class MyActivityMonitor(context: Context) : Application.ActivityLifecycleCallbacks {
private var isMyActivityInForeground = false
init {
(context.applicationContext as Application).registerActivityLifecycleCallbacks(this)
}
fun isMyActivityForeground() = isMyActivityInForeground
override fun onActivityPaused(activity: Activity?) {
if (activity is MyActivity) {
isMyActivityInForeground = false
}
}
override fun onActivityResumed(activity: Activity?) {
if (activity is MyActivity) {
isMyActivityInForeground = true
}
}
}
Trong các hoạt động của tôi, onResume và onP Because tôi viết một boolean isVisible cho SharedPrefences.
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
Editor editor = sharedPrefs.edit();
editor.putBoolean("visible", false);
editor.commit();
Và đọc nó ở nơi khác khi cần thông qua,
// Show a Toast Notification if App is not visible (ie in background. Not running, etc)
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
if(!sharedPrefs.getBoolean("visible", true)){...}
Có thể không thanh lịch, nhưng nó hoạt động với tôi ...
Có thể đã quá muộn để trả lời nhưng nếu ai đó đến thăm thì đây là giải pháp tôi đề xuất, Lý do một ứng dụng muốn biết trạng thái của nó ở chế độ nền hoặc sắp tới có thể là rất nhiều, một vài là, 1. Để hiển thị bánh mì nướng và thông báo khi người dùng ở trong BG. 2.Để thực hiện một số tác vụ cho người dùng lần đầu tiên đến từ BG, như thăm dò ý kiến, vẽ lại, v.v.
Giải pháp của Idolon và những người khác chăm sóc phần đầu tiên, nhưng không dành cho phần thứ hai. Nếu có nhiều hoạt động trong ứng dụng của bạn và người dùng đang chuyển đổi giữa chúng, thì khi bạn ở hoạt động thứ hai, cờ hiển thị sẽ sai. Vì vậy, nó không thể được sử dụng một cách xác định.
Tôi đã làm một cái gì đó được đề xuất bởi CommonsWare, "Nếu Dịch vụ xác định rằng không có hoạt động nào hiển thị và vẫn duy trì như vậy trong một khoảng thời gian , hãy dừng truyền dữ liệu tại điểm dừng logic tiếp theo."
Dòng in đậm rất quan trọng và điều này có thể được sử dụng để đạt được mục thứ hai. Vì vậy, những gì tôi làm là một khi tôi nhận được onActivityPaused (), đừng thay đổi trực tiếp thành false, thay vào đó là bộ đếm thời gian 3 giây (đó là mức tối đa mà hoạt động tiếp theo sẽ được khởi chạy) và nếu không có onActivityResumed ( ) gọi trong 3 giây tiếp theo, thay đổi hiển thị thành sai. Tương tự như vậy trong onActivityResumed () nếu có bộ đếm thời gian thì tôi hủy nó. Để tổng hợp, hiển thị trở thành isAppInBackground.
Xin lỗi không thể sao chép-dán mã ...
Tôi muốn khuyên bạn nên sử dụng một cách khác để làm điều này.
Tôi đoán bạn muốn hiển thị màn hình khởi động trong khi chương trình đang bắt đầu, nếu nó đã chạy trong phần phụ trợ, đừng hiển thị nó.
Ứng dụng của bạn có thể liên tục ghi thời gian hiện tại vào một tệp cụ thể. Trong khi ứng dụng của bạn đang bắt đầu, hãy kiểm tra dấu thời gian cuối cùng, nếu current_time-last_time> phạm vi thời gian bạn chỉ định để viết thời gian gần nhất, điều đó có nghĩa là ứng dụng của bạn bị dừng, do chính hệ thống hoặc người dùng tự giết.