जब अग्रभूमि सेवा अंतिम रोक दी जाती है तो ऐप चलता रहता है


9

मैं अग्रभूमि सेवाओं के साथ मिलकर एंड्रॉइड के प्रक्रिया प्रबंधन में एक व्यवहार के साथ आया, जो वास्तव में मुझे भ्रमित करता है।

मेरे लिए क्या उचित है?

  1. जब आप अपने ऐप को 'हाल के ऐप्स' से स्वाइप करते हैं, तो OS को अपेक्षाकृत निकट भविष्य में ऐप प्रक्रिया समाप्त कर देनी चाहिए।
  2. जब आप अग्रभूमि सेवा चलाते समय अपने ऐप को 'हाल के ऐप्स' से स्वाइप करते हैं, तो ऐप जीवित रहता है।
  3. जब आप अपने ऐप को 'हाल के ऐप्स' से स्वाइप करने से पहले अग्रभूमि सेवा बंद कर देते हैं तो आपको 1 के समान ही मिलता है)।

मुझे क्या उलझन है

जब आप अग्रभूमि में कोई गतिविधि नहीं करते हुए अग्रभूमि सेवा बंद कर देते हैं (ऐप 'हाल के ऐप्स' में प्रकट नहीं होता है), तो मुझे उम्मीद है कि ऐप अब मारा जा रहा है।

हालांकि, ऐसा नहीं हो रहा है, ऐप प्रक्रिया अभी भी जीवित है।

उदाहरण

मैंने एक न्यूनतम उदाहरण बनाया है जो इस व्यवहार को दर्शाता है।

अग्रभूमि सेवा:

import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.Service
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.IBinder
import androidx.core.app.NotificationCompat
import timber.log.Timber

class MyService : Service() {

    override fun onBind(intent: Intent?): IBinder? = null

    override fun onCreate() {
        super.onCreate()
        Timber.d("onCreate")
    }

    override fun onDestroy() {
        super.onDestroy()
        Timber.d("onDestroy")

        // just to make sure the service really stops
        stopForeground(true)
        stopSelf()
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        Timber.d("onStartCommand")
        startForeground(ID, serviceNotification())
        return START_NOT_STICKY
    }

    private fun serviceNotification(): Notification {
        createChannel()

        val stopServiceIntent = PendingIntent.getBroadcast(
            this,
            0,
            Intent(this, StopServiceReceiver::class.java),
            PendingIntent.FLAG_UPDATE_CURRENT
        )
        return NotificationCompat.Builder(this, CHANNEL_ID)
            .setSmallIcon(R.drawable.ic_launcher_foreground)
            .setContentTitle("This is my service")
            .setContentText("It runs as a foreground service.")
            .addAction(0, "Stop", stopServiceIntent)
            .build()
    }

    private fun createChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val notificationManager = getSystemService(NotificationManager::class.java)
            notificationManager.createNotificationChannel(
                NotificationChannel(
                    CHANNEL_ID,
                    "Test channel",
                    NotificationManager.IMPORTANCE_DEFAULT
                )
            )
        }
    }

    companion object {
        private const val ID = 532207
        private const val CHANNEL_ID = "test_channel"

        fun newIntent(context: Context) = Intent(context, MyService::class.java)
    }
}

इस प्रसारण को रोकने के लिए प्रसारणकर्ता:

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent

class StopServiceReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {

        val serviceIntent = MyService.newIntent(context)

        context.stopService(serviceIntent)
    }
}

वह काम:

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        startService(MyService.newIntent(this))
    }
}

प्रकट:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.christophlutz.processlifecycletest">

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service android:name=".MyService"/>
        <receiver android:name=".StopServiceReceiver" />
    </application>

</manifest>

इसे निम्नलिखित तरीकों से आज़माएँ:

  1. ऐप शुरू करें, अग्रभूमि सेवा बंद करें, 'हाल के ऐप्स' से ऐप निकालें
  2. ऐप शुरू करें, 'हाल के ऐप्स' से ऐप निकालें, अग्रभूमि सेवा बंद करें

आप Android Studio के LogCat में देख सकते हैं कि ऐप प्रक्रिया केस 1 के लिए [DEAD] चिह्नित है, लेकिन केस 2 के लिए नहीं।

चूंकि इसे पुन: पेश करना बहुत आसान है, यह एक इच्छित व्यवहार हो सकता है, लेकिन डॉक्स में मुझे इसका कोई वास्तविक उल्लेख नहीं मिला।

क्या किसी को पता है कि यहां क्या चल रहा है?

जवाबों:


0

यह इस बात पर निर्भर करता है कि अग्रभूमि सेवा वास्तव में क्या करती है। यदि यह थ्रेड्स, नेटवर्क कनेक्शन, फ़ाइल I / O आदि का उपयोग करता है .. जो कि मेमोरी को सक्रिय रूप से खपत करता है, भले ही आप सेवा को रोकने की कोशिश करें, यह नष्ट नहीं होगा, इसलिए यह प्रक्रिया जीवित रहेगी। यह किसी भी इंटरफ़ेस कॉलबैक में शामिल है जो सेवा को रोकने की कोशिश करते समय जीवित रहते हैं। विशेष रूप से थ्रेड्स जो अभी भी चलते हैं (यहां तक ​​कि बाधित) और बाध्य सेवाएं जीवनचक्र को अवरुद्ध करती हैं जो सेवा को ठीक से रोक रही हैं।

सुनिश्चित करें कि आपकी सेवा में कोई मेमोरी लीक नहीं है और हर कनेक्शन (डेटाबेस, नेटवर्क आदि ...) को बंद करें, अपनी सेवा को रोकने से पहले सभी इंटरफेस से सभी कॉलबैक निकालें। आप यह सुनिश्चित कर सकते हैं कि यदि onDestroy()कॉल किया जाता है तो सेवा नष्ट होने वाली है।

विभिन्न प्रक्रियाओं के लिए: मेरा मानना ​​है कि इस प्रक्रिया के जीवित रहने का कारण यह है कि, सिस्टम इस तरह से देखता है जहां सेवा कुछ समय के लिए फिर से शुरू हो सकती है, इसलिए यह प्रक्रिया को थोड़े समय के लिए जीवित रखता है। कम से कम, यही मैंने देखा है, क्योंकि onDestroy()कहा जाने के बाद भी , प्रक्रिया जीवित रही, मैं इसे डिबगर से देख पा रहा था।

यदि आप यह सुनिश्चित करना चाहते हैं (भले ही इस तरह की सिफारिश नहीं की गई है) कि प्रक्रिया सब कुछ नष्ट हो जाने के बाद सुनिश्चित हो जाती है, तो आप हमेशा इस प्रक्रिया को स्वयं समाप्त करने के लिए कह सकते हैं:

android.os.Process.killProcess(android.os.Process.myPid());

आप प्रश्न & mdash से उदाहरण के साथ व्यवहार को पुन: पेश कर सकते हैं; कोई कनेक्शन, थ्रेड या कुछ भी नहीं चलता है। onDestroy(सेवा) कहा जाता है, फिर भी सब कुछ खत्म हो जाने के बाद भी यह प्रक्रिया जीवित रहती है। यहां तक ​​कि अगर सेवा के फिर से शुरू होने की स्थिति में, ओएस प्रक्रिया को जीवित रखे हुए था, तो मैं यह नहीं देखता कि जब आप पहले सेवा को रोकते हैं तो यह वही काम क्यों नहीं करता है, तो एप्लिकेशन को पुनरावृत्ति से हटा दें। प्रदर्शित व्यवहार अप्रभावी लगता है, विशेष रूप से पृष्ठभूमि निष्पादन की सीमाओं में हालिया परिवर्तन, इसलिए यह जानना अच्छा होगा कि यह सुनिश्चित करने के लिए कि प्रक्रिया बंद हो जाती है
डेविड मेडेनजैक

@DavidMedenjak getApplicationContext().startService(MyService.newIntent(this));आप जो प्रयोग कर रहे हैं उसके बजाय प्रयोग करने की कोशिश करें और मुझे परिणाम बताएं। मेरा मानना ​​है कि गतिविधि जीवित रहती है क्योंकि गतिविधि संदर्भ का उपयोग अनुप्रयोग संदर्भ के बजाय किया जाता है। इसके अलावा अगर आप Oreo या इसके बाद के संस्करण का परीक्षण कर रहे हैं, तो उपयोग करने की कोशिश करेंgetApplicationContext().startforegroundService(MyService.newIntent(this));
Furkan Yurdakul

0

एंड्रॉइड सिस्टम को स्मृति, प्रोसेसर शक्ति और अनुप्रयोगों के जीवनकाल के मामले में अपनी आत्म-जागरूकता के लिए जाना जाता है - यह खुद तय करता है कि क्या नहीं की एक प्रक्रिया को मारना है (गतिविधियों और सेवाओं के साथ ही)

इस मामले के बारे में आधिकारिक दस्तावेज यहां दिया गया है।

देखिए कि यह अग्रभूमि के बारे में क्या कहता है

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

और दृश्यमान प्रक्रियाएं (अग्रभूमि सेवा एक दृश्यमान प्रक्रिया है)

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

इसका मतलब है कि एंड्रॉइड ओएस में आपके ऐप की प्रक्रिया तब तक चलेगी जब तक कि इसमें सभी अग्रभूमि प्रक्रियाओं का समर्थन करने के लिए पर्याप्त मेमोरी होगी । यहां तक ​​कि अगर आप इसे रोकते हैं - सिस्टम इसे केवल कैश्ड प्रक्रियाओं में स्थानांतरित कर सकता है और इसे कतार की तरह तरीके से संभाल सकता है। आखिरकार इसे किसी भी तरह से मार दिया जाएगा - लेकिन आमतौर पर यह आपके लिए तय नहीं होता है। सच कहूँ तो आपको इस बात की बिल्कुल भी परवाह नहीं करनी चाहिए कि आपके एंड्रॉइड जीवन चक्र के तरीकों को (और जब तक) कहा जाता है, उसके बाद आपकी ऐप प्रक्रिया क्या हो रही है। Android बेहतर जानता है।

बेशक आप इस प्रक्रिया को मार देते हैं, android.os.Process.killProcess(android.os.Process.myPid());लेकिन यह अनुशंसित नहीं है क्योंकि यह उचित एंड्रॉइड तत्वों के जीवनचक्र को बाधित करता है और उचित कॉलबैक नहीं कहा जा सकता है, इस प्रकार आपका ऐप कुछ मामलों में दुर्व्यवहार कर सकता है।

आशा है ये मदद करेगा।


0

एंड्रॉइड पर यह ऑपरेटिंग सिस्टम है जो यह तय करता है कि कौन से एप्लिकेशन मारे गए हैं।

प्राथमिकता का एक आदेश है:
एक अग्रभूमि सेवा वाले एप्लिकेशन शायद ही कभी मारे जाते हैं, इसके बजाय निष्क्रियता की अवधि के बाद अन्य ऐप और सेवाओं को मार दिया जाता है और यही आपके ऐप के साथ होता है।

जब आप अग्रभूमि सेवा समाप्त करते हैं, तो यह आपके ऐप को मारने वाले सिस्टम की संभावनाओं को बढ़ाता है लेकिन किसी भी मामले में इसका मतलब यह नहीं है कि यह तुरंत मारा जाएगा।


0

हाल ही स्क्रीन [...] एक सिस्टम स्तर यूआई कि सूचियों हाल ही में पहुंचे है गतिविधियों और कार्यों

सूची में एक ऐप से कई गतिविधियाँ या कार्य हो सकते हैं। यह नहीं एक हाल ही के एप्लिकेशन सूची।

इसलिए रीसेंट स्क्रीन के तत्वों और ऐप प्रक्रिया के बीच कोई सीधा संबंध नहीं है।

किसी भी तरह , यदि आप अपने ऐप की अंतिम गतिविधि को बंद कर देते हैं और प्रक्रिया के भीतर (अग्रभूमि सेवा की तरह) कुछ और नहीं चल रहा है, तो प्रक्रिया बस साफ हो जाती है।

इसलिए जब आप किसी रनिंग फोरग्राउंड (बाय stopService()या stopSelf()अनबाइंडिंग) को रोकते हैं , तो सिस्टम उस प्रक्रिया को भी साफ कर देगा जो उसमें चल रही थी।

तो यह वास्तव में एक इच्छित व्यवहार है

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