पृष्ठभूमि से, मेरा मतलब है कि एप्लिकेशन की कोई भी गतिविधि वर्तमान में उपयोगकर्ता को दिखाई नहीं दे रही है?
पृष्ठभूमि से, मेरा मतलब है कि एप्लिकेशन की कोई भी गतिविधि वर्तमान में उपयोगकर्ता को दिखाई नहीं दे रही है?
जवाबों:
यह पता लगाने के कुछ तरीके हैं कि आपका एप्लिकेशन पृष्ठभूमि में चल रहा है या नहीं, लेकिन उनमें से केवल एक ही पूरी तरह से विश्वसनीय है:
सही समाधान (क्रेडिट दान , कॉमन्सवेयर और नेइटइन्स्टाईएनएन पर जाते हैं )
अपने आवेदन की दृश्यता को ट्रैक करके अपने आप का उपयोग करते हुए Activity.onPause
, Activity.onResume
तरीकों से। स्टोर "दृश्यता" की स्थिति कुछ अन्य वर्ग में। अच्छे विकल्प आपके स्वयं के कार्यान्वयन हैं Application
या Service
( इस समाधान के कुछ रूपांतर भी हैं यदि आप सेवा से गतिविधि की दृश्यता की जांच करना चाहते हैं)।
उदाहरण
कस्टम Application
वर्ग लागू करें ( isActivityVisible()
स्थिर विधि पर ध्यान दें ):
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;
}
इसमें अपना आवेदन वर्ग पंजीकृत करें AndroidManifest.xml
:
<application
android:name="your.app.package.MyApplication"
android:icon="@drawable/icon"
android:label="@string/app_name" >
जोड़े onPause
और onResume
हर के लिए Activity
परियोजना में (यदि आप करना चाहते हैं तो आप अपने गतिविधियों के लिए एक आम पूर्वज बना सकते हैं, लेकिन अगर अपनी गतिविधि को पहले से ही से बढ़ा दिया गया है MapActivity
/ ListActivity
आदि आप अभी भी हाथ से निम्नलिखित लिखने की ज़रूरत):
@Override
protected void onResume() {
super.onResume();
MyApplication.activityResumed();
}
@Override
protected void onPause() {
super.onPause();
MyApplication.activityPaused();
}
अद्यतन
गतिविधिलिफ़साइकलबैक को एपीआई स्तर 14 (एंड्रॉइड 4.0) में जोड़ा गया था। आप उन्हें ट्रैक करने के लिए उपयोग कर सकते हैं कि क्या आपके एप्लिकेशन की गतिविधि वर्तमान में उपयोगकर्ता को दिखाई दे रही है। विवरण के लिए नीचे कॉर्न्स्टल के उत्तर की जाँच करें।
गलत
मैं निम्नलिखित समाधान का सुझाव देता था:
आप वर्तमान में अग्रभूमि / पृष्ठभूमि अनुप्रयोग का पता लगा सकते हैं,
ActivityManager.getRunningAppProcesses()
जिसके साथRunningAppProcessInfo
रिकॉर्ड की एक सूची मिलती है। यह निर्धारित करने के लिए कि आपका आवेदन अग्रभूमि चेकRunningAppProcessInfo.importance
फ़ील्ड पर समानता के लिए हैRunningAppProcessInfo.IMPORTANCE_FOREGROUND
जबकिRunningAppProcessInfo.processName
आपके एप्लिकेशन पैकेज नाम के बराबर है।यदि आप
ActivityManager.getRunningAppProcesses()
अपने एप्लिकेशन UI थ्रेड से कॉल करते हैं, तो यहIMPORTANCE_FOREGROUND
आपके कार्य के लिए महत्व देगा चाहे वह वास्तव में अग्रभूमि में हो या नहीं। इसे बैकग्राउंड थ्रेड (उदाहरण के माध्यम सेAsyncTask
) में कॉल करें और यह सही परिणाम देगा।
हालांकि यह समाधान काम कर सकता है (और यह वास्तव में ज्यादातर समय काम करता है) मैं दृढ़ता से इसका उपयोग करने से परहेज करने की सलाह देता हूं। और यहाँ क्यों है। जैसा कि डायने हैकॉर्न ने लिखा है :
ये एपीआई अपने यूआई प्रवाह को आधार बनाने के लिए अनुप्रयोगों के लिए नहीं हैं, लेकिन ऐसा करने के लिए उपयोगकर्ता को चलने वाले एप्लिकेशन या एक कार्य प्रबंधक, या इस तरह की चीजें दिखाते हैं।
हाँ इन बातों के लिए स्मृति में रखी गई एक सूची है। हालाँकि, यह एक अन्य प्रक्रिया में बंद है, आपके द्वारा अलग से चल रहे थ्रेड्स द्वारा प्रबंधित किया जाता है, और कुछ ऐसा नहीं जिसे आप (ए) सही निर्णय लेने के लिए समय में देख सकते हैं (बी) आपके पास लौटने के समय तक एक सुसंगत तस्वीर है। प्लस "जाने के लिए" अगली "गतिविधि के बारे में निर्णय हमेशा उस बिंदु पर किया जाता है जहां स्विच होना है, और यह उस सटीक बिंदु तक नहीं है (जहां गतिविधि राज्य संक्षेप में स्विच करने के लिए बंद है) कि हम वास्तव में यह सुनिश्चित करने के लिए जानते हैं कि अगली चीज क्या होगी।
और यहाँ कार्यान्वयन और वैश्विक व्यवहार भविष्य में समान रहने की गारंटी नहीं है।
काश, मैंने एसओ पर जवाब पोस्ट करने से पहले इसे पढ़ा हो, लेकिन उम्मीद है कि मेरी गलती को स्वीकार करने में देर नहीं हुई होगी।
एक अन्य गलत समाधान
Droid-Fu पुस्तकालय में वर्णित एक विधि में ActivityManager.getRunningTasks
इसका उपयोग किया गया isApplicationBroughtToBackground
है। ऊपर डायने की टिप्पणी देखें और उस पद्धति का उपयोग न करें।
OnStop
अनुरोध में isActivityVisible
।
user1269737 का उत्तर ऐसा करने के लिए उचित (Google / Android अनुमोदित) तरीका है । उनके उत्तर को पढ़ें और उन्हें +1 दें।
मैं अपने मूल उत्तर को यहाँ पोस्टर्सिटी की खातिर छोड़ दूँगा। यह 2012 में सबसे अच्छा उपलब्ध था, लेकिन अब इसके लिए एंड्रॉइड का उचित समर्थन है।
कुंजी उपयोग कर रही है ActivityLifecycleCallbacks
(ध्यान दें कि इसके लिए Android API स्तर 14 (Android 4.0) की आवश्यकता है)। बस जाँच करें कि क्या रुकी गतिविधियों की संख्या शुरू की गई गतिविधियों की संख्या के बराबर है। यदि वे समान हैं, तो आपके आवेदन को पृष्ठभूमि में रखा जा रहा है। यदि अधिक आरंभिक गतिविधियाँ हैं, तो भी आपका आवेदन दिख रहा है। यदि रुकी हुई गतिविधियों की तुलना में अधिक फिर से शुरू किया जाता है, तो आपका आवेदन न केवल दिखाई देता है, बल्कि यह अग्रभूमि में भी है। 3 मुख्य राज्य हैं जो आपकी गतिविधि में हो सकते हैं, फिर: दृश्यमान और अग्रभूमि में, दृश्यमान लेकिन अग्रभूमि में नहीं, और दृश्यमान नहीं और अग्रभूमि में नहीं (अर्थात पृष्ठभूमि में)।
इस विधि के बारे में बहुत अच्छी बात यह है कि यह अतुल्यकालिक मुद्दों नहीं है getRunningTasks()
है, लेकिन आप भी हर संशोधित करने की जरूरत नहीं है Activity
में सेट / सेट किए बिना कुछ करने के लिए अपने आवेदन में onResumed()
/ onPaused()
। यह कोड की कुछ पंक्तियाँ है जो स्वयं निहित है, और यह आपके पूरे आवेदन में काम करती है। इसके अलावा, कोई फंकी परमिशन की भी जरूरत नहीं है।
MyLifecycleHandler.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());
}
}
@ मेवेज़र ने इस पद्धति के बारे में कुछ अच्छे प्रश्न पूछे हैं जिनका मैं इस उत्तर में सभी के लिए जवाब देना चाहता हूँ:
onStop()
कम स्मृति स्थितियों में नहीं कहा जाता है; कि यहाँ एक समस्या है?
नहीं के लिए डॉक्स onStop()
कहने के :
ध्यान दें कि इस विधि को कभी भी नहीं बुलाया जा सकता है, कम स्मृति स्थितियों में जहां सिस्टम में पर्याप्त मेमोरी नहीं होती है कि वह आपकी गतिविधि की प्रक्रिया को चालू रखने के बाद चालू करें () विधि कहलाती है।
यहाँ कुंजी है "अपनी गतिविधि की प्रक्रिया को चालू रखें ..." यदि यह कम स्मृति स्थिति कभी भी पहुंच जाती है, तो आपकी प्रक्रिया वास्तव में मार दी जाती है (न कि केवल आपकी गतिविधि)। इसका मतलब यह है कि बैकग्राउंडेड-नेस के लिए जाँच करने का यह तरीका अभी भी मान्य है क्योंकि a) आप वैसे भी बैकग्राउंडिंग के लिए जाँच नहीं कर सकते हैं यदि आपकी प्रक्रिया मारी गई है, और b) यदि आपकी प्रक्रिया फिर से शुरू होती है (क्योंकि एक नई गतिविधि बनती है), सदस्य चर (स्थिर या नहीं) के लिए MyLifecycleHandler
रीसेट किया जाएगा0
।
क्या यह विन्यास परिवर्तन के लिए काम करता है?
डिफ़ॉल्ट रूप से, नहीं। आपको स्पष्ट रूप से सेट करना होगा configChanges=orientation|screensize
( पहले से ही मेरी सभी परियोजनाओं में क्योंकि यह मेरी पूरी गतिविधि के लिए स्क्रीन रोटेट / रिसाइज पर नष्ट होने के लिए अवांछनीय था, इसलिए मैंने इसे कभी भी समस्याग्रस्त नहीं पाया है। (इसके लिए अपनी स्मृति को ताज़ा करने के लिए dpimka के लिए धन्यवाद)। और मुझे सही कर रहा है!)|
अपनी मैनिफ़ेस्ट फ़ाइल में किसी भी चीज़ के साथ) और कॉन्फ़िगरेशन परिवर्तन को संभालना होगा, अन्यथा आपकी गतिविधि नष्ट हो जाएगी और फिर से बनाई जाएगी। यदि आप इसे सेट नहीं करते हैं, तो आपकी गतिविधि के तरीकों को इस क्रम में बुलाया जाएगा onCreate -> onStart -> onResume -> (now rotate) -> onPause -> onStop -> onDestroy -> onCreate -> onStart -> onResume
:। जैसा कि आप देख सकते हैं, कोई ओवरलैप नहीं है (आम तौर पर, दो गतिविधियों को बहुत संक्षेप में ओवरलैप करते हैं जब दोनों के बीच स्विच करते हैं, जो कि यह पृष्ठभूमि-पता लगाने की विधि कैसे काम करती है)। इसे प्राप्त करने के लिए, आपको सेट करना होगा configChanges
ताकि आपकी गतिविधि नष्ट न हो। सौभाग्य से, मुझे सेट करना पड़ाconfigChanges
एक नोट:
जब मैंने इस उत्तर में "पृष्ठभूमि" कहा है, तो मेरा मतलब है "आपका ऐप अब दिखाई नहीं दे रहा है।" एंड्रॉइड गतिविधियां अभी तक अग्रभूमि में नहीं दिखाई दे सकती हैं (उदाहरण के लिए, यदि पारदर्शी अधिसूचना ओवरले है)। इसीलिए मैंने इस उत्तर को प्रतिबिंबित करने के लिए अद्यतन किया है।
यह जानना महत्वपूर्ण है कि एंड्रॉइड में गतिविधियों को स्विच करने के दौरान एक अजीब अंग है, जहां कुछ भी अग्रभूमि में नहीं है । इस कारण से, यदि आप जाँचते हैं कि गतिविधियों के बीच स्विच करने पर आपका एप्लिकेशन अग्रभूमि में है (उसी ऐप में), तो आपको बताया जाएगा कि आप अग्रभूमि में नहीं हैं (भले ही आपका ऐप अभी भी सक्रिय ऐप है और दिखाई दे रहा है )।
आप देख सकते हैं कि आपके ऐप अपने में अग्रभूमि में चल रही Activity
है onPause()
विधि के बाद super.onPause()
। बस अजीब सी लिमो स्टेट याद है जिसकी मैंने अभी बात की थी।
आप (यानी अगर यह पृष्ठभूमि में नहीं है) की जांच कर सकते कि आपके ऐप में दिखाई दे रहा है अपने में Activity
की onStop()
विधि के बाद super.onStop()
।
onStop()
के बाद super.onStop()
। में पृष्ठभूमि के लिए जाँच न करें onPause()
।
GOOGLE SOLUTION - एक हैक नहीं, पिछले समाधानों की तरह। ProcessLifecycleOwner 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
}
}
जावा:
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
}
}
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' }
}
}
आप लाइफसाइकल से संबंधित वास्तुकला घटकों के बारे में अधिक यहाँ पढ़ सकते हैं - https://developer.android.com/topic/lbooks/ RGBecture / lifecycle
companion object { private var foreground = false fun isForeground() : Boolean { return foreground } }
फिर आप अग्रभूमि राज्य प्राप्त कर सकते हैंArchLifecycleApp.isForeground()
The LifecycleOwner for the whole application process. Note that if your application has multiple processes, this provider does not know about other processes.
, यह multiple processes
ऐप्स के लिए काम नहीं कर रहा है, क्या कुछ एपि हैं जिन्हें हम शान से हासिल कर सकते हैं?
समर्थन लाइब्रेरी संस्करण 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
जब भी आप एप्लिकेशन स्टेट के लिए चाहें तो क्वेरी करें , उदाहरण:
//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);
एंड्रॉइड एपीआई 16 के बाद से यह जांचने का एक सरल तरीका है कि ऐप अग्रभूमि में है या नहीं। यह मूर्खतापूर्ण नहीं हो सकता है, लेकिन एंड्रॉइड पर कोई भी तरीके मूर्ख नहीं हैं। यह विधि उपयोग करने के लिए पर्याप्त है जब आपकी सेवा सर्वर से अपडेट प्राप्त करती है और यह तय करना होता है कि क्या अधिसूचना दिखाना है, या नहीं (क्योंकि यदि यूआई अग्रभूमि है, तो उपयोगकर्ता अधिसूचना के बिना अपडेट को नोटिस करेगा)।
RunningAppProcessInfo myProcess = new RunningAppProcessInfo();
ActivityManager.getMyMemoryState(myProcess);
isInBackground = myProcess.importance != RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
JobService
पता लगाने में सक्षम था कि सेवा पृष्ठभूमि में चल रही है।
आइडलोन का उत्तर त्रुटि प्रवण है और बहुत अधिक जटिल अलहदा दोहराया गया है यहां देखें कि एंड्रॉइड एप्लिकेशन अग्रभूमि में है या नहीं? और यहाँ एक पृष्ठभूमि कार्य या सेवा से वर्तमान अग्रभूमि अनुप्रयोग का निर्धारण
अधिक सरल दृष्टिकोण है:
सभी कार्यकलापों का विस्तार करने वाले एक बेसएक्टिविटी पर :
protected static boolean isVisible = false;
@Override
public void onResume()
{
super.onResume();
setVisible(true);
}
@Override
public void onPause()
{
super.onPause();
setVisible(false);
}
जब भी आपको यह जांचने की आवश्यकता होती है कि क्या आपकी कोई भी एप्लिकेशन गतिविधियां केवल जांच के लिए अग्रभूमि में हैं isVisible()
;
इस दृष्टिकोण को समझने के लिए, साइड-बाय-साइड गतिविधि जीवनचक्र के इस उत्तर की जाँच करें: गतिविधि साइड-बाय-साइड जीवनचक्र
Idolon's answer is error prone
- दुर्भाग्य से मुझे आपसे सहमत होना होगा। Google समूह में डायने हैकॉर्न की टिप्पणी के आधार पर मैंने अपना उत्तर अपडेट किया है। विवरण के लिए कृपया इसे जांचें।
onPause
, onStop
और न ही onResume
घटना कहा जाता है। तो अगर आप इन घटनाओं में से कोई भी निकाल दिया जाता है तो आप क्या करते हैं ?!
मैंने Application.ActivityLifecycleCallbacks और कई अन्य का उपयोग करने वाले अनुशंसित समाधान की कोशिश की , लेकिन वे उम्मीद के मुताबिक काम नहीं कर पाए। सर्ज के लिए धन्यवाद , मैं एक बहुत ही आसान और सरल समाधान के साथ आया जिसका मैं नीचे वर्णन कर रहा हूं।
वे समाधान की कुंजी यह समझने का तथ्य है कि अगर हमारे पास एक्टिवा और एक्टीबीबी है, और हम एक्टिवा से एक्टिविबी कहते हैं (और कॉल नहीं करते हैं
ActivityA.finish
), तो एक्टिवा से पहले एक्टिविटीबी कोonStart()
कॉल किया जाएगा ।onStop()
यह भी मुख्य अंतर है onStop()
और onPause()
मैंने जो लेख पढ़ा, उसमें किसी ने भी इसका उल्लेख नहीं किया।
तो इस गतिविधि के जीवनचक्र के व्यवहार के आधार पर, आप बस यह गिन सकते हैं कि कितनी बार किया onStart()
और onPause()
अपने कार्यक्रम में बुलाया। ध्यान दें कि प्रत्येक के लिए Activity
अपने कार्यक्रम की, आप को ओवरराइड चाहिए onStart()
और onStop()
आदेश में, वेतन वृद्धि / कमी स्थिर चर गिनती के लिए इस्तेमाल करने के लिए। नीचे इस तर्क को लागू करने वाला कोड है। ध्यान दें कि मैं एक वर्ग का उपयोग कर रहा हूं जो विस्तारित होता है Application
, इसलिए Manifest.xml
आवेदन टैग के अंदर घोषित करना न भूलें : android:name=".Utilities"
हालांकि, यह एक सरल कस्टम वर्ग का उपयोग करके भी लागू किया जा सकता है।
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--;
}
}
अब हमारे कार्यक्रम के प्रत्येक गतिविधि पर, हम ओवरराइड करना चाहिए onStart()
और onStop()
नीचे के रूप में दिखाया गया है और वेतन वृद्धि / कमी:
@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();
}
इस तर्क के साथ, 2 संभावित मामले हैं:
stateCounter = 0
: रोकी गई संख्या शुरू की गई गतिविधियों की संख्या के बराबर है, जिसका अर्थ है कि आवेदन पृष्ठभूमि पर चल रहा है।stateCounter > 0
: प्रारंभ की संख्या रुकी हुई संख्या से बड़ी है, जिसका अर्थ है कि एप्लिकेशन अग्रभूमि पर चल रहा है।सूचना: stateCounter < 0
इसका मतलब होगा कि शुरू होने के बजाय अधिक रुकी हुई गतिविधियाँ हैं, जो असंभव है। यदि आप इस मामले का सामना करते हैं, तो इसका मतलब है कि आप उस काउंटर को नहीं बढ़ा रहे हैं / घटा रहे हैं जैसा आपको चाहिए।
तुम जाने के लिए तैयार हो। यदि आपका एप्लिकेशन बैकग्राउंड में है, तो आपको जांचना चाहिए onStop()
।
if(Utilities.isApplicationOnBackground()) …
करने के लिए Utilities
। क्योंकि अन्यथा केवल एक विशिष्ट गतिविधि घटना पर प्रतिक्रिया करेगी।
कोई तरीका नहीं है, आप में से कोई भी इसे ट्रैक कर रहा है, यह निर्धारित करने के लिए कि आपकी कोई गतिविधि दिखाई दे रही है या नहीं। शायद आपको एक नया StackOverflow प्रश्न पूछने पर विचार करना चाहिए, यह समझाते हुए कि यह आप एक उपयोगकर्ता अनुभव से क्या हासिल करने की कोशिश कर रहे हैं, इसलिए हम शायद आपको वैकल्पिक कार्यान्वयन विचार दे सकते हैं।
Service
। यदि ऐसा है, तो अपनी गतिविधियों को सेवा को सूचित करें क्योंकि वे दिखाई देते हैं और गायब हो जाते हैं। यदि यह Service
निर्धारित करता है कि कोई गतिविधियाँ दिखाई नहीं दे रही हैं, और यह कुछ समय के लिए इस तरह से बनी हुई है, तो अगले तार्किक रोक बिंदु पर डेटा स्थानांतरण को रोक दें। हां, इसके लिए आपकी प्रत्येक गतिविधि के लिए कोड की आवश्यकता होगी, लेकिन अभी, यह अपरिहार्य AFAIK है।
MyActivityClass
से इनहेरिट Activity
और जीवन चक्र के तरीकों को लागू करने, और अपने सभी गतिविधियों से विरासत बनाने के MyActivityClass
। यह PreferenceActivity
या MapActivity
इसके लिए कोई काम नहीं करेगा ( इस प्रश्न को देखें )
ऐप पृष्ठभूमि में है या नहीं, इसका पता लगाने के लिए आप ComponentCallbacks2 का उपयोग कर सकते हैं । BTW यह कॉलबैक केवल एपीआई स्तर 14 (आइसक्रीम सैंडविच) और इसके बाद के संस्करण में उपलब्ध है।
आपको विधि के लिए एक कॉल मिलेगा:
public abstract void onTrimMemory (int level)
यदि स्तर है ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
तो ऐप पृष्ठभूमि में है।
तुम एक करने के लिए इस इंटरफ़ेस को लागू कर सकते हैं activity
, service
आदि
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
}
}
}
@Cornstalks पर निर्माण उपयोगी सुविधाओं के एक जोड़े को शामिल करने के लिए उत्तर देता है।
अतिरिक्त विशेषताएँ:
App.java
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(AppLifecycleHandler.getInstance());
}
}
AppLifecycleHandler.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;
}
}
सबसे अच्छा समाधान मैं टाइमर्स का उपयोग करता हूं।
आपने ऑनपॉज़ () में एक टाइमर शुरू किया है और ऑनस्क्यूम () में उसी टाइमर को रद्द कर दिया है, टाइमर का 1 उदाहरण है (आमतौर पर एप्लिकेशन वर्ग में परिभाषित किया गया है)। टाइमर स्वयं 2 सेकंड (या जो भी अंतराल आपको उपयुक्त लगता है) के बाद एक रननेबल चलाने के लिए सेट किया गया है, जब टाइमर फायर करता है तो आप पृष्ठभूमि में होने के नाते आवेदन को चिह्नित करते हुए एक ध्वज सेट करते हैं।
टाइमर को रद्द करने से पहले onResume () विधि में, आप किसी भी स्टार्टअप ऑपरेशन (जैसे डाउनलोड शुरू करने या स्थान सेवाओं को सक्षम करने) के लिए पृष्ठभूमि ध्वज को क्वेरी कर सकते हैं।
यह समाधान आपको बैक स्टैक पर कई गतिविधियाँ करने की अनुमति देता है, और इसे लागू करने के लिए किसी भी अनुमति की आवश्यकता नहीं होती है।
यदि आप किसी ईवेंट बस का भी उपयोग करते हैं, तो यह समाधान अच्छी तरह से काम करता है, क्योंकि आपका टाइमर किसी ईवेंट को आग लगा सकता है और आपके ऐप के विभिन्न भागों के अनुसार प्रतिक्रिया दे सकता है।
यदि आप डेवलपर सेटिंग्स को चालू करते हैं, तो "एक्टीविटीज़ न रखें" - केवल बनाए गए एक्टिविटीज़ की गिनती की जाँच करें पर्याप्त नहीं है। आपको यह भी देखना होगा कि SaveInstanceState है । मेरा कस्टम तरीका है ApplicationRunning () चेक है android app चल रहा है:
यहाँ मेरा काम कोड:
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) { }
}
एकमात्र सही समाधान:
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) {
...
}
}
}
CommonsWare और Key ने जो कहा है, उस पर गुल्लक करने के लिए, आप शायद अनुप्रयोग वर्ग का विस्तार कर सकते हैं और आपकी सभी गतिविधियाँ कॉल कर सकती हैं जो उनके ऑनपॉन्ज / onResume विधियों पर हैं। यह आपको यह जानने की अनुमति देगा कि कौन सी गतिविधि (ies) दिखाई दे रही है, लेकिन इसे शायद बेहतर तरीके से संभाला जा सकता है।
क्या आप इसके बारे में विस्तार से बता सकते हैं कि आपके मन में क्या है? जब आप कहते हैं कि पृष्ठभूमि में चल रहा है, तो क्या इसका मतलब यह है कि आपका आवेदन अभी भी स्मृति में है, हालांकि यह वर्तमान में स्क्रीन पर नहीं है? क्या आपने सेवाओं का उपयोग अपने ऐप को प्रबंधित करने के लिए एक अधिक स्थायी तरीके के रूप में किया है जब यह ध्यान में नहीं है?
Application
है onPause()
या नहीं onResume()
।
मैंने एक्टिविटी लाइफ़ साइकल कॉलबैक का अपना कार्यान्वयन किया। मैं शर्लकअक्टिविटी का उपयोग कर रहा हूं, लेकिन सामान्य गतिविधि के लिए वर्ग काम कर सकता है।
सबसे पहले, मैं एक इंटरफ़ेस बना रहा हूँ जिसमें गतिविधियों के जीवनचक्र को ट्रैक करने के सभी तरीके हैं:
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);
}
दूसरा, मैंने इस इंटरफ़ेस को अपने एप्लिकेशन की कक्षा में लागू किया:
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());
}
}
तीसरा, मैं एक वर्ग बना रहा हूँ जो शेरलाक्टिविटी से निकला है:
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);
}
}
चौथा, सभी वर्ग जो शेरलाकिटिविटी से विस्तार करते हैं, मैंने माईशर्लोक्टक्टिविटी के लिए प्रतिस्थापित किया:
public class MainActivity extends MySherlockActivity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
अब, लॉगकैट में आप MyApplication में किए गए इंटरफ़ेस कार्यान्वयन में प्रोग्राम किए गए लॉग देखेंगे।
चूंकि यह पहले से ही उल्लेख नहीं किया गया है, मैं पाठकों को Android आर्किटेक्चर घटकों के माध्यम से उपलब्ध ProcessLifecycleOwner का पता लगाने का सुझाव दूंगा
सिस्टम अग्रभूमि और पृष्ठभूमि एप्लिकेशन के बीच अंतर करता है। (सेवा सीमाओं के प्रयोजनों के लिए पृष्ठभूमि की परिभाषा स्मृति प्रबंधन द्वारा उपयोग की जाने वाली परिभाषा से अलग है; एक ऐप पृष्ठभूमि में स्मृति प्रबंधन से संबंधित हो सकती है , लेकिन अग्रभूमि में सेवाओं को लॉन्च करने की क्षमता से संबंधित है।) एक ऐप। निम्न में से कोई भी सत्य होने पर अग्रभूमि में माना जाता है:
यदि उन स्थितियों में से कोई भी सत्य नहीं है, तो एप्लिकेशन को पृष्ठभूमि में माना जाता है।
इस पुरानी पोस्ट का एक और समाधान (उन लोगों के लिए जो इसे मदद कर सकता है):
<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();
}
}
OnActivityDestroyed फ़ंक्शन में टिप्पणी देखें।
एसडीके लक्ष्य संस्करण 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++;
}
}
आपको अपनी गतिविधियों से सेवा बंधन का उपयोग करके संपत्ति को संग्रहीत करने और उस पर कार्य करने के लिए एक साझा प्राथमिकता का उपयोग करना चाहिए । यदि आप केवल बाइंडिंग का उपयोग करते हैं, (जो कि कभी भी startService का उपयोग नहीं करता है), तो आपकी सेवा केवल तभी चलेगी जब आप इसे बाँधेंगे, (onResume और unbind onPause पर बाँधें) जो इसे केवल अग्रभूमि पर चलाएगा, और यदि आप काम करना चाहते हैं पृष्ठभूमि आप नियमित स्टार्ट स्टॉप सेवा का उपयोग कर सकते हैं।
मुझे लगता है कि यह प्रश्न अधिक स्पष्ट होना चाहिए। कब? कहाँ पे? यदि आपका ऐप बैकग्राउंड में है, तो आपकी विशिष्ट स्थिति क्या है?
मैं बस अपने तरीके से अपने समाधान का परिचय देता हूं।
मैं अपने ऐप RunningAppProcessInfo
में हर गतिविधि के onStop
तरीके में कक्षा के "महत्व" के क्षेत्र का उपयोग करके इसे प्राप्त करता हूं, जिसे केवल "महत्व" के मूल्य की जांच BaseActivity
करने के लिए onStop
विधि को लागू करने के लिए अन्य गतिविधियों के लिए प्रदान करके प्राप्त किया जा सकता है । यहाँ कोड है:
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;
}
मैं इस पृष्ठ के माध्यम से पढ़ने की सलाह देता हूं: http://developer.android.com/reference/android/app/Activity.html
संक्षेप में, आपकी गतिविधि onStop()
को कॉल किए जाने के बाद दिखाई नहीं देता है ।
onStop
; के बीच onPause
और onStop
यह दृश्यमान है , लेकिन अग्रभूमि में नहीं है ।
onStop()
है, जिसे आपने लिखा है।
onPause
जाता है जब तक कहा जाता है: एक हालिया संपादन ने आपको सही किया है।
मेरी राय में, कई उत्तर कोड के भारी भार का परिचय देते हैं और बहुत सारी जटिलता और गैर-पठनीयता लाते हैं।
जब लोग एसओ से पूछते हैं कि ए Service
और ए के बीच कैसे संवाद करना है Activity
, तो मैं आमतौर पर लोकलब्रॉडकास्टमैन का उपयोग करने की सलाह देता हूं ।
क्यों?
डॉक्स के हवाले से:
आप जानते हैं कि आप जो डेटा प्रसारित कर रहे हैं, वह आपके ऐप को नहीं छोड़ेगा, इसलिए निजी डेटा को लीक करने के बारे में चिंता करने की ज़रूरत नहीं है।
अन्य एप्लिकेशन के लिए इन प्रसारणों को अपने ऐप पर भेजना संभव नहीं है, इसलिए आपको सुरक्षा छेद होने की चिंता करने की आवश्यकता नहीं है जो वे शोषण कर सकते हैं।
यह प्रणाली के माध्यम से एक वैश्विक प्रसारण भेजने की तुलना में अधिक कुशल है।
डॉक्स में नहीं:
Activity
, Application
...विवरण
तो, आप जांचना चाहते हैं कि Activity
क्या वर्तमान में कोई भी अग्रभूमि में है। आप आमतौर पर ऐसा करते हैं Service
, या आपकी Application
कक्षा में।
इसका मतलब है, आपकी Activity
वस्तुएँ एक सिग्नल का प्रेषक बन जाती हैं (मैं चालू / बंद हूँ)। Service
दूसरी ओर आपका , बन जाता है Receiver
।
कर रहे हैं दो , जिसमें देर में अपनाActivity
आपको बताता है कि अगर यह अग्रभूमि में या पृष्ठभूमि (हाँ केवल दो ... नहीं 6) में जा रहा है।
जब Activity
अग्रभूमि में जाता है, तो onResume()
विधि चालू हो जाती है (जिसे बाद में भी कहा जाता है onCreate()
)।
जब Activity
पीठ में जाता है, onPause()
कहा जाता है।
ये ऐसे क्षण हैं जिनमें आपको अपने राज्य का वर्णन Activity
करने के लिए संकेत भेजना चाहिए Service
।
कई के मामले में Activity
, एक याद हैActivity
पहले एक पृष्ठभूमि में जाना , फिर एक और एक अग्रभूमि में आता है।
तो स्थिति यह होगी: *
Activity1 -- send --> Signal:OFF
Activity2 -- send --> Signal:ON
Service
/ Application
बस उन संकेतों में सुनते रहें और उसके अनुसार कार्य करेंगे।
कोड (TLDR)
संकेतों को सुनने के लिए आपका आदेश Service
लागू होना चाहिए BroadcastReceiver
।
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")
रजिस्टर Receiver
मेंService::onCreate()
@Override
protected void onCreate() {
LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(this.localBroadcastReceiver, SIGNAL_FILTER);
}
इसमें अन-रजिस्टर करें Service::onDestroy()
@Override
protected void onDestroy() {
// I'm dead, no need to listen to anything anymore.
LocalBroadcastManager.getInstance(getApplicationContext()).unregisterReceiver(this.localBroadcastReceiver);
}
अब आपके Activity
राज्य का संचार होना चाहिए।
में Activity::onResume()
Intent intent = new Intent();
intent.setAction(SomeActivity.SIGNAL_FILTER); // put ON boolean in intent
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
में Activity::onPause()
Intent intent = new Intent();
intent.setAction(SomeActivity.SIGNAL_FILTER); // put OFF boolean in intent
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
एक बहुत ही सामान्य स्थिति
डेवलपर: मैं अपने से डेटा भेजना चाहता हूं
Service
और अपडेट करना चाहता हूंActivity
। अगर मैंActivity
अग्रभूमि में है तो मैं कैसे जांच करूं ?
आमतौर पर यह जांचने की आवश्यकता नहीं Activity
है कि अग्रभूमि में है या नहीं। बस LocalBroadcastManager
अपने माध्यम से डेटा भेजें Service
। यदि Activity
चालू है, तो यह प्रतिक्रिया देगा और कार्य करेगा।
इस बहुत ही सामान्य स्थिति के लिए, Service
प्रेषक बन जाता है और आम Activity
लागू होता है BroadcastReceiver
।
तो, एक बनाने के Receiver
अपने में Activity
। इसे रजिस्टर करें onResume()
और इसे अन-रजिस्टर करें onPause()
। अन्य जीवन-चक्र विधियों का उपयोग करने की कोई आवश्यकता नहीं है ।
Receiver
व्यवहार को परिभाषित करें onReceive()
(सूची दृश्य को अपडेट करें, ऐसा करें, ऐसा करें, ...)।
इस तरह से यह Activity
केवल तभी सुनेगा जब यह अग्रभूमि में हो और कुछ भी नहीं होगा यदि यह पीछे है या नष्ट हो गया है।
एकाधिक के मामले में Activity
, जो भी Activity
जवाब देगा (यदि वे भी लागू होते हैं Receiver
)।
यदि सभी पृष्ठभूमि में हैं, तो कोई भी प्रतिक्रिया नहीं करेगा और संकेत बस खो जाएगा।
से डेटा भेजने Service
के माध्यम से Intent
(ऊपर कोड देखें) संकेत आईडी निर्दिष्ट करने के द्वारा।
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
}
यदि कोई विशेष गतिविधि फ़ोरग्राउंड में है और यदि आप SDK हैं, तो एप्लिकेशन को सीधे पहुंच के बिना यदि आपको पता चल जाए कि आपके द्वारा देखे गए उत्तरों में से किसी ने भी विशिष्ट मामले को फिट नहीं किया है। मेरे लिए मैं बैकग्राउंड थ्रेड में था, बस एक नए चैट संदेश के लिए एक पुश नोटिफिकेशन प्राप्त किया और केवल एक सिस्टम नोटिफिकेशन प्रदर्शित करना चाहता था यदि चैट स्क्रीन अग्रभूमि में नहीं है।
का उपयोग करते हुए ActivityLifecycleCallbacks
जैसा कि अन्य उत्तरों में सुझाया गया है, मैंने एक छोटा सा उपयोग वर्ग बनाया है जो तर्क देता है कि MyActivity
फोरग्राउंड में है या नहीं।
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
}
}
}
अपनी गतिविधियों में onResume और onPause मैं SharedPrefences में एक अदृश्य बूलियन लिखता हूं।
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
Editor editor = sharedPrefs.edit();
editor.putBoolean("visible", false);
editor.commit();
और जरूरत पड़ने पर इसे कहीं और पढ़ें।
// 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)){...}
शायद सुरुचिपूर्ण नहीं है, लेकिन यह मेरे लिए काम करता है ...
इसका उत्तर देने में बहुत देर हो सकती है लेकिन अगर कोई व्यक्ति आता है, तो यहां मैं जो समाधान सुझाता हूं, उसका कारण (ऐप) जानना चाहता है कि यह पृष्ठभूमि में होने की स्थिति है या अग्रभूमि में आने वाले कई हो सकते हैं, कुछ हैं, 1। उपयोगकर्ता के बीजी में होने पर टोस्ट और सूचनाएं दिखाने के लिए। 2. जब उपयोगकर्ता पहली बार बीजी से आता है तो कुछ कार्य करते हैं, जैसे कि पोल, रेड्रा इत्यादि।
आइडलोन और अन्य द्वारा समाधान पहले भाग का ध्यान रखता है, लेकिन दूसरे के लिए नहीं। यदि आपके ऐप में कई गतिविधियां हैं, और उपयोगकर्ता उनके बीच स्विच कर रहा है, तो जब तक आप दूसरी गतिविधि में होते हैं, तब तक दिखाई देने वाला झंडा गलत होगा। तो यह नियत रूप से इस्तेमाल नहीं किया जा सकता है।
मैंने कॉमन्सवेयर द्वारा सुझाए गए कुछ किया था, "यदि सेवा निर्धारित करती है कि कोई गतिविधियां दिखाई नहीं दे रही हैं, और यह कुछ समय के लिए उस तरह से बनी हुई है , तो अगले तार्किक रोक बिंदु पर डेटा स्थानांतरण रोकें।"
बोल्ड में लाइन महत्वपूर्ण है और इसका उपयोग दूसरी वस्तु को प्राप्त करने के लिए किया जा सकता है। इसलिए मैं एक बार onActivityPaused () प्राप्त करने के लिए क्या करता हूं, डॉन को सीधे झूठे में नहीं बदलते हैं, इसके बजाय 3 सेकंड का टाइमर है (यह अधिकतम है कि अगली गतिविधि शुरू की जानी चाहिए), और अगर onActivity नहीं है (तो ) अगले 3 सेकंड में कॉल करें, झूठ को दृश्यमान बदलें। इसी तरह onActivityResumed () अगर कोई टाइमर है तो मैं उसे रद्द कर देता हूं। योग करने के लिए, दृश्यमान isAppInBackground हो जाता है।
क्षमा करें, कोड को कॉपी-पेस्ट नहीं कर सकते ...
मैं आपको ऐसा करने के लिए दूसरे तरीके का उपयोग करने की सलाह देना चाहूंगा।
मुझे लगता है कि आप प्रोग्राम शुरू करते समय स्टार्ट स्क्रीन दिखाना चाहते हैं, अगर यह पहले से ही बैकएंड में चल रहा है, तो इसे न दिखाएं।
आपका एप्लिकेशन किसी विशिष्ट फ़ाइल में लगातार वर्तमान समय लिख सकता है। जब आपका आवेदन शुरू हो रहा है, तो अंतिम टाइमस्टैम्प की जांच करें, यदि current_time-last_time> समय आपके नवीनतम समय को लिखने के लिए निर्दिष्ट है, तो इसका मतलब है कि आपका आवेदन बंद हो गया है, या तो सिस्टम या उपयोगकर्ता द्वारा खुद को मार दिया गया है।