Bagaimana cara memeriksa apakah suatu aktivitas adalah yang terakhir di tumpukan aktivitas untuk suatu aplikasi?

Jawaban:

116

UPDATE (Jul 2015):

Sejak getRunningTasks () mendapatkan usang, dari API 21 itu lebih baik untuk mengikuti raukodraug jawaban atau Ed Burnette satu (saya lebih suka satu detik).


Ada kemungkinan untuk memeriksa tugas saat ini dan tumpukannya menggunakan ActivityManager .

Jadi, untuk menentukan apakah suatu aktivitas adalah yang terakhir:

  • meminta izin android.permission.GET_TASKS di manifes.
  • Gunakan kode berikut:

    ActivityManager mngr = (ActivityManager) getSystemService( ACTIVITY_SERVICE );
    
    List<ActivityManager.RunningTaskInfo> taskList = mngr.getRunningTasks(10);
    
    if(taskList.get(0).numActivities == 1 &&
       taskList.get(0).topActivity.getClassName().equals(this.getClass().getName())) {
        Log.i(TAG, "This is last activity in the stack");
    }

Harap dicatat, kode di atas hanya akan berlaku jika Anda memiliki tugas tunggal. Jika ada kemungkinan sejumlah tugas akan ada untuk aplikasi Anda - Anda harus memeriksa elemen daftar tugas lainnya . Baca lebih lanjut tentang tugas Tasks dan Back Stack


sandrstar
sumber
25
H9kDroid telah memberikan saran yang benar. Jawaban yang dipilih adalah retasan. Seseorang harus melakukannya dengan cara yang benar menggunakan isTaskRoot()metode ini.
Sufian
@Sufian di mana itu hack khususnya? Kode ini logis dan menggunakan API Android terbuka dengan cara yang dimaksudkan untuk digunakan (misalnya getRunningTasks harus digunakan untuk menjalankan tugas dan seseorang mungkin ingin memanggilnya hanya dengan tujuan untuk menganalisis tugas ini). Penggunaan get (0) didokumentasikan dengan baik dan logis 'Kembalikan daftar tugas yang sedang berjalan, dengan yang terbaru menjadi yang pertama dan yang lebih lama setelahnya secara berurutan'.
sandrstar
2
getRunningTasks () tidak digunakan lagi di API level 21.
gilchris
Dapatkah saya melakukan hal yang sama untuk fragmen. Jika ya bagaimana caranya? Tolong bantu
Sagar Devanga
1
@ Mr. Drew melihat jawaban voting tertinggi dari @ raukodraug
David Wasser
167

Saya akan memposting komentar @ H9kDroid sebagai jawaban terbaik di sini untuk orang-orang yang memiliki pertanyaan serupa.

Anda bisa menggunakan isTaskRoot () untuk mengetahui apakah aktivitas adalah root tugas.

saya harap ini membantu

raukodraug
sumber
1
bisakah Anda memberikan satu baris kode sehingga jelas tentang cara menggunakan isTaskRoot. Terima kasih.
Kaveesh Kanwal
18
@TheHunterif (isTaskRoot()) { // do something }
howettl
3
Satu-satunya masalah adalah bahwa pada <= 4.4 saya melihatnya melakukan perilaku yang berbeda daripada di> = 5.x. Tampaknya selalu mengembalikan false.
chubbsondubs
Saya pikir Anda harus mempertimbangkan untuk memasukkan kode contoh yang disediakan di komentar ke dalam jawaban, untuk memudahkan pembaca di masa mendatang.
Isac
jawaban yang sangat bagus. dalam kasus saya setelah pengguna mengklik notifikasi, aktivitas tersebut mungkin root jika mereka menutup aplikasi sebelumnya
dave o grady
19

Semoga ini bisa membantu pemula baru, Berdasarkan jawaban di atas yang berfungsi dengan baik bagi saya, saya juga membagikan cuplikan kode sehingga akan mudah diterapkan.

solusi: saya menggunakan isTaskRoot()yang mengembalikan true jika aktivitas saat ini hanya aktivitas di tumpukan Anda dan selain saya juga menangani kasus di mana jika saya memiliki beberapa aktivitas di tumpukan pergi ke aktivitas terakhir dalam tumpukan alih-alih membuka yang baru kustom.

Dalam aktivitas Anda

   @Override
    public void onBackPressed() {

        if(isTaskRoot()){
            startActivity(new Intent(currentActivityName.this,ActivityNameYouWantToOpen.class));
            // using finish() is optional, use it if you do not want to keep currentActivity in stack
            finish();
        }else{
            super.onBackPressed();
        }

    }
Abhishek Garg
sumber
16

ada solusi termudah untuk ini, Anda bisa menggunakan isTaskRoot () dalam aktivitas Anda

Laxmikant Revdikar
sumber
5

Meskipun mungkin ada cara untuk mencapai ini (lihat jawaban lain), saya menyarankan agar Anda tidak melakukan itu. Aplikasi Android normal tidak perlu mengetahui apakah layar Utama akan ditampilkan atau tidak.

Jika Anda mencoba untuk menyimpan data, masukkan kode penyimpanan data dalam metode onPause () Anda. Jika Anda mencoba memberi pengguna cara untuk mengubah pikirannya tentang aplikasi yang sudah ada, Anda bisa mencegat tombol atas / bawah untuk tombol Kembali dan metode onBackPressed () dan menampilkan "Apakah Anda yakin?" cepat.

Ed Burnette
sumber
1
Bagaimana jika saya membutuhkan layanan yang berjalan selama pengguna belum meninggalkan aktivitas? Saya tidak bisa menangkap salah satu fungsi seperti onStop karena ini bisa dipanggil setelah layar dimatikan.
Michael
2
Jika layanan latar belakang meluncurkan suatu Aktivitas, mungkin Anda ingin tahu apakah itu satu-satunya Aktivitas di tumpukan atau tidak.
Matt W
4

Salah satu cara untuk melacaknya adalah dengan menyertakan penanda saat Anda memulai aktivitas baru dan memeriksa apakah penanda tersebut ada.

Setiap kali Anda memulai aktivitas baru, masukkan penanda:

newIntent=new Intent(this, NextOne.class);
newIntent.putExtra(this.getPackageName()+"myself", 0);
startActivity(newIntent);

Dan Anda kemudian dapat memeriksanya seperti ini:

boolean islast=!getIntent().hasExtra(this.getPackageName()+"myself")
H9kDroid
sumber
1
Tidak berfungsi jika aktivitas dimatikan dan tumpukan aktivitas direkonstruksi - setiap aktivitas berdasarkan permintaan.
AlikElzin-kilaka
3

Masalah dengan solusi sandrstar yang digunakan ActivityManageradalah: Anda memerlukan izin untuk mendapatkan tugas dengan cara ini. Saya menemukan cara yang lebih baik:

getIntent().hasCategory(Intent.CATEGORY_LAUNCHER)

Di Activitybagian bawah Stack selalu mendapatkan kategori ini secara default sementara Aktivitas lain tidak boleh mendapatkannya.
Tetapi meskipun ini gagal pada beberapa perangkat, Anda dapat mengaturnya saat memulai Activity:

Intent intent = new Intent(startingActivity, SomeActivityClass.class);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
activity.startActivity(intent);
A. Binzxxxxxx
sumber
Bagaimana jika aktivitas dibuka dari push notification? Mereka tidak memiliki CATEGORY LAUNCHER
nbtk
Saya yakin bagian kedua dari jawaban saya masih berlaku. Anda bisa menyetel kategori sebagai petunjuk dalam maksud. Dalam hal ini mungkin maksud dari konteks notifikasi Anda. Selain itu Anda juga bisa menggunakan flag untuk ini. lihat tautan ini untuk pembuatan notifikasi dengan maksud: stackoverflow.com/questions/13716723/…
A. Binzxxxxxx
Namun, Jika aktivitas terlama Anda adalah MainActivity dan sekarang dilanjutkan, lalu Anda menerima notifikasi push dan Anda menyetel pendingIntent untuk dibuka dengan CATEGORY_LAUNCHER, Anda akan memiliki 2 aktivitas dengan kategori ini. Mungkin pada tugas yang berbeda
nbtk
Saya tidak begitu yakin bagaimana cara kerjanya dengan notifikasi. Saya tidak pernah menggunakannya seperti Anda melakukannya di sini. Saya cukup yakin ada cara mudah untuk melakukannya dengan pendekatan ini tetapi saya tidak menyentuh kode android sejak Q1 2014. Mungkin Anda ingin menggunakan kategori kedua untuk kasus ini? Atau beberapa bendera? Tapi saya rasa ment untuk bekerja seperti ini. Bagaimana kalau memulai aktivitas utama dan menambahkan semacam info meta untuk membuka aktivitas yang benar?
A. Binzxxxxxx
2

Saya telah membuat kelas dasar untuk semua aktivitas saya, memperluas AppCompatActivity , dan yang memiliki penghitung statis:

public abstract class BasicActivity extends AppCompatActivity {
    private static int activityCounter = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ++activityCounter;
        ...
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        --activityCounter;
        if(activityCounter==0) {
            // Last instance code...
        }
    }

    public boolean isLastInstance() { return (activityCounter==1); }
}

Ini telah bekerja dengan cukup baik, sejauh ini; dan apa pun versi API-nya. Tentu saja diperlukan bahwa semua aktivitas memperluas kelas dasar ini - yang mereka lakukan, dalam kasus saya.

Edit: Saya perhatikan satu contoh ketika penghitung turun ke nol sebelum aplikasi benar-benar keluar, yaitu ketika orientasi diubah dan hanya satu aktivitas yang terbuka. Ketika orientasi berubah, aktivitas ditutup dan yang lain dibuat, sehingga onDestroyeddipanggil untuk aktivitas terakhir, dan kemudian onCreatedipanggil saat aktivitas yang sama dibuat dengan orientasi yang diubah. Perilaku ini harus diperhitungkan; OrientationEventListener mungkin dapat digunakan.

Per Löwgren
sumber
0

Android mengimplementasikan tumpukan Aktivitas, saya sarankan Anda membacanya di sini . Sepertinya semua yang ingin Anda lakukan meskipun adalah mengambil aktivitas panggilan: getCallingActivity(). Jika aktivitas saat ini adalah aktivitas pertama dalam aplikasi Anda dan aplikasi diluncurkan dari layar beranda, ini harus (saya asumsikan) kembali null.

Gyan alias Gary Buyn
sumber
9
Itu tidak akan berfungsi karena getCallingActivity () akan mengembalikan null jika aktivitas tidak dimulai melalui startActivityForResult ().
H9kDroid
0

Satu hal yang terlewat di sini, adalah klik "Tombol Beranda", ketika diaktifkan, Anda tidak dapat mendeteksi ini dari aktivitas Anda, jadi akan lebih baik untuk mengontrol tumpukan aktivitas secara terprogram dengan menangani penekanan "Tombol kembali" dan berpindah ke aktivitas yang diperlukan atau hanya melakukan langkah-langkah yang diperlukan.

Selain itu, Anda tidak bisa memastikan, bahwa memulai aktivitas Anda dari daftar "Aktivitas Terkini" bisa dideteksi dengan menyetel beberapa data tambahan ke dalam maksud untuk membuka aktivitas, karena digunakan kembali dalam kasus tersebut.

ACM64
sumber