Maksud - jika aktivitas sedang berjalan, bawa ke depan, kalau tidak mulailah yang baru (dari notifikasi)

129

Aplikasi saya memiliki notifikasi, yang - jelas - tanpa tanda, memulai aktivitas baru setiap kali jadi saya mendapatkan beberapa aktivitas yang sama berjalan di atas satu sama lain, yang hanya salah.

Yang ingin saya lakukan adalah membawa aktivitas yang ditentukan dalam pemberitahuan menunggu keputusan, ke depan jika sudah berjalan, jika tidak, mulailah.

Sejauh ini, niat / niat menunggu untuk pemberitahuan yang saya miliki adalah

private static PendingIntent prepareIntent(Context context) {
    Intent intent = new Intent(context, MainActivity.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);

    return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}

dan anehnya, kadang-kadang berhasil, kadang tidak ... Saya merasa seperti saya sudah mencoba setiap kombinasi bendera.

urus
sumber

Jawaban:

131

Anda bisa menggunakan ini:

<activity 
   android:name=".YourActivity"
   android:launchMode="singleTask"/>

yang akan bekerja mirip "singleInstance"tetapi tidak memiliki animasi aneh.

Franco
sumber
15
+1, Anda harus menjadi jawaban yang diterima. Perbedaannya ada di sini: developer.android.com/guide/topics/manifest/…
user1032613
1
Untuk memperjelas, gunakan singleTask jika Anda memiliki beberapa aktivitas dalam aplikasi dan ini adalah induknya, singleInstance jika Anda hanya memiliki satu Aktivitas.
frostymarvelous
4
Jika ada orang seperti saya telah mencoba banyak kombinasi solusi sebelum berakhir di situs ini: Pastikan untuk menyingkirkan perubahan lain yang Anda coba dan pastikan Anda melakukan perubahan ini pada aktivitas yang benar. Butuh waktu terlalu lama untuk mengetahui bahwa solusi ini akan berhasil jika saya belum mencoba solusi lain juga (mis. Mengganti onNewIntentdan mengatur bendera)
mengganti
Saya memiliki peta Messenger, Pasangan aktivitas. Saya ingin menampilkan instance Activity jika saya mendapat pesan darinya. Apakah ada cara untuk melakukan ini? misal: HashMap.get (Messenger) .bringActivityToFront (); Maksudku, aktivitasnya masih berjalan. Jika saya membuka tugas terbaru dan mengkliknya, itu akan onResume (); Cant I onResume () secara pemrograman.
@JaveneCPPMcGowan yang sepertinya merupakan pertanyaan yang berbeda sama sekali, saya sarankan Anda memposting karena itu pertanyaan sendiri, sayangnya saya tidak tahu jawabannya.
Franco
46

Saya pikir cara terbaik untuk melakukannya dan secara sederhana adalah memulai aktivitas secara normal, tetapi atur aktivitas itu dalam manifes dengan singleInstanceproperti. Dengan ini, Anda secara praktis mendekati kedua masalah yang Anda alami saat ini, dengan membawa aktivitas ke depan sepanjang waktu, dan membiarkan OS secara otomatis membuat yang baru jika tidak ada aktivitas atau membawa ke depan aktivitas yang saat ini ada (berkatsingleInstance Properti).

Ini adalah cara aktivitas dinyatakan sebagai satu kejadian:

<activity 
   android:name=".YourActivity"
   android:launchMode="singleInstance"/>

Juga untuk menghindari animasi berombak ketika diluncurkan melalui singleInstance, Anda bisa menggunakan "singleTask", keduanya sangat mirip tetapi perbedaannya dijelaskan di sini sesuai dokumentasi Google:

<activity 
   android:name=".YourActivity"
   android:launchMode="singleTask"/>

singleInstance sama dengan "singleTask", kecuali bahwa sistem tidak meluncurkan aktivitas lain ke dalam tugas memegang instance. Aktivitas selalu menjadi satu-satunya anggota dari tugasnya.

Semoga ini membantu.

Salam!

Martin Cazares
sumber
4
kelihatannya berhasil, tetapi sekarang setiap aktivitas baru yang saya luncurkan dari singleIntent MainActivity, mainkan animasi melengkung yang aneh ini alih-alih pudar & skala biasa
urSus
Bagaimana dengan saya meluncurkan aktivitas baru setiap kali tetapi menghapus semua contoh menjalankannya, apakah itu mungkin?
urSus
Yah, saya rasa animasi yang Anda sebutkan tidak ada hubungannya dengan properti "singleInstance", yang ia lakukan hanyalah menggunakan contoh yang ada, mungkin animasi yang Anda bicarakan adalah masalah yang sama sekali berbeda ...
Martin Cazares
1
baik saya sedang mengujinya sekarang dan itu benar. Jika saya menghapus semua flag maksud dan hanya mengatur launchMode = "singleInstance" di manifes, animasi aneh ada di sana, jika saya menghapusnya, kembali ke normal
urSus
Ya, menurut dokumentasi android, sepertinya animasi "init" tidak ada lagi seperti biasanya karena aktivitasnya tidak diinisialisasi, hanya digunakan kembali ...
Martin Cazares
26

Saya pikir apa yang Anda butuhkan ada dalam singleTop Activity, daripada a singleTaskatau singleInstance.

<activity android:name=".MyActivity"
          android:launchMode="singleTop"
          ...the rest... >

Apa yang dikatakan dokumentasi tidak sesuai dengan kebutuhan Anda:

[...] contoh baru dari "singleTop aktivitas " juga dapat dibuat untuk menangani maksud baru. Namun, jika tugas target sudah memiliki instance aktivitas yang ada di bagian atas stacknya, instance tersebut akan menerima maksud baru (dalam onNewIntent()panggilan); contoh baru tidak dibuat. Dalam keadaan lain - misalnya, jika instance singleTopaktivitas " " yang ada ada di tugas target, tetapi tidak di bagian atas tumpukan, atau jika itu di bagian atas tumpukan, tetapi tidak di tugas target - yang baru Misalnya akan dibuat dan didorong pada stack.

Selain itu (tidak ada permainan kata-kata yang dimaksudkan), saya memiliki kebutuhan yang persis sama dengan Anda. Saya menguji semua launchModeflag untuk mengetahui bagaimana mereka sebenarnya berperilaku dalam praktek dan sebagai hasilnya singleTopsebenarnya yang terbaik untuk ini: tidak ada animasi aneh, aplikasi ditampilkan sekali dalam daftar aplikasi terbaru (tidak seperti singleInstanceyang menampilkannya dua kali karena kenyataannya tidak ' t izinkan orang lain Activityuntuk menjadi bagian dari tugasnya), dan lakukan dengan benar terlepas dari target yang Activitysudah ada atau tidak.

Shlublu
sumber
2
Bekerja sampai 10 malam pada hari Jumat malam dan ini yang saya inginkan ... Sedih kehidupan pengembang.
felixwcf
Menghemat banyak waktu saya! Terima kasih!
hetsgandhi
13

Ini adalah utas lama, tetapi bagi semua yang masih mencari jawaban, inilah solusi saya. Ini murni dalam kode, tanpa pengaturan nyata:

private static PendingIntent prepareIntent(Context context) {
  Intent intent = new Intent(context, MainActivity.class);
  intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);      
  return PendingIntent.getActivity(context, NON_ZERO_REQUEST_CODE, intent, 
    PendingIntent.FLAG_UPDATE_CURRENT);
}

Di sini FLAG_ACTIVITY_SINGLE_TOP membuka aktivitas yang ada jika berada di bagian atas tumpukan tugas. Jika tidak di atas, tetapi di dalam tumpukan, FLAG_ACTIVITY_CLEAR_TOP akan menghapus semua aktivitas di atas aktivitas target dan menunjukkannya. Jika aktivitas tidak ada di tumpukan tugas, yang baru akan dibuat. Poin yang sangat penting untuk disebutkan - parameter kedua dari PendingIntent.getActivity (), yaitu requestCode harus memiliki nilai bukan nol (saya bahkan menyebutnya NON_ZERO_REQUEST_CODE dalam cuplikan saya), jika tidak, bendera niat tersebut tidak akan berfungsi. Saya tidak tahu mengapa seperti itu. Tandai FLAG_ACTIVITY_SINGLE_TOP dapat dipertukarkan dengan android: launchMode = "singleTop" dalam tag aktivitas dalam manifes.

Andrey Koretskyy
sumber
Berjuang sejak jam dengan bendera ini dan bertanya-tanya mengapa mengubah bendera niat saya tidak mengubah apa pun. Kode permintaan tidak nol ... poin yang sangat penting untuk disebutkan !!! Sekarang bekerja! Terima kasih!
Max Power
9

Saya tahu ini sudah tua, tetapi tidak ada dari atas yang cocok untuk aplikasi saya.

Tanpa mengubah manifes dan konfigurasi lainnya, berikut adalah kode untuk membawa aplikasi Anda kembali ke depan - atau membukanya saat ditutup

Intent notificationIntent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
notificationIntent.setPackage(null); // The golden row !!!
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
Raziza O
sumber
Ini jawaban yang sebenarnya!
azizbekian
2
tidak, ini tidak berfungsi - itu menambah aktivitas baru di atas yang sekarang.
Tobliug
3

Saya mencoba ini, dan itu berhasil meskipun IDE mengeluh tentang kode

Intent notificationIntent = new Intent(THIS_CONTEXT, MainActivity.class);
    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
    PendingIntent intent = PendingIntent.getActivity(THIS_CONTEXT, 0, notificationIntent, Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);

    NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(THIS_CONTEXT)
            .setSmallIcon(R.drawable.cast_ic_notification_0)
            .setContentTitle("Title")
            .setContentText("Content")
            .setContentIntent(intent)
            .setPriority(PRIORITY_HIGH) //private static final PRIORITY_HIGH = 5;
            .setAutoCancel(true)
            /*.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS)*/;
    NotificationManager mNotificationManager = (NotificationManager) THIS_CONTEXT.getSystemService(Context.NOTIFICATION_SERVICE);
    mNotificationManager.notify(0, mBuilder.build());
nada
sumber
2
<activity android: name = ". MainActivity" android: launchMode = "singleTask">
nada
Intent.FLAG_ACTIVITY_REORDER_TO_FRONTbukan bendera yang valid untukPendingINtent.getActivity
rds
@rds Bisakah Anda menautkan sumbernya?
Louis CAD
@LouisCAD Maaf, saya tidak punya akses ke kode sumber lagi
nada
@ rds Saya tidak meminta kode sumber, tetapi untuk tautan tempat Anda membaca yang Intent.FLAG_ACTIVITY_REORDER_TO_FRONTbukan merupakan flag yang valid ketika digunakan sebagai a PendingIntent. Atau mungkin Anda bermaksud tidak valid untuk masuk ke getActivitymetode, tetapi apakah valid untuk digunakan sebagai Intentflag yang kemudian digunakan sebagai PendingIntent?
Louis CAD
2

Karena Anda mengatakan ingin memulai aktivitas jika belum dimulai, mungkin Anda tidak keberatan memulai kembali. Saya menguji banyak saran dan kombinasi bendera untuk maksud juga, ini akan selalu membawa aktivitas yang Anda butuhkan ke depan, meskipun itu tidak akan membuat negara yang sebelumnya terkait dengannya.

intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);

Hanya API11 +.

Shogun Gendut
sumber
0

Saya memiliki masalah serupa setelah menambahkan pemberitahuan seperti yang ditemukan di situs pelatihan android . Tidak ada jawaban lain di sini yang berfungsi untuk saya, namun jawaban ini berhasil untuk saya. Ringkasan:

final Intent notificationIntent = new Intent(context, YourActivity.class);
notificationIntent.setAction(Intent.ACTION_MAIN);
notificationIntent.addCategory(Intent.CATEGORY_LAUNCHER);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
gattsbr
sumber