Android: الحفاظ على خدمة خلفية حية (منع وفاة العملية)

StackOverflow https://stackoverflow.com/questions/3856767

سؤال

لدي خدمة تُعرّف بأنها:

public class SleepAccelerometerService extends Service implements SensorEventListener

في الأساس ، أقوم بعمل تطبيق يراقب نشاط التسارع لأسباب مختلفة بينما ينام المستخدم بهاتفه/جهازها على السرير. هذه خدمة طويلة الأمد لا يجب قتلها أثناء الليل. اعتمادًا على عدد تطبيقات الخلفية والعمليات الدورية التي تحدث أثناء الليل ، يقتل Android أحيانًا عملي ، وبالتالي إنهاء خدمتي. مثال:

10-04 03:27:41.673: INFO/ActivityManager(1269): Process com.androsz.electricsleep (pid 16223) has died.
10-04 03:27:41.681: INFO/WindowManager(1269): WIN DEATH: Window{45509f98 com.androsz.electricsleep/com.androsz.electricsleep.ui.SleepActivity paused=false}

لا أريد إجبار المستخدم على الحصول على "نوم" أو أي نشاط آخر في تطبيقي كمقدمة. لا يمكنني تشغيل خدمتي بشكل دوري ، لأنه يعترض باستمرار onSensorChanged.

أي نصائح؟ رمز المصدر هنا: http://code.google.com/p/electricsleep/

هل كانت مفيدة؟

المحلول

لنظام Android 2.0 أو في وقت لاحق يمكنك استخدام startForeground() طريقة لبدء خدمتك في المقدمة.

ال الوثائق يقول ما يلي:

يمكن للخدمة التي بدأت استخدام startForeground(int, Notification) API لوضع الخدمة في دولة مقدمة ، حيث يعتبر النظام أنها شيء يدركه المستخدم بنشاط وبالتالي ليس مرشحًا للقتل عند انخفاض الذاكرة. (لا يزال من الممكن نظريًا قتل الخدمة تحت ضغط الذاكرة القصوى من تطبيق المقدمة الحالي ، ولكن في الممارسة العملية ، لا ينبغي أن يكون هذا مصدر قلق.)

المقصود في المقام الأول عند قتل الخدمة سيكون مضطربًا للمستخدم ، على سبيل المثال ، سيتوقف قتل خدمة مشغل الموسيقى عن تشغيل الموسيقى.

ستحتاج إلى توفير ملف Notification إلى الطريقة التي يتم عرضها في شريط الإخطارات في القسم المستمر.

نصائح أخرى

عندما تقوم بربط خدمتك بالنشاط باستخدام BIND_AUTO_CREET يتم قتل خدمتك بعد تدمير نشاطك مباشرة. إنه لا يعتمد على كيفية تنفيذ خدماتك غير المرتبطة ، فسيظل يتم قتله.

الطريقة الأخرى هي بدء خدمتك باستخدام طريقة startervice من نشاطك. وبهذه الطريقة ، حتى إذا تم تدمير نشاطك ، فلن يتم تدمير خدمتك أو حتى توقف مؤقتًا ولكن عليك أن تتوقف/تدميرها بنفسك مع توقف/توقف عند الاقتضاء.

كما أشار ديف بالفعل, ، يمكنك تشغيل الخاص بك Service مع أولوية المقدمة. ولكن يجب استخدام هذه الممارسة فقط عندما تكون ضرورية للغاية ، أي عندما تتسبب في تجربة مستخدم سيئة إذا تم قتل الخدمة بواسطة Android. هذا ما يعنيه "المقدمة" حقًا: تطبيقك هو بطريقة ما في المقدمة وسيشير المستخدم على الفور إذا تم قتله (على سبيل المثال لأنه لعب أغنية أو مقطع فيديو).

في معظم الحالات ، يكون طلب الأولوية المقدمة لخدمتك هو contraproduction!

لماذا هذا؟ عندما يقرر Android قتل أ Service, ، إنه يفعل ذلك لأنه أقل من الموارد (عادةً ما يكون ذاكرة الوصول العشوائي). استنادًا إلى فئات الأولوية المختلفة ، يقرر Android عمليات التشغيل ، وتشمل ذلك الخدمات ، لإنهاء الموارد المجانية. هذه عملية صحية تريد أن تحدث حتى يتمتع المستخدم بتجربة سلسة. إذا طلبت أولوية صوتية ، دون سبب وجيه ، فقط لمنع خدمتك من القتل ، فمن المرجح أن يتسبب ذلك في تجربة مستخدم سيئة. أو هل يمكنك ضمان أن تظل خدمتك ضمن الحد الأدنى من استهلاك الموارد وليس لها تسرب ذاكرة؟1

يوفر Android الخدمات اللاصقة للاحتفال بالخدمات التي يجب إعادة تشغيلها بعد فترة سماح إذا قتلوا. يحدث هذا إعادة التشغيل عادة في غضون بضع ثوان.

الصورة التي تريد كتابة عميل XMPP لنظام Android. هل يجب أن تطلب الأولوية المقدمة ل Service الذي يحتوي على اتصال XMPP الخاص بك؟ بالتأكيد لا ، لا يوجد أي سبب للقيام بذلك. لكنك تريد استخدامها START_STICKY كعلم العودة لخدمتك onStartCommand طريقة. بحيث يتم إيقاف خدمتك عندما يكون هناك ضغط للموارد وإعادة تشغيله بمجرد العودة إلى الوضع إلى طبيعتها.

1: أنا متأكد من أن العديد من تطبيقات Android لديها تسرب الذاكرة. إنه شيء لا يهتم به المبرمج غير الرسمي (سطح المكتب) كثيرًا.

كان لي مشكلة مشابهة. على بعض الأجهزة بعد فترة من الوقت يقتل Android خدمتي وحتى startForeground () لا يساعد. وعميلي لا يحب هذه المشكلة. الحل الخاص بي هو الاستخدام المنبه الفصل للتأكد من أن الخدمة تعمل عندما تكون ضرورية. أنا أستعمل المنبه لإنشاء نوع من مؤقت الوكالة الدولية للطاقة. يتحقق من وقت لآخر إذا كانت الخدمة يجب أن تعمل وإعادة تشغيلها. أيضا أنا أستخدم تفضيلات المشتركة للحفاظ على العلم ما إذا كان ينبغي أن تكون الخدمة قيد التشغيل.

إنشاء/رفض جهاز مراقبة جهاز المراقبة الخاص بي:

void setServiceWatchdogTimer(boolean set, int timeout)
{
    Intent intent;
    PendingIntent alarmIntent;
    intent = new Intent(); // forms and creates appropriate Intent and pass it to AlarmManager
    intent.setAction(ACTION_WATCHDOG_OF_SERVICE);
    intent.setClass(this, WatchDogServiceReceiver.class);
    alarmIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    AlarmManager am=(AlarmManager)getSystemService(Context.ALARM_SERVICE);
    if(set)
        am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + timeout, alarmIntent);
    else
        am.cancel(alarmIntent);
}

تلقي ومعالجة القصد من مؤقت الوكالة الدولية للطاقة:

/** this class processes the intent and
 *  checks whether the service should be running
 */
public static class WatchDogServiceReceiver extends BroadcastReceiver
{
    @Override
    public void onReceive(Context context, Intent intent)
    {

        if(intent.getAction().equals(ACTION_WATCHDOG_OF_SERVICE))
        {
            // check your flag and 
            // restart your service if it's necessary
            setServiceWatchdogTimer(true, 60000*5); // restart the watchdogtimer
        }
    }
}

في الواقع أنا أستخدم WakefulBroadcastreceiver بدلاً من مستقبل البث. أعطيتك الرمز مع Broadcastreceiver فقط لتبسيطه.

http://developer.android.com/reference/android/content/context.html#bind_above_client

نهائي ثابت عام bind_above_client - أضيفت في API المستوى 14

العلم ل bindService(Intent, ServiceConnection, int): يشير إلى أن تطبيق العميل الملزم لهذه الخدمة يعتبر أن الخدمة أكثر أهمية من التطبيق نفسه. عند التعيين ، ستحاول المنصة أن تقتل التطبيق من الذاكرة قبل أن تقتل الخدمة التي لا بد من ذلك ، على الرغم من أن هذا ليس مضمونًا ليكون كذلك.

أعلام أخرى من نفس المجموعة هي: bind_adjust_with_activity ، bind_auto_create ، bind_important ، bind_not_foreground ، bind_waive_priority.

لاحظ أن معنى bind_auto_create قد تغير في ICS ، والتطبيقات القديمة التي لا تحدد BIND_AUTO_CREATE سوف يكون لها الأعلام تلقائيًا BIND_WAIVE_PRIORITY و BIND_ADJUST_WITH_ACTIVITY تعيين لهم.

حافظ على انبعاثات الخدمة الصغيرة ، وهذا يقلل من احتمال إغلاق Android لتطبيقك. لا يمكنك منعه من القتل لأنه إذا تمكنت من ذلك ، فيمكن للأشخاص إنشاء برامج تجسس مستمرة بسهولة

أنا أعمل على تطبيق وأواجه قضية قتل خدمتي من خلال Kill App. لقد بحثت على Google ووجدت أنه يجب علي جعلها مقدمة. فيما يلي الرمز:

public class UpdateLocationAndPrayerTimes extends Service {

 Context context;
@Override
public void onCreate() {
    super.onCreate();
    context = this;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {

    StartForground();
    return START_STICKY;
}

@Override
public void onDestroy() {


    super.onDestroy();
}

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


private void StartForground() {
    LocationChangeDetector locationChangeDetector = new LocationChangeDetector(context);
    locationChangeDetector.getLatAndLong();
    Notification notification = new NotificationCompat.Builder(this)
            .setOngoing(false)
            .setSmallIcon(android.R.color.transparent)

            //.setSmallIcon(R.drawable.picture)
            .build();
    startForeground(101,  notification);

    }
}

القفزات أنه قد يساعد !!!!

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top