Pertanyaan Layanan Latar Belakang Android dimulai ulang saat aplikasi terbunuh


Saya mengembangkan aplikasi di mana layanan latar belakang dibuat untuk mengumpulkan data sensor. Saya memulai layanan dari aktivitas saya:

startService(new Intent(this, MyService.class));

Saya membuat layanan jadi jika aplikasi dihancurkan, layanan latar belakang masih terus mengumpulkan data. Saya mencoba ini, dan itu berhasil sampai batas tertentu. Masalah saya adalah bahwa ketika saya membunuh aplikasi, layanan tampaknya restart karena onCreate() layanan dan onStart() metode dipanggil. Apakah ada cara dengan mana layanan tidak direstart?

MEMPERBARUI:

Seperti yang disarankan dalam jawaban di bawah ini, saya menambahkan metode berikut dalam layanan tetapi tidak berhasil.

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    return START_NOT_STICKY;
}

32
2018-03-16 18:21


asal


Jawaban:


Itu tergantung pada nilai yang dikembalikan di onStartCommand.

Anda harus kembali START_NOT_STICKY

Menurut dokumentasi:

Untuk layanan yang dimulai, ada dua mode utama operasi tambahan yang dapat mereka putuskan untuk dijalankan, tergantung pada nilai yang mereka kembalikan dari onStartCommand (): START_STICKY digunakan untuk layanan yang secara eksplisit dimulai dan dihentikan sebagaimana diperlukan, sementara START_NOT_STICKY atau START_REDELIVER_INTENT digunakan untuk layanan yang seharusnya hanya tetap berjalan saat memproses perintah apa pun yang dikirimkan kepada mereka

Pendeknya: Jika Anda kembali, START_STICKY layanan akan dibuat ulang setiap kali sumber daya tersedia. Jika Anda kembali START_NOT_STICKY Anda harus mengaktifkan kembali layanan yang mengirim maksud baru.

Karena semua ini memicu keingintahuan saya, saya membuat aplikasi contoh untuk menguji ini. Anda dapat menemukan zip dengan semua sumber di sini Ada tombol startService dan tombol stopService yang melakukan apa yang Anda harapkan dari mereka. Layanan mengembalikan START_NOT_STICKY di onStartCommand. Saya menempatkan bersulang di onCreate, onStartCommand dan onDestroy.

Di sini apa yang terjadi:

  • Jika saya menekan mulai, onCreate dan onStart dipanggil
  • Jika saya menekan stop, onDestroy terpicu
  • Jika saya menekan mulai dua kali, onCreate dipanggil sekali dan onStartCommand dua kali

Jadi itu berperilaku seperti yang diharapkan.

Jika saya memulai layanan dan membunuh aplikasi seperti yang Anda gambarkan, onDestroy tidak dipanggil tetapi tidak onCreate atau onStart.

Jika saya kembali ke aplikasi dan saya menekan mulai lagi, onCreate dipanggil yang berarti, seperti yang saya tulis sebelumnya, START_NOT_STICKY mencegah layanan untuk memulai ulang secara otomatis.

Saya kira Anda memiliki sesuatu yang lain di aplikasi Anda yang memulai layanan lagi (mungkin maksud yang tertunda).


18
2018-03-16 18:28



Aplikasi dan layanan ini hidup pada proses yang sama, yang berarti ketika aplikasi terbunuh begitu juga layanan Anda. Mengubah nilai pengembalian onStartCommand tidak memengaruhi proses ini. Ini hanya memberi tahu Layanan untuk memulai / menghentikan saat Anda memberi tahu atau kapan selesai melakukan apa yang perlu dilakukan. Seperti yang disebutkan dalam komentar Anda ke posting asli Anda, mengaturnya sebagai proses latar depan bekerja, tetapi itu benar-benar hanya memaksa layanan untuk memiliki prioritas tinggi, bukan memecahkan masalah.

Untuk mengubah Layanan sehingga terbunuh secara terpisah dan menganggap itu adalah layanan yang dimulai daripada layanan terikat karena penggunaan onStartCommand, tentukan nama proses dalam manifes untuk Layanan itu.

Dari Panduan Pengembang Proses dan Thread:

Entri manifes untuk setiap jenis elemen komponen— <activity>, <service>, <receiver>, and <provider>-   mendukung atribut proses android: yang dapat menentukan   proses di mana komponen itu harus dijalankan. Anda dapat mengatur   ini   atribut sehingga setiap komponen berjalan dalam prosesnya sendiri atau lebih   bahwa beberapa komponen berbagi proses sementara   yang lain tidak. Anda juga bisa mengatur android: proses jadi itu   komponen aplikasi yang berbeda berjalan di yang sama   proses — asalkan aplikasi berbagi sama   ID pengguna Linux dan ditandatangani dengan sertifikat yang sama.

Android mungkin memutuskan untuk menutup proses pada beberapa   titik, ketika memori rendah dan dibutuhkan oleh yang lain   proses yang lebih cepat melayani pengguna.   Komponen aplikasi berjalan dalam proses itu   dibunuh secara konsekuen hancur. Sebuah proses dimulai   lagi untuk komponen-komponen itu ketika ada lagi pekerjaan yang harus mereka lakukan.

Dari <service> dalam File Manifest:

android: proses

Nama proses di mana layanan dijalankan.   Biasanya, semua komponen aplikasi dijalankan dalam proses default   dibuat untuk aplikasi tersebut. Ini memiliki nama yang sama dengan aplikasi   paket. Atribut proses elemen dapat mengatur   standar berbeda untuk semua komponen. Tetapi komponen dapat menimpa   default dengan atribut prosesnya sendiri, memungkinkan Anda untuk menyebarkannya   aplikasi di berbagai proses.

Jika nama yang ditugaskan untuk ini   atribut dimulai dengan titik dua (':'), proses baru, pribadi ke   aplikasi, dibuat ketika dibutuhkan dan layanan berjalan di dalamnya   proses. Jika nama proses dimulai dengan karakter huruf kecil, maka   layanan akan berjalan dalam proses global nama itu, asalkan demikian   memiliki izin untuk melakukannya. Ini memungkinkan komponen berbeda   aplikasi untuk berbagi proses, mengurangi penggunaan sumber daya.

Tidak yakin mengapa jawaban lain yang menyebutkan ini turun sebagai suara. Saya telah menggunakan metode ini di masa lalu dan, hari ini, membuat satu aplikasi Aktivitas sederhana dengan Layanan pada proses yang berbeda hanya untuk memastikan saya tidak gila. Saya menggunakan Android Device Monitor untuk mematikan proses aplikasi. Anda dapat melihat keduanya, proses terpisah dalam ADM dan dapat melihat bahwa ketika proses aplikasi terbunuh, Layanan tidak.


4
2017-08-26 15:18



Jika Anda menggunakan IntentService, itu memiliki

onHandleIntent() 

metode di mana Anda harus menempatkan kode yang perlu dieksekusi. Ini dijalankan dalam utas yang terpisah (bukan utas UI tempat aplikasi Anda berjalan) oleh karena itu aplikasi Anda tidak boleh mempengaruhinya. Ketika kode selesai dieksekusi, utas dihentikan dan layanan dihentikan secara otomatis.


0
2018-03-16 18:27



Saya tahu sangat terlambat untuk menjawab pertanyaan ini, tetapi mungkin itu bisa membantu orang lain. Ini sangat membantu saya untuk Aplikasi Music Player saya.

Jika ada layanan yang dapat mengganggu atau dapat mempengaruhi pengalaman pengguna seperti musik dll, maka dalam hal ini Anda harus menggunakan Pemberitahuan dan ketika layanan dimulai dengan sukses, kemudian buat Pemberitahuan dan gunakan fungsi

startForeground(int Notification_id,Notification);

Ini akan menjalankan layanan Anda di latar belakang tanpa memulai ulang dan reinvoking metodenya

https://developer.android.com/reference/android/app/Service.html


0
2017-09-28 16:27



Mulai tidak lengket tidak berfungsi di atas kitkat, dan yang lainnya diTaskRemoved tidak berfungsi di atas Marshmellow. onTaskRemoved dapat digunakan dengan menangani beberapa pengecualian. Tidak mengerjakan itu. Tapi coba yang itu.


0
2018-03-04 07:56



Ketika memori rendah, layanan yang berjalan di latar belakang secara otomatis terbunuh. Alih-alih menggunakan startService () untuk memulai layanan, coba gunakan StartForeground () sebagai gantinya. Layanan berjalan di latar depan dan tidak akan pernah terbunuh meskipun memori rendah.


-2
2017-12-28 12:03



Saya mengalami masalah yang sama dan mampu menyelesaikannya dengan membuat layanan berjalan dalam proses global. Anda melakukan ini dengan menambahkan yang berikut ke tag manifes:

proses = "com.myapp.ProcessName"

(Buat nama apa pun.)

Ketika saya melakukan ini, saya menemukan bahwa layanan saya tidak terbunuh (dan dimulai ulang) ketika aplikasi dihapus dari daftar. Agaknya ini karena proses aplikasi terbunuh ketika Anda menggeseknya, tetapi proses layanan global tidak.

Kerugiannya adalah bahwa komunikasi antara aplikasi dan layanan Anda sekarang harus melalui antarmuka IBinder; Anda tidak dapat secara langsung memanggil fungsi dalam aplikasi atau layanan dari yang lain, karena mereka berjalan dalam proses yang berbeda.


-2
2018-04-01 15:50