Android 8.0: java.lang.IllegalStateException: Tidak diizinkan memulai Intent layanan

360

Pada peluncuran aplikasi, aplikasi memulai layanan yang harus melakukan beberapa tugas jaringan. Setelah menargetkan API level 26, aplikasi saya gagal memulai layanan di Android 8.0 di latar belakang.

Disebabkan oleh: java.lang.IllegalStateException: Tidak diizinkan untuk memulai layanan Intent {cmp = my.app.tt / com.my.service}: aplikasi berada di latar belakang UidRecord {90372b1 u0a136 Projek siaga CEM: 1 seq (0,0 , 0)}

seperti yang saya pahami terkait dengan: Batas eksekusi latar belakang

Metode startService () sekarang melempar IllegalStateException jika aplikasi yang menargetkan Android 8.0 mencoba menggunakan metode itu dalam situasi ketika tidak diizinkan untuk membuat layanan latar belakang.

" dalam situasi ketika itu tidak diizinkan " - apa artinya sebenarnya ?? Dan bagaimana cara memperbaikinya. Saya tidak ingin mengatur layanan saya sebagai "foreground"

PHNNN
sumber
4
Ini berarti bahwa Anda tidak dapat memulai layanan ketika aplikasi Anda berada di latar belakang
Tim
22
ini tidak ada hubungannya dengan izin runtime
Tim
10
Gunakan startForegroundService()sebagai ganti startService().
frogatto
2
Anda dapat mencoba menggunakan targetSdkVersion 25 tetapi kompilasi dengan compileSdkVersion 26. Dengan cara ini Anda dapat menggunakan kelas-kelas baru dari Android 8 dan pustaka pendukung terbaru tetapi aplikasi Anda tidak akan dibatasi oleh Batas Eksekusi Latar Belakang.
Kacper Dziubek
2
@KacperDziubek Itu harus bekerja tetapi merupakan solusi sementara karena akan diperlukan untuk menargetkan SDK26 pada musim gugur 2018.
RightHandedMonkey

Jawaban:

194

Situasi yang diizinkan adalah daftar putih sementara di mana layanan latar belakang berperilaku sama seperti sebelum Android O.

Dalam keadaan tertentu, aplikasi latar belakang ditempatkan pada daftar putih sementara selama beberapa menit. Saat aplikasi masuk daftar putih, ia dapat meluncurkan layanan tanpa batasan, dan layanan latar belakangnya diizinkan untuk berjalan. Aplikasi ditempatkan pada daftar putih ketika menangani tugas yang terlihat oleh pengguna, seperti:

  • Menangani pesan Firebase Cloud Messaging (FCM) prioritas tinggi.
  • Menerima siaran, seperti pesan SMS / MMS.
  • Menjalankan PendingIntent dari notifikasi.
  • Memulai VpnService sebelum aplikasi VPN mempromosikan dirinya sendiri ke latar depan.

Sumber: https://developer.android.com/about/versions/oreo/background.html

Jadi dengan kata lain jika layanan latar belakang Anda tidak memenuhi persyaratan daftar putih Anda harus menggunakan JobScheduler baru . Ini pada dasarnya sama dengan layanan latar belakang, tetapi dipanggil secara berkala alih-alih berjalan di latar belakang terus menerus.

Jika Anda menggunakan IntentService, Anda dapat mengubah ke JobIntentService. Lihat jawaban @ kosev di bawah ini .

Murat Karagöz
sumber
Saya mendapatkan crash setelah saya ingin memulai layanan tepat setelah saya menerima pesan GCM dari prio "tinggi". Saya masih menggunakan GCM: "com.google.android.gms: play-services-gcm: 11.4.2", bukan 'com.google.firebase: firebase-messaging: firebase-messaging: 11.4.2'. Tidak yakin itu penting ..
Alex Radzishevsky
"Ini pada dasarnya sama dengan layanan latar belakang, tetapi dipanggil secara berkala alih-alih berjalan di latar belakang terus menerus." - tidak yakin apa yang Anda maksud dengan ini, karena layanan Android tidak pernah dieksekusi terus menerus. Mereka memulai, berlari, lalu mematikan.
Melllvar
2
Apakah FirebaseInstanceIdService dan onTokenRefreshmetodenya pesan FCM prioritas tinggi?
Cord Rehn
@ phnmnn tidak, GCMTaskService tidak benar-benar mengikuti FCM sehingga mereka tidak berfungsi.
Abhinav Upadhyay
4
Bukankah Anda seharusnya menggunakan WorkManager (di sini: developer.android.com/topic/libraries/architecture/workmanager ) alih-alih dari JobScheduler atau yang lain? Maksud saya ini: youtu.be/IrKoBFLwTN0
pengembang android
256

Saya mendapat solusi. Untuk perangkat pra-8.0, Anda hanya perlu menggunakan startService(), tetapi untuk perangkat pasca-7.0, Anda harus menggunakan startForgroundService(). Berikut ini contoh kode untuk memulai layanan.

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        context.startForegroundService(new Intent(context, ServedService.class));
    } else {
        context.startService(new Intent(context, ServedService.class));
    }

Dan di kelas layanan, silakan tambahkan kode di bawah ini untuk pemberitahuan:

@Override
public void onCreate() {
    super.onCreate();
    startForeground(1,new Notification());
}

Di mana O adalah Android versi 26.

Sagar Kacha
sumber
9
Layanan foreground adalah sesuatu yang pengguna akan sadari dan perlu pemberitahuan. Ini juga akan PPA jika berjalan terlalu lama. Jadi itu bukan jawaban yang cocok jika aplikasi sudah berjalan di latar belakang.
SimonH
80
Ada ContextCompat.startForegroundService(...)lib dukungan yang dapat digunakan sebagai gantinya.
jayeffkay
37
Itu bukan solusi.
JacksOnF1re
17
Saya juga setuju bahwa ini bukan solusi. Ini adalah solusi dan itu membantu, tetapi batas latar belakang di Oreo diperkenalkan karena suatu alasan. Melewati batas-batas itu dengan cara ini jelas bukan pendekatan yang benar (meskipun berfungsi). Cara terbaik adalah menggunakan JobScheduler (lihat jawaban yang diterima).
Vratislav Jindra
6
Saya tidak berpikir itu akan menjadi pengalaman pengguna yang baik jika Anda harus menunjukkan pemberitahuan latar depan kosong. Mempertimbangkan kenyataan bahwa kamu harus. - Android 8.0 memperkenalkan metode baru startForegroundService () untuk memulai layanan baru di latar depan. Setelah sistem membuat layanan, aplikasi memiliki lima detik untuk memanggil metode startForeground () layanan untuk menampilkan notifikasi yang dapat dilihat pengguna layanan baru. Jika aplikasi tidak memanggil startForeground () dalam batas waktu, sistem menghentikan layanan dan menyatakan aplikasi tersebut ANR.
heeleeaz
85

Cara terbaik adalah dengan menggunakan JobIntentService yang menggunakan JobScheduler baru untuk Oreo atau layanan lama jika tidak tersedia.

Nyatakan dalam manifes Anda:

<service android:name=".YourService"
         android:permission="android.permission.BIND_JOB_SERVICE"/>

Dan dalam layanan Anda, Anda harus mengganti onHandleIntent dengan onHandleWork:

public class YourService extends JobIntentService {

    public static final int JOB_ID = 1;

    public static void enqueueWork(Context context, Intent work) {
        enqueueWork(context, YourService.class, JOB_ID, work);
    }

    @Override
    protected void onHandleWork(@NonNull Intent intent) {
        // your code
    }

}

Kemudian Anda memulai layanan Anda dengan:

YourService.enqueueWork(context, new Intent());
Kosev
sumber
Bagaimana Anda dapat memanggil metode non-statis di dalam metode statis? Bisakah Anda jelaskan?
Maddy
@ Maddy enqueueWork(...)adalah metode statis juga.
hgoebl
2
Di mana Anda akan memanggil YourService.enqueueWork (konteks, Intent baru ()); ? Dari penerima siaran?
TheLearner
Saya tidak percaya bahwa ini adalah solusi termudah. Lihat komentar saya di bawah ini tentang WorkManager. Ini menggunakan JobIntentService saat yang tepat, tetapi memiliki plat boiler jauh lebih sedikit.
TALE
36

Jika layanan ini berjalan di utas latar belakang dengan memperluas IntentService, Anda dapat mengganti IntentServicedengan JobIntentServiceyang disediakan sebagai bagian dari Perpustakaan Dukungan Android

Keuntungan menggunakan JobIntentServiceadalah, berperilaku sebagai perangkat IntentServicepra-O dan pada O dan lebih tinggi, mengirimkannya sebagai pekerjaan

JobSchedulerjuga dapat digunakan untuk pekerjaan yang diminta secara berkala / sesuai permintaan. Tetapi, pastikan untuk menangani kompatibilitas mundur karena JobSchedulerAPI hanya tersedia dari API 21

Harini S
sumber
1
Masalah dengan JobIntentService adalah bahwa Android dapat menjadwalkan pekerjaan Anda secara sewenang-wenang, dan itu tidak dapat dimulai secara tersirat tanpa bermain-main, tidak seperti IntentService. Lihat stackoverflow.com/questions/52479262/...
kilokahn
15

Di Oreo, Android membatasi batas layanan latar belakang .

Untuk meningkatkan pengalaman pengguna, Android 8.0 (API level 26) memberlakukan batasan pada apa yang dapat dilakukan aplikasi saat berjalan di latar belakang.

Namun jika Anda selalu perlu menjalankan layanan, maka Anda dapat menggunakan layanan latar depan.

Batasan Layanan Latar Belakang: Saat aplikasi tidak digunakan, ada batasan penggunaan layanan latar belakang. Ini tidak berlaku untuk layanan latar depan, yang lebih terlihat oleh pengguna.

Jadi, Anda dapat membuat layanan latar depan . Anda harus menunjukkan pemberitahuan kepada pengguna saat layanan Anda berjalan. Lihat jawaban ini (Ada banyak lainnya)

Solusi jika -

Anda tidak ingin pemberitahuan untuk layanan Anda?

Anda dapat membuat tugas berkala, 1. memulai layanan Anda, 2. layanan akan melakukan tugasnya dan 3. berhenti sendiri. Dengan ini aplikasi Anda tidak akan dianggap menguras baterai.

Anda dapat menggunakan tugas berkala dengan Manajer Alarm , Penjadwal Pekerjaan , Evernote-Jobs atau Work Manager .

  • Manajer kerja adalah solusi terbaik untuk tugas-tugas berkala. Yang diperkenalkan dengan Komponen Arsitektur Android .
  • Tidak seperti Penjadwal-Pekerjaan (hanya> 21 API) ini akan berfungsi untuk semua versi.
  • Juga mulai berfungsi setelah mode Doze-Standby .
  • Buat Penerima Boot Android untuk layanan penjadwalan setelah perangkat boot.

Saya telah menguji selamanya menjalankan layanan dengan Work-Manager.

Khemraj
sumber
WorkManager sepertinya adalah cara terbaik untuk pergi, dengan asumsi pekerjaan itu tidak harus dijalankan segera. Ini kompatibel dengan API 14, menggunakan JobScheduler pada perangkat dengan API 23+ dan kombinasi BroadcastReceiver + AlarmManager pada perangkat dengan API 14-22
James Allen
hal utama tentang WorkManager adalah WorkManager dimaksudkan untuk tugas-tugas yang dapat ditunda — yaitu, tidak diharuskan untuk segera dijalankan
touhid udoy
13

Ya, itu karena Anda tidak dapat memulai layanan di latar belakang lagi di API 26. Jadi Anda dapat memulai ForegroundService di atas API 26.

Anda harus menggunakan

ContextCompat.startForegroundService(...)

dan memposting pemberitahuan saat memproses kebocoran.

PK
sumber
1
OP secara khusus mengatakan dia tidak ingin sebagai latar depan. Ini harus dimasukkan sebagai komentar atau sebagai bagian dari jawaban yang lebih lengkap.
Ricardo A.
7

Seperti @kosev katakan dalam jawabannya Anda dapat menggunakan JobIntentService. Tapi saya menggunakan solusi alternatif - saya menangkap IllegalStateException dan memulai layanan sebagai latar depan. Misalnya, fungsi ini memulai layanan saya:

@JvmStatic
protected fun startService(intentAction: String, serviceType: Class<*>, intentExtraSetup: (Intent) -> Unit) {
    val context = App.context
    val intent = Intent(context, serviceType)
    intent.action = intentAction
    intentExtraSetup(intent)
    intent.putExtra(NEED_FOREGROUND_KEY, false)

    try {
        context.startService(intent)
    }
    catch (ex: IllegalStateException) {
        intent.putExtra(NEED_FOREGROUND_KEY, true)
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            context.startForegroundService(intent)
        }
        else {
            context.startService(intent)
        }
    }
}

dan ketika saya memproses Intent saya melakukan hal seperti itu:

override fun onHandleIntent(intent: Intent?) {
    val needToMoveToForeground = intent?.getBooleanExtra(NEED_FOREGROUND_KEY, false) ?: false
    if(needToMoveToForeground) {
        val notification = notificationService.createSyncServiceNotification()
        startForeground(notification.second, notification.first)

        isInForeground = true
    }

    intent?.let {
        getTask(it)?.process()
    }
}
Alex Shevelev
sumber
Saya suka solusi try catch Anda. Bagi saya itu adalah solusi karena kadang-kadang context.startServicebekerja di latar belakang - kadang-kadang tidak - terlihat ini seperti satunya cara terbaik jika Anda harus menerapkan kode lebih banyak di kelas utama Anda extending Applicationdan implementing ActivityLifecycleCallbacksdan melacak apakah aplikasi ini di latar depan atau latar belakang dan mulai niat Anda demikian.
Pierre
Bisakah pengecualian ini ditangkap?
thecr0w
5

Dari catatan rilis firebase , mereka menyatakan bahwa dukungan untuk Android O pertama kali dirilis pada 10.2.1 (walaupun saya akan merekomendasikan menggunakan versi terbaru).

silakan tambahkan dependensi pesan berbasis firebase baru untuk Android O

compile 'com.google.firebase:firebase-messaging:11.6.2'

tingkatkan layanan google play dan repositori google jika diperlukan.

Dhaval Jivani
sumber
Ini tidak menjawab pertanyaan, atau pertanyaan itu tidak ada hubungannya dengan firebase. Itu harus dimasukkan sebagai komentar.
Ricardo A.
5

Jika ada niat yang sebelumnya berfungsi dengan baik ketika aplikasi di latar belakang, itu tidak akan terjadi lagi dari Android 8 dan di atas. Hanya merujuk pada niat yang harus melakukan pemrosesan ketika aplikasi berada di latar belakang.

Langkah-langkah di bawah ini harus diikuti:

  1. Niat yang disebutkan di atas harus menggunakan JobIntentServicebukan IntentService.
  2. Kelas yang meluas JobIntentServiceharus mengimplementasikan onHandleWork(@NonNull Intent intent)metode - dan harus memiliki di bawah metode, yang akan memanggil onHandleWorkmetode:

    public static void enqueueWork(Context context, Intent work) {
        enqueueWork(context, xyz.class, 123, work);
    }
  3. Panggil enqueueWork(Context, intent)dari kelas di mana maksud Anda ditentukan.

    Kode sampel:

    Public class A {
    ...
    ...
        Intent intent = new Intent(Context, B.class);
        //startService(intent); 
        B.enqueueWork(Context, intent);
    }

Kelas di bawah ini sebelumnya memperluas kelas Layanan

Public Class B extends JobIntentService{
...

    public static void enqueueWork(Context context, Intent work) {
        enqueueWork(context, B.class, JobId, work);
    }

    protected void onHandleWork(@NonNull Intent intent) {
        ...
        ...
    }
}
  1. com.android.support:support-compatdiperlukan untuk JobIntentService- saya gunakan 26.1.0 V.

  2. Yang paling penting adalah untuk memastikan versi Firebase libraries aktif setidaknya 10.2.1, saya punya masalah dengan 10.2.0- jika Anda punya!

  3. Manifes Anda harus memiliki izin di bawah ini untuk kelas Layanan:

    service android:name=".B"
    android:exported="false"
    android:permission="android.permission.BIND_JOB_SERVICE"

Semoga ini membantu.

chitraju chaithanya
sumber
4

Saya melihat banyak tanggapan yang merekomendasikan hanya menggunakan ForegroundService. Untuk menggunakan ForegroundService harus ada pemberitahuan yang terkait dengannya. Pengguna akan melihat pemberitahuan ini. Bergantung pada situasinya, mereka mungkin terganggu dengan aplikasi Anda dan mencopotnya.

Solusi termudah adalah dengan menggunakan Komponen Arsitektur baru yang disebut WorkManager. Anda dapat melihat dokumentasi di sini: https://developer.android.com/topic/libraries/architecture/workmanager/

Anda cukup mendefinisikan kelas pekerja Anda yang memperpanjang Pekerja.

public class CompressWorker extends Worker {

    public CompressWorker(
        @NonNull Context context,
        @NonNull WorkerParameters params) {
        super(context, params);
    }

    @Override
    public Worker.Result doWork() {

        // Do the work here--in this case, compress the stored images.
        // In this example no parameters are passed; the task is
        // assumed to be "compress the whole library."
        myCompress();

        // Indicate success or failure with your return value:
        return Result.SUCCESS;

        // (Returning RETRY tells WorkManager to try this task again
        // later; FAILURE says not to try again.)
    }
}

Kemudian Anda menjadwalkan kapan Anda ingin menjalankannya.

    OneTimeWorkRequest compressionWork = 
        new OneTimeWorkRequest.Builder(CompressWorker.class)
            .build();
    WorkManager.getInstance().enqueue(compressionWork);

Mudah! Ada banyak cara Anda dapat mengkonfigurasi pekerja. Ini mendukung pekerjaan berulang dan Anda bahkan dapat melakukan hal-hal rumit seperti merantai jika Anda membutuhkannya. Semoga ini membantu.

KISAH
sumber
3
Saat ini WorkManager masih alpha.
pzulw
3
05 Maret 2019 - WorkManager rilis stabil 1.0.0.
phnmnn
harus menggunakan WorkManager alih-alih menggunakan interservice atau JobIntentService
sivaBE35
1
WorkManager is intended for tasks that are deferrable—that is, not required to run immediately... mungkin paling mudah, namun, aplikasi saya membutuhkan layanan latar belakang yang segera mengeksekusi permintaan pengguna!
Seseorang di suatu tempat
Jika Anda membutuhkan tugas yang harus diselesaikan segera, maka Anda harus menggunakan layanan latar depan. Pengguna akan melihat pemberitahuan dan tahu bahwa Anda sedang melakukan pekerjaan. Periksa dokumen jika Anda perlu bantuan memutuskan apa yang akan digunakan. Mereka memiliki panduan yang cukup bagus untuk pemrosesan latar belakang. developer.android.com/guide/background
TALE
4

Alternatif solusi dengan menggunakan JobScheduler, dapat memulai layanan di latar belakang dalam interval waktu yang teratur.

Pertama-tama buatlah kelas dengan nama Util.java

import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.content.ComponentName;
import android.content.Context;

public class Util {
// schedule the start of the service every 10 - 30 seconds
public static void schedulerJob(Context context) {
    ComponentName serviceComponent = new ComponentName(context,TestJobService.class);
    JobInfo.Builder builder = new JobInfo.Builder(0,serviceComponent);
    builder.setMinimumLatency(1*1000);    // wait at least
    builder.setOverrideDeadline(3*1000);  //delay time
    builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED);  // require unmetered network
    builder.setRequiresCharging(false);  // we don't care if the device is charging or not
    builder.setRequiresDeviceIdle(true); // device should be idle
    System.out.println("(scheduler Job");

    JobScheduler jobScheduler = null;
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
        jobScheduler = context.getSystemService(JobScheduler.class);
    }
    jobScheduler.schedule(builder.build());
   }
  }

Kemudian, buat kelas JobService dinamai TestJobService.java

import android.app.job.JobParameters;
import android.app.job.JobService;
import android.widget.Toast;

  /**
   * JobService to be scheduled by the JobScheduler.
   * start another service
   */ 
public class TestJobService extends JobService {
@Override
public boolean onStartJob(JobParameters params) {
    Util.schedulerJob(getApplicationContext()); // reschedule the job
    Toast.makeText(this, "Bg Service", Toast.LENGTH_SHORT).show();
    return true;
}

@Override
public boolean onStopJob(JobParameters params) {
    return true;
  }
 }

Setelah itu kelas Penerima BroadCast bernama ServiceReceiver.java

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

 public class ServiceReceiver extends BroadcastReceiver {
 @Override
public void onReceive(Context context, Intent intent) {
    Util.schedulerJob(context);
 }
}

Perbarui file Manifes dengan kode kelas layanan dan penerima

<receiver android:name=".ServiceReceiver" >
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>
    <service
        android:name=".TestJobService"
        android:label="Word service"
        android:permission="android.permission.BIND_JOB_SERVICE" >

    </service>

Meninggalkan peluncur main_intent ke file mainActivity.java yang dibuat secara default, dan perubahan pada file MainActivity.java adalah

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Util.schedulerJob(getApplicationContext());
  }
 }

WOOAAH !! Layanan Latar Belakang dimulai tanpa layanan Foreground

Anshul1507
sumber
2

Jika Anda menjalankan kode pada 8.0 maka aplikasi akan macet. Jadi, mulailah layanan di latar depan. Jika di bawah 8,0 gunakan ini:

Intent serviceIntent = new Intent(context, RingtonePlayingService.class);
context.startService(serviceIntent);

Jika di atas atau 8.0 maka gunakan ini:

Intent serviceIntent = new Intent(context, RingtonePlayingService.class);
ContextCompat.startForegroundService(context, serviceIntent );
iamfaizuddin
sumber
Disarankan untuk hanya menggunakan layanan Foreground untuk kasus-kasus di mana pengguna perlu menyadari bahwa layanan sedang berjalan. Contoh khas adalah untuk memutar musik di latar belakang. Ada kasus-kasus lain yang masuk akal, tetapi Anda tidak boleh hanya mengubah semua layanan Anda ke layanan Foreground. Pertimbangkan mengonversi layanan Anda untuk menggunakan WorkManager dari komponen Arsitektur Google ketika Anda hanya perlu melakukan beberapa pekerjaan di latar belakang dan dijamin itu akan berjalan.
TALE
startForegroundService memerlukan izin, jika tidak java.lang.SecurityException: Permission Denial: startForeground from pid=13708, uid=10087 requires android.permission.FOREGROUND_SERVICE. Perbaiki di stackoverflow.com/a/52382711/550471
Seseorang di suatu tempat
1

jika Anda telah mengintegrasikan pemberitahuan push pesan berbasis firebase,

Tambahkan / perbarui dependensi pesan berbasis firebase baru untuk android O (Android 8.0), karena Batas Eksekusi Latar Belakang .

compile 'com.google.firebase:firebase-messaging:11.4.0'

tingkatkan layanan google play dan repositori google jika diperlukan.

Memperbarui:

 compile 'com.google.firebase:firebase-messaging:11.4.2'
Samir Mangroliya
sumber
0

Gunakan startForegroundService()sebagai ganti startService() dan jangan lupa untuk membuat startForeground(1,new Notification());dalam layanan Anda dalam waktu 5 detik dari layanan awal.

Arpit
sumber
2
Tampaknya Pemberitahuan baru () tidak berfungsi dari Android 8.1; Anda harus membuat saluran untuk pemberitahuan: stackoverflow.com/a/47533338/1048087
Prizoff
0

Karena suara kontroversial pada jawaban ini (+ 4 / -4 pada edit ini), TOLONG LIHAT JAWABAN LAINNYA, PERTAMA DAN GUNAKAN HANYA INI SEBAGAI RESORT TERAKHIR . Saya hanya menggunakan ini sekali untuk aplikasi jaringan yang berjalan sebagai root dan saya setuju dengan pendapat umum bahwa solusi ini tidak boleh digunakan dalam keadaan normal.

Jawaban asli di bawah ini:

Jawaban lainnya semuanya benar, tetapi saya ingin menunjukkan bahwa cara lain untuk menyiasatinya adalah dengan meminta pengguna menonaktifkan pengoptimalan baterai untuk aplikasi Anda (ini biasanya bukan ide yang baik kecuali jika aplikasi Anda terkait sistem). Lihat jawaban ini untuk cara meminta keluar dari optimisasi baterai tanpa membuat aplikasi Anda dilarang di Google Play.

Anda juga harus memeriksa apakah optimisasi baterai dimatikan pada penerima Anda untuk mencegah crash melalui:

if (Build.VERSION.SDK_INT < 26 || getSystemService<PowerManager>()
        ?.isIgnoringBatteryOptimizations(packageName) != false) {
    startService(Intent(context, MyService::class.java))
} // else calling startService will result in crash
Tuhanku
sumber
1
Meminta pengguna Anda untuk memberi Anda izin masuk gratis menggunakan baterai sebanyak mungkin bukanlah solusi yang baik. Pertimbangkan untuk mengubah kode Anda menjadi solusi yang lebih ramah baterai. Pengguna Anda akan berterima kasih.
TALE
5
@TALE Tidak semua layanan latar belakang dapat dibuat menggunakan JobSchedulerdan hal-hal ramah baterai . Beberapa aplikasi perlu bekerja pada level yang lebih rendah daripada aplikasi sinkronisasi biasa. Ini adalah solusi alternatif ketika itu tidak berhasil.
Mygod
-17

jangan gunakan di onStartCommand:

return START_NOT_STICKY

ubah saja ke:

return START_STICKY

dan itu akan berhasil

Omar Othman
sumber