Ý định - nếu hoạt động đang chạy, hãy đưa nó ra phía trước, bắt đầu một hoạt động mới (từ thông báo)


129

Ứng dụng của tôi có thông báo, rõ ràng - không có bất kỳ cờ nào, bắt đầu một hoạt động mới mỗi lần để tôi có nhiều hoạt động giống nhau chạy trên nhau, điều này là sai.

Những gì tôi muốn nó làm là đưa hoạt động được chỉ định trong mục đích chờ thông báo, lên phía trước nếu nó đang chạy, nếu không thì bắt đầu nó.

Cho đến nay, ý định / ý định chờ xử lý cho thông báo mà tôi có là

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

và thật kỳ lạ, đôi khi nó hoạt động, đôi khi không ... Tôi cảm thấy như mình đã thử mọi cách kết hợp cờ.

Câu trả lời:


131

Bạn có thể sử dụng điều này:

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

Nó sẽ hoạt động tương tự "singleInstance"nhưng nó sẽ không có hình ảnh động kỳ lạ đó.


15
+1, bạn nên là câu trả lời được chấp nhận. Sự khác biệt có ở đây: developer.android.com/guide/topics/manifest/ từ
user1032613

1
Để làm rõ, hãy sử dụng SingleTask nếu bạn có nhiều hoạt động trong ứng dụng và đây là cha mẹ, SingleInstance nếu bạn chỉ có một Hoạt động.
sương giá

4
Nếu bất kỳ ai như tôi đã thử nhiều kết hợp giải pháp trước khi chúng kết thúc trên trang web này: Hãy đảm bảo loại bỏ các thay đổi khác mà bạn đã thử và đảm bảo bạn thực hiện thay đổi này cho đúng hoạt động. Mất quá nhiều thời gian để biết rằng giải pháp này sẽ có hiệu quả nếu tôi cũng không thử các giải pháp khác (ví dụ: ghi đè onNewIntentvà đặt cờ)
lucidbrot

Tôi có một bản đồ của Messenger, cặp Activity. Tôi muốn hiển thị cá thể Activity nếu tôi nhận được tin nhắn từ nó. Có cách nào để làm điều này. ví dụ: HashMap.get (Messenger) .bringActivityToFront (); Ý tôi là, hoạt động vẫn đang chạy. Nếu tôi mở tác vụ gần đây và nhấp vào nó, nó sẽ onResume (); Không thể tôi onResume () lập trình.

@JaveneCPPMcGowan dường như là một câu hỏi hoàn toàn khác, tôi khuyên bạn nên đăng bài đó là câu hỏi của riêng mình, tôi thực sự không biết câu trả lời thật đáng tiếc.
Franco

46

Tôi nghĩ rằng cách tốt nhất để làm điều đó và một cách đơn giản là bắt đầu hoạt động bình thường, nhưng đặt hoạt động đó trong bảng kê khai với thuộc singleInstancetính. Với điều này, bạn thực sự tiếp cận cả hai vấn đề bạn đang gặp phải ngay bây giờ, bằng cách đưa hoạt động ra phía trước mọi lúc và để HĐH tự động tạo một vấn đề mới nếu không có hoạt động nào tồn tại hoặc đưa ra phía trước hoạt động hiện có (nhờ singleInstancebất động sản).

Đây là cách một hoạt động được khai báo như một thể hiện duy nhất:

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

Ngoài ra, để tránh hình ảnh động bị giật khi khởi chạy qua singleInstance, bạn có thể sử dụng thay vì "singleTask", cả hai đều rất giống nhau nhưng sự khác biệt được giải thích ở đây theo tài liệu của Google:

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

singleInstance giống như "singleTask", ngoại trừ việc hệ thống không khởi chạy bất kỳ hoạt động nào khác vào tác vụ giữ thể hiện. Các hoạt động luôn luôn là thành viên duy nhất và duy nhất của nhiệm vụ của nó.

Hi vọng điêu nay co ich.

Trân trọng!


4
nó dường như hoạt động, nhưng bây giờ mọi hoạt động mới khác mà tôi khởi chạy từ MainActivity duy nhất, chơi hoạt hình vũ trang kỳ lạ này thay vì phai & quy mô thông thường
urSus

Điều gì về tôi đã khởi chạy một hoạt động mới mỗi lần nhưng xóa tất cả các phiên bản đang chạy khác của nó, điều đó có khả thi không?
urSus

Chà, tôi không nghĩ rằng hoạt hình mà bạn đề cập có liên quan đến thuộc tính "singleInstance", tất cả những gì nó làm là sử dụng lại cá thể hiện có, có lẽ hoạt hình mà bạn đang nói đến là một vấn đề hoàn toàn khác ...
Martin Cazares

1
Tôi đang thử nghiệm nó ngay bây giờ và nó. Nếu tôi xóa tất cả các cờ ý định và chỉ đặt launchMode = "singleInstance" trong tệp kê khai, thì hình ảnh động kỳ lạ sẽ ở đó, nếu tôi gỡ bỏ nó, nó sẽ trở lại bình thường
urSus

Vâng, theo tài liệu của Android, có vẻ như hoạt hình "init" không còn ở đó như thường lệ vì hoạt động không được khởi tạo, chỉ được sử dụng lại ...
Martin Cazares

26

Tôi nghĩ những gì bạn cần là trong singleTop Activity, chứ không phải là một singleTaskhoặc singleInstance.

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

Những gì tài liệu nói hoàn toàn phù hợp với nhu cầu của bạn:

[...] Một trường hợp mới của singleTophoạt động "" cũng có thể được tạo để xử lý mục đích mới. Tuy nhiên, nếu tác vụ đích đã có một phiên bản hiện có của hoạt động ở đầu ngăn xếp của nó, thì thể hiện đó sẽ nhận được ý định mới (trong một onNewIntent()cuộc gọi); một trường hợp mới không được tạo. Trong các trường hợp khác - ví dụ: nếu một phiên bản hiện có của singleTophoạt động "" nằm trong tác vụ đích, nhưng không ở trên cùng của ngăn xếp hoặc nếu nó ở trên cùng của ngăn xếp, nhưng không phải trong nhiệm vụ đích - mới thể hiện sẽ được tạo và đẩy vào ngăn xếp.

Trên hết (không có ý định chơi chữ), tôi có cùng nhu cầu với bạn. Tôi đã thử nghiệm tất cả các launchModecờ để tìm ra cách chúng thực sự hoạt động trong thực tế và kết quả singleToplà thực sự tốt nhất cho điều này: không có hoạt hình lạ, ứng dụng được hiển thị một lần trong danh sách ứng dụng gần đây (không giống như singleInstancehiển thị hai lần do thực tế nó không ' t cho phép bất kỳ ai khác Activitylà một phần của nhiệm vụ của mình) và hành vi đúng đắn bất kể mục tiêu Activityđã tồn tại hay chưa.


2
Làm việc đến 10 giờ tối tối thứ Sáu và đây là điều tôi muốn ... Cuộc sống của nhà phát triển buồn.
felixwcf

Tiết kiệm nhiều thời gian của tôi! Cảm ơn bạn!
hetsgandhi

13

Đây là chủ đề cũ, nhưng đối với tất cả những người vẫn đang tìm kiếm câu trả lời, đây là giải pháp của tôi. Nó hoàn toàn là mã, không có cài đặt tệp kê khai:

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

Ở đây FLAG_ACTIVITY_SINGLE_TOP mở hoạt động hiện có nếu nó ở đầu ngăn xếp nhiệm vụ. Nếu nó không ở trên cùng, nhưng bên trong ngăn xếp, FLAG_ACTIVITY_CLEAR_TOP sẽ xóa tất cả các hoạt động trên đầu hoạt động đích và hiển thị nó. Nếu hoạt động không có trong ngăn xếp nhiệm vụ, một hoạt động mới sẽ được tạo. Một điểm quan trọng nhất cần đề cập - tham số thứ hai của PendingIntent.getActivity (), tức là requestCode phải có giá trị khác không (tôi thậm chí còn gọi nó là NON_ZERO_REQUEST_CODE trong đoạn trích của tôi), nếu không các cờ mục đích đó sẽ không hoạt động. Tôi không biết tại sao nó lại như vậy. Cờ FLAG_ACTIVITY_SINGLE_TOP có thể hoán đổi với android: launchMode = "singleTop" trong thẻ hoạt động trong tệp kê khai.


Chiến đấu hàng giờ với những lá cờ này và tự hỏi tại sao việc thay đổi cờ ý định của tôi không thay đổi gì cả. Mã yêu cầu khác không ... một điểm quan trọng nhất cần đề cập !!! Hoạt động ngay! Cảm ơn bạn!
Công suất tối đa

9

Tôi biết nó đã cũ, nhưng không có gì ở trên phù hợp với ứng dụng của tôi.

Không thay đổi bảng kê khai và cấu hình khác, đây là mã để đưa ứng dụng của bạn trở lại phía trước - hoặc mở nó khi đóng

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

Đây là câu trả lời thực sự!
azizbekian

2
không, nó không hoạt động - nó thêm một hoạt động mới lên trên hoạt động hiện tại.
Tobliug

3

Tôi đã thử điều này và nó vẫn hoạt động mặc dù IDE đã phàn nàn về mã

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

2
<hoạt động android: name = ". MainActivity" android: launchMode = "singleTask">
nada

Intent.FLAG_ACTIVITY_REORDER_TO_FRONTkhông phải là cờ hợp lệ choPendingINtent.getActivity
rds

@rds Bạn có thể liên kết nguồn không?
Louis CAD

@LouisCAD Tôi xin lỗi, tôi không có quyền truy cập vào mã nguồn nữa
nada

@rds Tôi không yêu cầu mã nguồn, nhưng đối với liên kết nơi bạn đọc Intent.FLAG_ACTIVITY_REORDER_TO_FRONTkhông phải là cờ hợp lệ khi được sử dụng làm a PendingIntent. Hoặc có thể bạn có nghĩa là nó không hợp lệ để truyền vào getActivityphương thức, nhưng có hợp lệ để sử dụng làm Intentcờ sau đó được sử dụng như một PendingIntent?
Louis CAD

2

Vì bạn nói rằng bạn muốn bắt đầu hoạt động của mình nếu nó chưa bắt đầu, có lẽ bạn sẽ không khởi động lại nó. Tôi cũng đã thử nghiệm rất nhiều gợi ý và kết hợp cờ cho mục đích này, điều này sẽ luôn đưa hoạt động bạn cần lên phía trước, mặc dù nó sẽ không giữ bất kỳ trạng thái nào trước đây liên quan đến nó.

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

Chỉ API11 +.


0

Tôi đã có một vấn đề tương tự sau khi thêm thông báo như được tìm thấy trên trang web đào tạo Android . Không có câu trả lời nào khác ở đây làm việc cho tôi, tuy nhiên câu trả lời này đã làm việc cho tôi. Tóm lược:

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);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.