अगर एंड्रॉइड ऐप अग्रभूमि में चल रहा है तो मैं कैसे बता सकता हूं?


83

मैं अपने एंड्रॉइड ऐप में एक स्टेटस बार नोटिफिकेशन कर रहा हूं जो कि c2dm द्वारा ट्रिगर किया गया है। यदि ऐप चल रहा है तो मैं अधिसूचना प्रदर्शित नहीं करना चाहता। यदि एप्लिकेशन चल रहा है और अग्रभूमि में है तो आप कैसे निर्धारित करते हैं?



यह एक ऐसा ही प्रश्न है ... हालाँकि मैंने onStart / onStop पर एक ध्वज की कोशिश की थी और यह काम नहीं किया। मुझे अब भी स्टॉप / स्टार्ट और पॉज़ / रिज्यूम के बीच अंतर नहीं मिलता है।
एंड्रयू थॉमस

1
आपको इस समाधान का उपयोग करना चाहिए: stackoverflow.com/questions/3667022/…
Informatic0re

एपीआई 16 के बाद से एक्टिविटी
मैनजर

लाइब्रेरी संस्करण 26 का समर्थन करने के बाद से आपको बस जब भी आप चाहते हैं, तो ProcessLifecycleOwner को क्वेरी करना होगा। Check stackoverflow.com/a/52678290/6600000
कीवन एस्बती

जवाबों:


55

की तरह एक वैश्विक चर बनाने private boolean mIsInForegroundMode;और एक आवंटित falseमें मूल्य onPause()और एक trueमें मूल्य onResume()

नमूना कोड:

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: हाँ, यह है। लेकिन जब भी कोई परिवर्तन होता है, तो हम इस चर को पास करने के लिए स्वतंत्र होते हैं, उदाहरण के लिए प्राथमिकताएँ या डेटाबेस।
व्रोकलाई

19
@ पूरी तरह से लेकिन एक ही ऐप के भीतर गतिविधियों के माध्यम से स्विच करते समय आपका वेरिएबल True / False / True बहुत कुछ हो जाएगा। इसका मतलब है कि जब आपका ऐप फोरग्राउंड खो देता है तो आपको उसका पता लगाने के लिए हिस्टैरिसीस होना चाहिए।
रादु

10
यह सबसे अच्छा उपाय नहीं है। नीचे @Gadenkan समाधान की जाँच करें।
फेलिप लीमा

यह सरल परिदृश्यों के लिए काम करता है, लेकिन यदि आपके पास अपनी गतिविधि पर onActivityResult () जटिल है। मैं एक पृष्ठभूमि सेवा चलाना चाहता हूं यदि और केवल तभी जब मेरे ऐप की सभी गतिविधियां पृष्ठभूमि में हैं, और यह समाधान ऊपर कम हो जाता है।
जोश

1
@Tima आप इसे सभी गतिविधियों के लिए उपलब्ध बनाने के लिए चाहते हैं, आप MyOwnActivity अंदर बना सकते हैं एक नया MyOwnActivity फैली AppCompatActivity ... फिर, दोनों onResume () / onPause () ओवरराइड, और अंत में आप फैली तुम सब MyOwnActivity से बजाय गतिविधियों एप्लिकेशन AppCompatActivity। समस्या सुलझ गयी। ; )
इलियटचिंग

112

वैकल्पिक रूप से, आप विधि ActivityManagerद्वारा चलाए जा रहे कार्यों की जांच कर सकते हैं getRunningTasks। फिर दिए गए कार्यों की सूची में पहले कार्य (अग्रभूमि में कार्य) के साथ जांचें, यदि यह आपका कार्य है।
यहाँ कोड उदाहरण है:

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
    }

}

और उपरोक्त कोड में विधि को चलाने में सक्षम होने के लिए मैनिफ़ेस्टGET_TASKS . xml फ़ाइल में अनुमति जोड़ना न भूलें getRunningTasks():

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

p / s: यदि इस तरह से सहमत हैं, तो कृपया ध्यान दें कि यह अनुमति अब पदावनत है।


24
यदि आप इस कोड का उपयोग करना चाहते हैं, तो न भूलें <उपयोग-अनुमति Android: name = "android.permission.GET_TASKS" />
लक्ष्मण

13
नाइटपिक्स: रिटर्निंग toString()अ स्ट्रींग पर कॉल getPackageName()करना निरर्थक है। इसके अलावा, जैसा कि हम केवल पहले कार्य में रुचि रखते हैं getRunningTasks(), हम 1इसके बजाय पास कर सकते हैं Integer.MAX_VALUE
Jonik

14
नोट: यह विधि केवल डिबगिंग और कार्य प्रबंधन उपयोगकर्ता इंटरफ़ेस को प्रस्तुत करने के लिए है। किसी अनुप्रयोग में मुख्य तर्क के लिए इसका उपयोग कभी नहीं किया जाना चाहिए, जैसे कि यहां मिली जानकारी के आधार पर विभिन्न व्यवहारों के बीच निर्णय लेना। इस तरह के उपयोग समर्थित नहीं हैं, और भविष्य में होने की संभावना है। उदाहरण के लिए, यदि एक ही समय में कई एप्लिकेशन सक्रिय रूप से चल सकते हैं, तो नियंत्रण प्रवाह के प्रयोजनों के लिए यहां डेटा के अर्थ के बारे में की गई धारणाएं गलत होंगी।
Informatic0re

5
दुर्भाग्यवश, Android L (API 20) के बाद से getRunningTasks () को हटा दिया गया है। एल के रूप में, यह विधि अब तीसरे पक्ष के अनुप्रयोगों के लिए उपलब्ध नहीं है: दस्तावेज़-केंद्रित रिकेट्स की शुरूआत का मतलब है कि यह व्यक्ति की जानकारी कॉलर को लीक कर सकता है। पीछे की संगतता के लिए, यह अभी भी अपने डेटा का एक छोटा सबसेट लौटाएगा: कम से कम कॉलर के स्वयं के कार्य, और संभवतः घर जैसे कुछ अन्य कार्य जो संवेदनशील नहीं होने के लिए जाने जाते हैं।
सैम लू

2
संभवत: यदि यह केवल कॉलर के कार्यों को दिखाता है, तो पहला कार्य और शीर्ष गतिविधि हमेशा आपकी होगी, जिसका अर्थ यह हमेशा सही पोस्ट-लॉलीपॉप लौटाएगा।
माइक हॉलर

46

यह एक बहुत पुरानी पोस्ट है लेकिन अभी भी काफी प्रासंगिक है। उपरोक्त स्वीकृत समाधान काम कर सकता है लेकिन गलत है।जैसा कि डायने हैकॉर्न ने लिखा है:

ये एपीआई अपने यूआई प्रवाह को आधार बनाने के लिए अनुप्रयोगों के लिए नहीं हैं, लेकिन उन चीजों को करने के लिए जैसे उपयोगकर्ता को चल रहे एप्लिकेशन, या एक कार्य प्रबंधक, या इस तरह से दिखाते हैं।

हाँ इन बातों के लिए स्मृति में रखी गई एक सूची है। हालाँकि, यह एक अन्य प्रक्रिया में बंद है, आपके द्वारा अलग से चल रहे थ्रेड्स द्वारा प्रबंधित किया जाता है, और कुछ ऐसा नहीं है जिस पर आप (a) सही निर्णय लेने के लिए समय में देख सकते हैं (b) आपके पास लौटने के समय तक एक सुसंगत तस्वीर है। प्लस "जाने के लिए" अगली "गतिविधि के बारे में निर्णय हमेशा उस बिंदु पर किया जाता है जहां स्विच होना है, और यह उस सटीक बिंदु तक नहीं है (जहां गतिविधि राज्य संक्षेप में स्विच करने के लिए बंद है) कि हम वास्तव में इस तरह के लिए जानते हैं कि अगली चीज क्या होगी।

और यहां के कार्यान्वयन और वैश्विक व्यवहार भविष्य में समान रहने की गारंटी नहीं है।

सही समाधान को लागू करना है: एक्टिविटीलाइफ साइकल कॉलबैक

यह मूल रूप से एक एप्लिकेशन क्लास की जरूरत है और ऐप में आपकी गतिविधियों की स्थिति की पहचान करने के लिए हैंडलर को वहां सेट किया जा सकता है।


7
यहाँ एक उदाहरण है कि इसका उपयोग कैसे किया जाता है baroqueworksdev.blogspot.com/2012/12/…
कालोवन रूससे

2
मुझे लगता है कि यह सबसे अच्छा समाधान है और शायद भविष्य में नहीं टूटेगा। आश्चर्य है कि इसे पर्याप्त वोट क्यों नहीं मिले।
रोहन कंडवाल

2
यदि आप एक उदाहरण कोड लिखते हैं, तो आपको अधिक वोट मिलेंगे क्योंकि कुछ लोग उदाहरण के बिना उत्तर छोड़ देते हैं ... लेकिन यह सबसे अच्छा समाधान है ...
समन सालेह

यह स्वीकार किए गए उत्तर में ओवरराइडिंग onPauseऔर onResumeविधि से अलग कैसे है ?
सैतामा

24

जैसा कि विनय कहते हैं, शायद सबसे अच्छा समाधान (नए एंड्रॉइड संस्करणों का समर्थन करने के लिए, 14+) वर्ग कार्यान्वयन ActivityLifecycleCallbacksमें उपयोग Applicationकरना है।

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

और आवेदन onCreate()विधि में:

registerActivityLifecycleCallbacks(new ApplicationLifecycleManager());

तब ApplicationLifecycleManager.isAppVisible()या ApplicationLifecycleManager.isAppInForeground()इच्छित स्थिति को जानने के लिए उपयोग किया जाएगा।


यह केवल isAppV अदृश्य () के साथ काम करेगा। यदि आप ऐप को बंद करते हैं, तो अग्रभूमि में भेजें, इसका कोई प्रभाव नहीं होगा
AlwaysConfused

19

एपीआई 16 के बाद से आप इसे इस तरह से कर सकते हैं:

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

कुशल समाधान। धन्यवाद :)
म.द सजदुल करीम

बहुत अच्छा समाधान है। कोई अनुमति की आवश्यकता नहीं है।
उपयोगकर्ता 3144836

बहुत बढ़िया! मैं टास्क सूची का उपयोग कर रहा था लेकिन इसके लिए GAS TASK की आवश्यकता है .. वास्तव में इसकी सराहना करें!
हेक्सागोड

15

FYI करें, यदि आप गैडेनकॉन समाधान का उपयोग करते हैं (जो बहुत अच्छा है !!) जोड़ना मत भूलना

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

प्रकट करने के लिए।


9
एंड्रॉइड लॉलीपॉप में इस अनुमति को पदावनत किया गया है
मुसना

14

गैडेनकॉन के समाधान के संस्करण को थोड़ा साफ किया । इसे किसी भी गतिविधि, या शायद अपने सभी गतिविधियों के लिए एक आधार वर्ग रखें।

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

कॉल करने में सक्षम होने के लिए getRunningTasks(), आपको इसे अपने में जोड़ना होगा AndroidManifest.xml:

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

ध्यान दें कि ActivityManager.getRunningTasks() जवादोक क्या कहता है:

नोट: यह विधि केवल डीबगिंग और कार्य प्रबंधन उपयोगकर्ता इंटरफ़ेस प्रस्तुत करने के लिए है। किसी अनुप्रयोग में मुख्य तर्क के लिए इसका उपयोग कभी नहीं किया जाना चाहिए, जैसे कि यहां मिली जानकारी के आधार पर विभिन्न व्यवहारों के बीच निर्णय लेना। इस तरह के उपयोग समर्थित नहीं हैं, और भविष्य में होने की संभावना है।

अपडेट (फरवरी 2015)

ध्यान दें कि एपीआई स्तर 21 में पदावनत कियाgetRunningTasks() गया था !

चूंकि LOLLIPOPयह विधि अब तृतीय पक्ष एप्लिकेशन के लिए उपलब्ध नहीं है: दस्तावेज़-केंद्रित पुनरावृत्ति की शुरुआत का अर्थ है कि यह व्यक्ति की जानकारी कॉलर को लीक कर सकता है। पीछे की संगतता के लिए, यह अभी भी अपने डेटा का एक छोटा सबसेट लौटाएगा: कम से कम कॉलर के स्वयं के कार्य, और संभवतः घर जैसे कुछ अन्य कार्य जो संवेदनशील नहीं होने के लिए जाने जाते हैं।

इसलिए जो मैंने पहले लिखा था वह और भी अधिक प्रासंगिक है:

कई मामलों में आप बेहतर समाधान के साथ आ सकते हैं। उदाहरण के लिए, में कुछ कर रही onPause()है और onResume(), शायद अपने सभी गतिविधियों के लिए एक BaseActivity में।

(यदि हम अग्रभूमि में नहीं हैं, तो हमारे मामले में हम एक ऑफ़लाइन अलर्ट गतिविधि शुरू नहीं करना चाहते हैं, इसलिए बेसएक्टिविटी में onPause()हम केवल Subscription"ऑफ़लाइन हो गए" संकेत सुनकर आरएक्सजेवा से अनसब्सक्राइब करते हैं ।)


क्या आप कृपया उस RxJava कोड का उपयोग कर सकते हैं जिसका आपने उपयोग किया है? मैं RxJava का उपयोग नहीं करना चाहता हूँ और मैं इस समय RxJava सीखने के लिए बहुत समय व्यतीत नहीं करना चाहता :(
MBH

@ बिज़ू: RxJava का उपयोग करना संभव नहीं होगा, बिना कुछ समय बिताने के बिना मूल अवधारणाओं से परिचित होना ... :-) किसी भी मामले में, यहां एक छोटा सा उदाहरण है
जोनीक

9

गैडेनकॉन के जवाब के बाद मुझे कुछ इस तरह की जरूरत पड़ी, ताकि मैं यह बता सकूं कि क्या मेरा ऐप अग्रभूमि में नहीं चल रहा है, लेकिन मुझे कुछ ऐसा चाहिए था, जो ऐप चौड़ा हो और मुझे अपने आवेदन के दौरान झंडे सेट करने / परेशान करने की आवश्यकता न हो।

गैडेनकॉन का कोड बहुत ज्यादा नाखून को सिर पर मारता था, लेकिन यह मेरे ही अंदाज में नहीं था और ऐसा लगा कि यह ख़राब हो सकता है, इसलिए मेरे ऐप में इसकी वजह से यह कम हो गया।

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

(साइड नोट: आप अभी हटा सकते हैं! यदि आप चाहते हैं कि चेक दूसरी तरह से काम करे)

हालांकि इस दृष्टिकोण के साथ आपको GET_TASKSअनुमति की आवश्यकता है ।


3

समर्थन लाइब्रेरी संस्करण 26 को प्रारंभ करके आप अनुप्रयोग वर्तमान स्थिति का निर्धारण करने के लिए ProcessLifecycleOwner का उपयोग कर सकते हैं , बस इसे अपनी निर्भरता में जोड़ें जैसे कि यहाँ वर्णित है , उदाहरण के लिए:

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
}

, अब आप क्वेरी कर सकते हैं ProcessLifecycleOwnerजब भी आप ऐप राज्य की जांच करना चाहते हैं, उदाहरण के लिए यह जांचने के लिए कि ऐप अग्रभूमि में चल रहा है या नहीं, आपको बस यह करना है:

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

1
यह सही जवाब है। बहुत से अन्य लोगों को पदावनत माना जाना चाहिए
11m0

AndroidX जावा के लिए implementation 'androidx.lifecycle:lifecycle-process:2.2.0'अपने प्रोजेक्ट ग्रेडेल में उपयोग करें।
जोनाथन

1

विभिन्न उत्तरों और टिप्पणियों के आधार पर, यहां एक अधिक इनलाइन संस्करण है जिसे आप एक सहायक वर्ग में जोड़ सकते हैं:

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

जैसा कि अन्य उत्तरों में बताया गया है कि आपको निम्नलिखित अनुमति को अपने साथ जोड़ना होगा AndroidManifest.xml

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

Android लॉलीपॉप में इस अनुमति को पदावनत किया गया है
मुसना

1

मैं यह करना चाहूंगा कि ऐसा करने का एक सुरक्षित तरीका है - यह जाँचने की तुलना में कि क्या आपका ऐप नोटिफिकेशन बनाने से पहले बैकग्राउंड में है - क्रमशः ब्रॉडकास्ट रिसीवर ऑनपॉज () और ऑनस्क्यूम () पर डिसेबल करना है।

यह विधि आपको वास्तविक एप्लिकेशन लॉजिक में अधिक नियंत्रण प्रदान करती है और भविष्य में बदलने की संभावना नहीं है।

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

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

1

मुझे यह जांचने के लिए अधिक सरल और सटीक तरीका मिला कि क्या एप्लिकेशन फोरग्राउंड या बैकग्राउंड में गतिविधियों को मैप करने से बूलियन तक है।

यहां पूरी तरह से जाँच करें


1

यहाँ @ user2690455 द्वारा ऊपर वर्णित अच्छे सरल समाधान के लिए कोड है। हालाँकि यह थोड़ा सा दिखता है, लेकिन आप देखेंगे कि यह वास्तव में काफी हल्का है

मेरे मामले में हम AppCompatActivity का भी उपयोग करते हैं, इसलिए मेरे पास 2 आधार कक्षाएं होनी चाहिए।

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

यह तभी उपयोगी है जब आप अपनी गतिविधि शुरू होने पर कुछ कार्रवाई करना चाहते हैं और इसकी जांच करना चाहते हैं कि क्या ऐप अग्रभूमि या पृष्ठभूमि में है।

गतिविधि प्रबंधक का उपयोग करने के बजाय एक सरल चाल है जिसे आप कोड के माध्यम से कर सकते हैं। यदि आप गतिविधि चक्र का बारीकी से निरीक्षण करते हैं, तो दो गतिविधियों और पृष्ठभूमि के अग्रभूमि के बीच का प्रवाह निम्नानुसार है। मान लीजिए कि A और B दो गतिविधियाँ हैं।

जब A से B में संक्रमण होता है तो A के 2. onPause () को 2. कहा जाता है। onResume () को B कहा जाता है। A का B

जब ऐप बैकग्राउंड में जाता है: 1. A के ऑनपॉज़ () को कॉल किया जाता है। A का 2. onStop () कहा जाता है

आप बस गतिविधि में एक झंडा लगाकर अपनी पृष्ठभूमि की घटना का पता लगा सकते हैं।

एक अमूर्त गतिविधि करें और इसे अपनी अन्य गतिविधियों से बढ़ाएँ, ताकि आपको जहाँ भी पृष्ठभूमि की घटना हो, आपको अन्य सभी गतिविधियों के लिए कोड पेस्ट करना पड़े।

अमूर्त गतिविधि में झंडा isAppInBackground बनाएँ।

ऑनक्रिएट () विधि: isAppInBackground = false;

ऑनपॉज़ () विधि में: isAppInBackground = false;

OnStop () विधि: isAppInBackground = true;

आपको बस अपने onResume () में जांच करने की आवश्यकता है अगर isAppInBackground सच है। n अपने ध्वज की जाँच करने के बाद फिर से isAppInBackground = false सेट करें

OnSTop () के बाद से दो गतिविधियों के बीच संक्रमण के लिए पहले को हमेशा दूसरे एक्टिविटी रिज्यूमे के बाद बुलाया जाएगा, झंडा कभी भी सही नहीं होगा और जब ऐप बैकग्राउंड में होगा, तो onPtop के तुरंत बाद गतिविधि के onStop () को कॉल किया जाएगा और इसलिए झंडा तभी सही होगा जब आप बाद में ऐप खोलें।

इस दृष्टिकोण में एक और परिदृश्य है। यदि आपकी कोई ऐप स्क्रीन पहले से खुली हुई है और आपने मोबाइल को निष्क्रिय कर दिया है तो कुछ समय बाद मोबाइल स्लीप मोड में चला जाएगा और जब आप मोबाइल को अनलॉक करेंगे, तो इसका इलाज बैकग्राउंड इवेंट में किया जाएगा।


1

यहाँ एक विधि है जिसका मैं उपयोग करता हूँ (और सहायक विधि):

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

ऐसा लगता है कि मैं दो साल पहले पोस्ट किए गए समाधान के लिए मतदान कर रहा था। एंड्रॉइड में विभिन्न सुरक्षा अपडेट के बाद यह विधि अब काम नहीं करती है।
Droid क्रिस

0

इसके लिए कोई वैश्विक कॉलबैक नहीं है, लेकिन प्रत्येक गतिविधि के लिए यह onStop () है। आप एक परमाणु int के साथ गड़बड़ करने की जरूरत नहीं है। बस शुरू की गतिविधियों की संख्या के साथ एक वैश्विक int है, हर गतिविधि में इसे बढ़ाएँ () और इसे onStop () में घटाएँ।

इसका पालन करें


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 अब कोई विकल्प नहीं है - नया सुरक्षा मॉडल इसे ज्यादातर बेकार बना देता है, और इसे हटा दिया जाता है।
टोनी मारो

@AnaghHegde सिस्टम से चल रही गतिविधियों की सूची खींचकर गैडेनकान द्वारा दिए गए उत्तर को देखें।
टोनी मारो

0

यहां बताए गए पिछले दृष्टिकोण इष्टतम नहीं हैं। कार्य आधारित दृष्टिकोण के लिए एक अनुमति की आवश्यकता होती है जो वांछित नहीं हो सकती है और "बूलियन" दृष्टिकोण समवर्ती संशोधन गड़बड़ी से ग्रस्त है।

मैं जिस दृष्टिकोण का उपयोग करता हूं और जो (मेरा मानना ​​है कि) ज्यादातर मामलों में काफी अच्छा काम करता है:

AtomicInteger में गतिविधि गणना को ट्रैक करने के लिए "MainApplication" वर्ग रखें :

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

और एक आधार गतिविधि वर्ग बनाएँ जो अन्य गतिविधियों का विस्तार करे:

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

ठीक है ... लेकिन ACTIVITY_COUNT.decrementAndGet () का उपयोग करने पर विचार करें; में सक्रिय ()।
क्रिसकार्नीरो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.