Bagaimana cara menangani kode saat aplikasi dimatikan dengan menggesekkan di android?

104

Jika aplikasi saya berjalan dan saya menekan tombol beranda, aplikasi tersebut berjalan di latar belakang. Sekarang jika lama menekan tombol home dan mematikan aplikasi dengan menggeseknya dari daftar aplikasi terbaru, tidak ada kejadian seperti onPause(), onStop()atau onDestroy()dipanggil sebaliknya proses dihentikan. Jadi, jika saya ingin layanan saya berhenti, mematikan notifikasi, dan membatalkan pendaftaran pendengar, bagaimana saya bisa melakukannya? Saya membaca beberapa artikel dan blog tetapi tidak mendapatkan informasi yang berguna dan saya belum menemukan dokumentasi apa pun tentangnya. Bantuan apa pun akan dihargai. Terima kasih sebelumnya.

CodeWarrior
sumber
Saya menyelesaikan masalah saya. Periksa
MysticMagicϡ
@MysticMagic Itu berfungsi untuk Layanan, bagaimana dengan membatalkan Notifikasi dan membatalkan pendaftaran pendengar?
CodeWarrior
Anda dapat membatalkan pendaftaran listener di onTaskRemoved. Tidak bisakah kamu Dan sama untuk membatalkan pemberitahuan
MysticMagicϡ
@ MysticMagicϡ Bagaimana jika saya ingin melakukan hal yang sama pada pembaruan aplikasi?
reji

Jawaban:

150

Saya baru saja menyelesaikan masalah serupa.

Inilah yang dapat Anda lakukan jika ini hanya tentang menghentikan layanan saat aplikasi dimatikan dengan menggesek dari daftar Aplikasi terbaru.

Di dalam file Manifest Anda, tetap bendera stopWithTasksebagai trueJasa. Suka:

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

Tetapi seperti yang Anda katakan Anda ingin membatalkan pendaftaran pendengar dan menghentikan pemberitahuan, dll., Saya menyarankan pendekatan ini:

  1. Di dalam file Manifest Anda, tetap bendera stopWithTasksebagai falseJasa. Suka:

    <service
        android:name="com.myapp.MyService"
        android:stopWithTask="false" />
    
  2. Sekarang di MyServicelayanan Anda , ganti metode onTaskRemoved. (Ini akan diaktifkan hanya jika stopWithTaskdiatur ke false).

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

Lihat pertanyaan saya untuk lebih jelasnya, yang juga berisi bagian lain dari kode.

Semoga ini membantu.

MysticMagicϡ
sumber
Terima kasih. Berpikir jika metode ini dapat digunakan untuk mengidentifikasi pembunuhan gesek. Layanan kosong sederhana?
Kiran
Ya @kiran bisa dicoba. :)
MysticMagicϡ
1
@ MysticMagicϡ hai, satu pertanyaan, saya mencoba menggunakan solusi Anda, tetapi tampaknya operasi yang lama seperti mengirim data ke server, analitik ke google, dll. Beberapa kali gagal sepenuhnya. Mungkinkah prosesnya mati sebelum metode ini memiliki kesempatan untuk menyelesaikan sendiri sepenuhnya? Apakah Anda juga sudah mencoba metode ini pada perangkat Huawei? Sepertinya onTaskRemoved tidak pernah dipanggil di perangkat tersebut. Ada ide mengapa?
Alon Minski
2
@ MysticMagicϡ public void onTaskRemoved (..) Metode tidak memanggil di Android O. Bekerja dengan baik di OS lain tetapi mendapatkan masalah di Android O.
Jay Patel
2
Kode ini tidak berfungsi untuk Android O karena batasan Layanan latar belakang. Apakah ada cara untuk menangani ini di semua perangkat Android?
Aanal Mehta
33

Menemukan satu cara untuk melakukan ini

buat satu layanan seperti ini

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) daftarkan layanan ini di manifest.xml

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

3) Kemudian mulai layanan ini pada aktivitas percikan Anda

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

Dan sekarang setiap kali Anda akan menghapus aplikasi Anda dari android recent maka metode ini onTaskRemoved () akan dijalankan.

emilpmp
sumber
1
Satu ke satu salin dan tempel dari jawaban ini: stackoverflow.com/questions/21040339
Flot2011
17

Saya menyelesaikan masalah serupa. Jika Anda ingin setelah menggesek dari tugas terbaru dan pada peluncuran berikutnya untuk berperilaku dengan benar, ikuti langkah-langkah di bawah ini: -

1) Simpan ID proses dalam preferensi bersama:

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

2) Saat aplikasi diluncurkan dari peluncur setelah menghapus dari tugas terbaru, lakukan:

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
}
Anshul Agarwal
sumber
Dikonfirmasi - digunakan di Android 8 tanpa layanan. OnTaskRemoved () - selesai dengan baik
Gal Rom
4
Solusi ini hanya mendeteksi jika aplikasi dimulai ulang, tetapi Anda tidak dapat mendeteksi saat yang tepat ketika aplikasi dimatikan
Vadim Kotov
6

Saat Anda menekan tombol home - onPausedan onStopAktivitas Anda dipanggil, jadi saat ini Anda harus melakukan semua penghematan dan pembersihan, karena platform Android tidak lagi menjamin bahwa onDestroyatau metode siklus hidup lainnya akan dipanggil, sehingga prosesnya dapat dihentikan tanpa pemberitahuan apapun.

Gurun
sumber
12
Terima kasih atas sarannya, tetapi saya tidak ingin mematikan notifikasi, layanan, dan pendengar saya, onPause()dan onstop()mereka hanya perlu dimatikan ketika pengguna keluar dari aplikasi yaitu logout.
CodeWarrior
1

Anda perlu menyimpan data Anda saat aktif onPause()dipanggil. Lihat diagram siklus hidup ini: Pengembang Android

Anda dapat melihat bahwa aplikasi dapat dimatikan setelah onPause()atau onStop().

Tangani data Anda di sana dan pulihkan di onRestart()\ onCreate().

semoga berhasil!

Fashizel
sumber
1

Anda tidak dapat menangani gesekan, karena sistem hanya menghapus proses Anda dari memori tanpa memanggil panggilan balik apa pun.

Saya telah memeriksa, bahwa sebelum pengguna memanggil layar "aplikasi terbaru", onPause () akan selalu dipanggil. Jadi, Anda perlu menyimpan semua data dalam metode onPause tanpa memeriksa isFinishing ().

Untuk memeriksa tombol kembali, gunakan metode onBackPressed.

Ahmad
sumber
1
Saya yakin ini adalah satu-satunya metode aman untuk semua versi Android.
Sergio
@Sergio ya itu adalah metode teraman dan saya mengujinya pada Aplikasi skala yang lebih besar.
Ahmad
1

ViewModel. [Beginilah awalnya saya sampai pada pertanyaan ini].

Aplikasi tidak mendapatkan notifikasi, dan Activity.onDestroy () dipanggil untuk perubahan konfigurasi seperti perubahan orientasi, jadi jawabannya tidak ada. Tapi ViewModel.onCleared dipanggil saat Aplikasi dihapus (serta saat pengguna mundur dari aktivitas). Jika sumber daya yang ingin Anda gunakan dikaitkan dengan lebih dari satu aktivitas dalam tumpukan, Anda dapat menambahkan jumlah referensi atau mekanisme lain untuk memutuskan apakah ViewModel.onClear harus merilis sumber daya.

Ini adalah satu lagi dari banyak alasan bagus untuk menggunakan ViewModel.

- Bob

Bob Cram
sumber
1

Saya tidak begitu tahu mengapa pendekatan di atas tidak berfungsi pada kasus saya bahkan saya menetapkan android:stopWithTask="false"yang onTaskRemoved()tidak dipanggil.

Pendekatan bagus lainnya akan digunakan AndroidViewModel. Yang ini bahkan berfungsi pada kasus ketika pengguna keluar dari aplikasi dengan menekan tombol kembali.

Cukup terikat ViewModelkelas ke Anda MainActivitylalu lakukan onCleared()panggilan balik tugas Anda .

Contoh:

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();
    }
}

lalu ikat ke MainActivity Anda:

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

~ Voila!

droidhs
sumber
itu mungkin tidak bekerja dengan pendekatan layanan karena Android O dan di atasnya seperti yang disebutkan oleh pemberi komentar lain. Ini sepertinya solusi yang menarik untuk memanfaatkan model tampilan untuk ini. Apakah ini masih dipicu jika aplikasi dimatikan paksa (digesek di layar pengalih aplikasi)? sunting: Jawaban Bob menyarankan itu berhasil dalam kasus ini
William Reed
ya berhasil, itulah kasus yang saya temui
droidhs
0

Ini bekerja untuk saya di android 6,7,8,9.

Buat satu layanan seperti ini:

 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) Daftarkan layanan ini di manifest.xml:

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

3) Kemudian mulai layanan ini pada aktivitas percikan Anda

 startService(new Intent(getBaseContext(),
 OnClearFromRecentService.class));
Alexis Osorio
sumber
1
Dan mengapa layanan Anda tetap berjalan di Android 8 ke atas? Anda menyadari bahwa ada batasan pada Layanan yang Dimulai setelah Android 8, bukan?
rahil008
0

Seperti yang disebutkan Bob Cram dalam jawabannya, metode onCleared () View Model adalah jawabannya. Ini berfungsi dalam kedua kasus:

  1. Saat pengguna menghapus aplikasi dengan menggesek aplikasi dari latar belakang.
  2. Saat pengguna menghapus semua aplikasi menggunakan tombol hapus daftar.

Layanan onTaskRemoved () akan berfungsi saat pengguna menggesek aplikasi dari latar belakang, tetapi tidak akan berfungsi saat aplikasi dihapus menggunakan tombol tutup semua.

Namun metode onCleared () viewModel berfungsi di kedua kasus. Anda dapat menggunakan if untuk menghentikan proses yang sedang berlangsung atau menghapus tugas apa pun di server jarak jauh.

 override fun onCleared() {
        super.onCleared()
        Log.d(TAG , "App Killed")
    }
Utkarsh Singh
sumber