जब एंड्रॉइड में स्वाइप करके ऐप को मार दिया जाए तो कोड को कैसे संभालें?


104

अगर मेरा ऐप चल रहा है और मैं होम बटन दबाता हूं, तो ऐप बैकग्राउंड में चला जाता है। अब एक लंबे प्रेस घर बटन और हाल ही में एप्लिकेशन सूची से स्वाइप करके एप्लिकेशन को समाप्त करता है, तो, घटनाओं में से कोई भी पसंद onPause(), onStop()या onDestroy()बल्कि कहा जाता हो जाता है प्रक्रिया को समाप्त कर रहा है। इसलिए अगर मैं चाहता हूं कि मेरी सेवाएं रुक जाएं, सूचनाओं को मारें और श्रोताओं को अपंजीकृत करें, तो मैं यह कैसे कर सकता हूं? मैंने काफी लेख और ब्लॉग पढ़े लेकिन कोई उपयोगी जानकारी नहीं मिली और मुझे इसके बारे में कोई दस्तावेज नहीं मिला। किसी भी सहायता की सराहना की जाएगी। अग्रिम में धन्यवाद।


मैं अपना मसला हल करता हूं। जाँच करें
मिस्टिकमैजिक

@MicicMagic वह सेवा के लिए काम करता है, जो अधिसूचना रद्द करने और श्रोताओं को अपंजीकृत करने के बारे में क्या करती है?
कोडवियार

आप onTaskRemoved में श्रोताओं को अपंजीकृत कर सकते हैं। क्या तुम नहीं कर सकते? और सूचनाएँ रद्द करने के लिए भी यही है
मिस्टिकमैजिक '17

@ MysticMagic Myst अगर मैं ऐप अपडेट पर समान चीजें करना चाहता हूं तो क्या होगा?
Reji

जवाबों:


150

मैंने बस इसी तरह के मुद्दे को हल किया।

यदि हाल ही में ऐप की सूची से स्वाइप करके एप्लिकेशन को मार दिया जाता है, तो इसके बारे में आप क्या कर सकते हैं ।

अपने मालसूची फ़ाइल के अंदर, झंडा रखने stopWithTaskके रूप में trueसेवा के लिए। पसंद:

<service
    android:name="com.myapp.MyService"
    android:stopWithTask="true" />

लेकिन जैसा कि आप कहते हैं कि आप श्रोताओं को अपंजीकृत करना चाहते हैं और अधिसूचना आदि को रोकना चाहते हैं, मैं इस दृष्टिकोण का सुझाव दूंगा:

  1. अपने मालसूची फ़ाइल के अंदर, झंडा रखने stopWithTaskके रूप में falseसेवा के लिए। पसंद:

    <service
        android:name="com.myapp.MyService"
        android:stopWithTask="false" />
  2. अब आपकी MyServiceसेवा में, ओवरराइड विधि onTaskRemoved। (यह केवल अगर stopWithTaskसेट किया गया है तो निकाल दिया जाएगा false)।

    public void onTaskRemoved(Intent rootIntent) {
    
        //unregister listeners
        //do any other cleanup if required
    
        //stop service
        stopSelf();  
    }

अधिक विवरण के लिए मेरे प्रश्न का संदर्भ लें , जिसमें कोड का अन्य भाग भी शामिल है।

उम्मीद है की यह मदद करेगा।


धन्यवाद। यह सोचकर कि क्या इस विधि का उपयोग स्वाइप किल को पहचानने के लिए किया जा सकता है। सरल रिक्त सेवा?
किरण

हां @ कीरान आप कोशिश कर सकते हैं। :)
मिस्टिकमैजिक

1
@ MysticMagic Myst हाय, एक सवाल, मैंने आपके समाधान का उपयोग करने की कोशिश की, लेकिन ऐसा लगता है कि लंबे समय तक ऑपरेशन जैसे सर्वर, एनालिटिक्स को Google पर भेजना आदि कुछ समय के लिए सभी तरह से विफल हो जाते हैं। क्या ऐसा हो सकता है कि इस प्रक्रिया को मारने से पहले इस विधि को पूरी तरह से पूरा करने का मौका मिला हो? क्या आपने भी Huawei डिवाइस पर यह तरीका आजमाया है? ऐसा लगता है onTaskRemoved को उन उपकरणों पर कभी नहीं बुलाया जाता है। कोई विचार क्यों?
एलोन मिंस्की

2
@ MysticMagic Myst सार्वजनिक शून्य onTaskRemoved (..) पद्धति Android O में कॉल नहीं करती है। अन्य OS में ठीक काम कर रही है लेकिन Android O में समस्या हो रही है
Jay Patel

2
बैकग्राउंड सर्विस लिमिट के कारण यह कोड Android O के लिए काम नहीं कर रहा है। क्या सभी Android उपकरणों में इसे संभालने का कोई तरीका है?
अंनाल मेहता

33

ऐसा करने का एक तरीका मिला

इस तरह एक सेवा करें

public class OnClearFromRecentService extends Service {

@Override
public IBinder onBind(Intent intent) {
    return null;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Log.d("ClearFromRecentService", "Service Started");
    return START_NOT_STICKY;
}

@Override
public void onDestroy() {
    super.onDestroy();
    Log.d("ClearFromRecentService", "Service Destroyed");
}

@Override
public void onTaskRemoved(Intent rootIntent) {
    Log.e("ClearFromRecentService", "END");
    //Code here
    stopSelf();
}

}

2) इस सेवा को मैनिफ़ेस्ट में दर्ज करें। xml

<service android:name="com.example.OnClearFromRecentService" android:stopWithTask="false" />

3) फिर अपनी छप गतिविधि पर इस सेवा को शुरू करें

startService(new Intent(getBaseContext(), OnClearFromRecentService.class));

और अब जब भी आप अपने ऐप को एंड्रॉइड से हाल ही में साफ़ करेंगे तो यह तरीका onTaskRemoved () निष्पादित करेगा।


1
इस उत्तर से एक से एक कॉपी और पेस्ट करें: stackoverflow.com/questions/21040339
Flot2011

17

मैंने इसी तरह का मुद्दा सुलझाया। यदि आप हाल के कार्य से स्वाइप करने के बाद और अगले लॉन्च पर इसे ठीक से व्यवहार करने के लिए चाहते हैं, तो नीचे दिए गए चरणों का पालन करें:

1) साझा प्राथमिकता में प्रक्रिया आईडी सहेजें:

SharedPreferencesUtils.getInstance().putInt(SharedPreferencesUtils.APP_PROCESS_ID, android.os.Process.myPid());

2) जब हाल ही के कार्य से स्पष्ट होने के बाद लॉन्चर से एप्लिकेशन लॉन्च किया जाता है, तब करें:

int previousProcessID = mSharedPreferencesUtils.getInt(SharedPreferencesUtils.APP_PROCESS_ID);

int currentProcessID = android.os.Process.myPid();

if ((previousProcessID == currentProcessID)) {
    // This ensures application not killed yet either by clearing recent or anyway
} else {
    // This ensures application killed either by clearing recent or by anyother means
}

पुष्टि की गई - एंड्रॉइड 8 पर सर्विस के बिना उपयोग किया गया। नोट रीमेक () - अच्छी तरह से किया गया
गैल रोम

4
यह समाधान केवल तभी पता लगाता है कि ऐप को फिर से शुरू किया गया था, लेकिन ऐप के मारे जाने पर आप उस सटीक क्षण का पता नहीं लगा सकते हैं
वादिम कोटोव

6

जब आप घर पर प्रेस करते हैं - onPauseऔर onStopआपकी गतिविधि को बुलाया जा रहा है, तो इस समय आपको सभी बचत और सफाई करनी होगी, क्योंकि एंड्रॉइड प्लेटफ़ॉर्म यह गारंटी नहीं देता है कि onDestroyया किसी अन्य जीवनचक्र पद्धति को लागू किया जाएगा, इसलिए प्रक्रिया को मार दिया जा सकता है बिना किसी सूचना के।


12
सुझाव के लिए धन्यवाद, लेकिन मैं अपने नोटिफिकेशन, सेवाओं और श्रोताओं को मारना नहीं चाहता हूं, onPause()और onstop()उन्हें केवल तभी मारना होगा जब उपयोगकर्ता ऐप से बाहर निकल जाए अर्थात लॉग आउट कर दे।
कोडवियार

1

onPause()कॉल करने पर आपको अपना डेटा सहेजना होगा । इस जीवन चक्र आरेख को देखें: Android डेवलपर

आप देख सकते हैं किसी ऐप के बाद मारा जा सकता है कि onPause()या onStop()

वहाँ अपने डेटा को संभालने और में यह ठीक onRestart()\ onCreate()

सौभाग्य!


1

आप स्वाइप को संभाल नहीं सकते, क्योंकि सिस्टम बिना किसी कॉलबैक के आपकी प्रक्रिया को मेमोरी से हटा देता है।

मैंने जाँच की है, कि उपयोगकर्ता "हाल के ऐप्स" स्क्रीन पर कॉल करने से पहले ऑनपॉज़ () को हमेशा कॉल करेगा। इसलिए आपको बिना जांच के ऑनपॉज विधि में सभी डेटा को बचाने की जरूरत है। फ़िनिशिंग ()।

बैक बटन चेक करने के लिए, ऑन बैकपैकड विधि का उपयोग करें।


1
मेरा मानना ​​है कि सभी Android संस्करणों के लिए यह एकमात्र सुरक्षित तरीका है।
सर्जियो

@ शेरगियो हाँ यह सबसे सुरक्षित तरीका है और मैंने इसे बड़े पैमाने पर प्रयोग किया है।
अहमद

1

ViewModel.onCleared () उपयोगी हो सकता है, यदि लक्ष्य कुछ संसाधन (शायद नेटवर्क पर कहीं और चल रहा एक सिस्टम) जारी करना है, जब उपयोगकर्ता "रोक" या बटन दबाकर, बजाय स्वाइप करके एक आश्चर्यजनक निकास निष्पादित करता है। [यह है कि मैं मूल रूप से इस सवाल पर कैसे आया]।

एप्लिकेशन को सूचना नहीं मिलती है, और एक्टिविटी.ऑनडेस्ट्रॉय () ओरिएंटेशन में परिवर्तन जैसे कॉन्फ़िगरेशन परिवर्तनों के लिए कॉल किया जाता है, इसलिए उत्तर नहीं है। लेकिन ViewModel.onCleared को तब बुलाया जाता है जब एप्लिकेशन को स्वाइप किया जाता है (साथ ही जब उपयोगकर्ता गतिविधि से बाहर निकलता है)। यदि आप जिस संसाधन का उपयोग करना चाहते हैं, वह स्टैक में एक से अधिक गतिविधियों से जुड़ा हुआ है, तो आप यह देखने के लिए संदर्भ काउंट या कुछ अन्य तंत्र जोड़ सकते हैं कि क्या ViewModel.onClear संसाधन को जारी करना चाहिए।

यह ViewModel का उपयोग करने के कई अच्छे कारणों में से एक है।

- बॉब


1

मैं वास्तव में नहीं जानता कि उपरोक्त दृष्टिकोण मेरे मामले पर काम क्यों नहीं कर रहे हैं यहां तक ​​कि मैंने android:stopWithTask="false"यह भी निर्धारित किया है कि onTaskRemoved()बुलाया नहीं।

एक और अच्छा तरीका उपयोग होगा AndroidViewModel। यह मामला उस समय भी काम करता है जब उपयोगकर्ता बैक बटन दबाने पर प्रशंसा छोड़ देता है।

बस ViewModelअपने वर्ग के लिए बाध्य MainActivityतो अपने कार्य onCleared()कॉलबैक करते हैं।

उदाहरण:

public class MainViewModel extends AndroidViewModel {
    public MainViewModel(@NonNull Application application) {
        super(application);
    }

    @Override
    protected void onCleared() {
        // Do your task here
        Log.e("MainViewModel", "OnCleared mainViewModel");
        super.onCleared();
    }
}

फिर इसे अपनी मुख्यता के लिए बाध्य करें:

MainViewModel viewModel = new ViewModelProvider(this).get(MainViewModel.class);

~ वोइला!


यह एंड्रॉइड O और उससे अधिक के कारण सेवा दृष्टिकोण के साथ काम नहीं कर सकता है जैसा कि अन्य टिप्पणीकारों द्वारा उल्लेख किया गया है। यह इसके लिए दृश्य मॉडल के उपयोग के लिए एक दिलचस्प समाधान की तरह लगता है। क्या यह तब भी चालू हो जाता है जब एप्लिकेशन को बल मारा जाता है (ऐप स्विचर स्क्रीन पर स्वाइप किया जाता है)? संपादित करें: बॉब का उत्तर बताता है कि यह इन मामलों में काम करता है
विलियम रीड

हाँ यह काम करता है, उस मामले जो मैं के साथ सामना करना पड़ा है
droidhs

0

इसने मेरे लिए एंड्रॉइड 6,7,8,9 पर काम किया।

इस तरह एक सेवा करें:

 public class OnClearFromRecentService extends Service {

 @Override public IBinder onBind(Intent intent) {
     return null; }

 @Override public int onStartCommand(Intent intent, int flags, int
 startId) {
     Log.d("ClearFromRecentService", "Service Started");
     return START_NOT_STICKY; }

 @Override public void onDestroy() {
     super.onDestroy();
     Log.d("ClearFromRecentService", "Service Destroyed"); }

 @Override public void onTaskRemoved(Intent rootIntent) {
     Log.e("ClearFromRecentService", "END");
     //Code here
     stopSelf(); } }

2) इस सेवा को इसमें पंजीकृत करें manifest.xml:

<service android:name="com.example.OnClearFromRecentService"
 android:stopWithTask="false" />

3) फिर अपनी छप गतिविधि पर इस सेवा को शुरू करें

 startService(new Intent(getBaseContext(),
 OnClearFromRecentService.class));

1
और आपकी सेवा Android 8 और इसके बाद के संस्करण पर क्यों चलती रहेगी? आपको पता चलता है कि स्टार्टेड सर्विसेज पोस्ट एंड्रॉइड 8 पर प्रतिबंध है, है ना?
rahil008

0

जैसा कि बॉब क्रैम ने अपने उत्तर में उल्लेख किया है, देखें मॉडल का ऑनक्लेयर () विधि उत्तर है। यह दोनों मामलों में काम करता है:

  1. जब यूजर ऐप को बैकग्राउंड से स्वाइप करके हटा देता है।
  2. जब उपयोगकर्ता स्पष्ट सूची बटन का उपयोग करके सभी एप्लिकेशन को साफ़ करता है।

सेवा का onTaskRemoved () तब काम करेगा जब उपयोगकर्ता ऐप को पृष्ठभूमि से स्वाइप करता है, लेकिन जब एप्स को सभी बटन का उपयोग करके साफ़ किया जाता है तो यह काम नहीं करेगा।

लेकिन viewModel का ऑनक्लेयर () तरीका दोनों ही मामलों में काम करता है। आप किसी चल रही प्रक्रिया को रोकने या दूरस्थ सर्वर में किसी कार्य को साफ़ करने के लिए उपयोग कर सकते हैं।

 override fun onCleared() {
        super.onCleared()
        Log.d(TAG , "App Killed")
    }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.