2013-06-02 15 views
7

ich bin mit dieser Lösung: How to make notification intent resume rather than making a new intent?klicken Sie auf Benachrichtigung aktuelle Aktivität zu gehen

I funktioniert gut, wenn ich meine app normal laufen .. aber meine app hat eine Share-Funktion.

Wenn ich die Bilder, die ich aus der Galerie App freigeben möchte, auswähle und sie in meiner Aktivität öffne, erstelle ich eine Benachrichtigung in der Aktivität. Ich möchte, dass, wenn Benutzer auf die Benachrichtigung klickt, öffnet die vorhandene Aktivität (geöffnet von der Galerie App)

Das Problem ist, dass, wenn ich auf die Benachrichtigung klicken Sie nicht diese Aktivität fortsetzen, sondern stattdessen eine neue Instanz der Aktivität oder eine andere Instanz bereits geöffnet zuvor

Edit: Mehr Erklärung

Meine app heißt ShareApp und die Aktivität genannt wird Teilen das Problem ist, dass, wenn ich öffnen Sie die Teilen über Galerie App, eine Instanz der ShareActivity wird an der Spitze der Gal erstellt lery app task's stack. Nun, wenn ich eine Meldung erstellen, die auf meine Teile Punkte, verwende ich die Absicht:

Intent intent = new Intent(this, ShareActivity.class); 
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); 
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 

Problem ist, dass, wenn ich auf der Meldung klicken, es verweist auf die Instanz des Teils es in der Stack der ShareApp Aufgabe statt die gallery app task's stack ..

eine idee wie man auf den richtigen task-stapel zeigt ??

bearbeiten 2: mein Code

 int defaults = Notification.FLAG_NO_CLEAR; 
     NotificationCompat.Builder mBuilder = 
        new NotificationCompat.Builder(this) 
        .setSmallIcon(R.drawable.ic_launcher) 
        .setContentTitle(getString(R.string.app_name)) 
         .setContentText(text) 
         .setDefaults(defaults); 
     Intent intent = new Intent(this, this.getClass()); 
     intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); 
     intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 

     PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); 

     mBuilder.setContentIntent(pendingIntent); 
     NotificationManager mNotificationManager = 
      (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 
     mNotificationManager.notify(_ID, mBuilder.build()); 

bearbeiten 3: adb shell dumpsys Aktivität (nach dem Code von David https://stackoverflow.com/a/16901603/1334268 Anwendung)

Meine App ist shareApp und meine Tätigkeit genannt wird ShareActivity

Bevor Sie auf Benachrichtigung klicken:

Main stack: 
    TaskRecord{41965708 #6 A com.android.gallery3d} 
    Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.android.gallery3d/.app.Gallery bnds=[364,50][108,108]} 
     Hist #2: ActivityRecord{417ccc28 com.yeahman.shareapp/.ShareActivity} 
     Intent { act=android.intent.action.SEND_MULTIPLE typ=image/* cmp=com.yeahman.shareapp/.ShareActivity (has extras) } 
     ProcessRecord{41c868d0 6088:com.yeahman.shareapp/10116} 
     Hist #1: ActivityRecord{4135e540 com.android.gallery3d/.app.Gallery} 
     Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.android.gallery3d/.app.Gallery bnds=[364,50][108,108] } 

Nach einem Klick-Benachrichtigung:

Main stack: 
    TaskRecord{41965708 #6 A com.android.gallery3d} 
    Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.android.gallery3d/.app.Gallery bnds=[364,50][108,108]} 
     Hist #3: ActivityRecord{4169f358 com.android.gallery3d/.app.Gallery} 
     Intent { flg=0x20000000 cmp=com.android.gallery3d/.app.Gallery bnds=[0,205][480,301] } 
     ProcessRecord{4175dd28 5808:com.android.gallery3d/10036} 
     Hist #2: ActivityRecord{417ccc28 com.yeahman.shareapp/.ShareActivity} 
     Intent { act=android.intent.action.SEND_MULTIPLE typ=image/* cmp=com.yeahman.shareapp/.ShareActivity (has extras) } 
     ProcessRecord{41c868d0 6088:com.yeahman.shareapp/10116} 
     Hist #1: ActivityRecord{4135e540 com.android.gallery3d/.app.Gallery} 
     Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.android.gallery3d/.app.Gallery bnds=[364,50][108,108] } 
+0

Geben Sie den Code ein, mit dem Sie den 'Intent',' PendingIntent' und den 'Notification' erstellen. –

+0

ich habe gerade meine Frage mit meinem Code bearbeitet – yeahman

+0

gibt es eine Lösung? Ich werde akzeptieren, es ist nicht möglich, als Antwort mit Backup-Erklärung – yeahman

Antwort

5

Wenn mehrere Instanzen von ShareActivity in verschiedenen Aufgaben aktiv sind, können Sie Android nicht sagen, welche Aufgabe durch Starten Ihrer Aktivität reaktiviert werden soll. Es klingt für mich wie das, was Sie tun möchten, in diesem Fall ist nicht Ihre Aktivität, sondern die Galerie-Anwendung zu starten. Wenn die Galerie-App bereits ausgeführt wird und sich Ihre Aktivität oben auf dem Aufgabenstapel befindet, müssen Sie lediglich die Galerie-App in den Vordergrund bringen. Erstellen Sie dazu einen "Launch Intent" für die Gallery App und stellen Sie sicher, dass Intent.FLAG_ACTIVITY_NEW_TASK auf den Intent gesetzt ist.Dieses Beispiel-Code mit Activity

Sie könnten versuchen: Sie sollten eine "Start Intent" von der PackageManager unter Verwendung getLaunchIntentForPackage()

EDIT Lage sein,

// Get the root activity of the task that your activity is running in 
ActivityManager am = (ActivityManager)getSystemService(ACTIVITY_SERVICE); 
List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1); 
ActivityManager.RunningTaskInfo task = tasks.get(0); // Should be my task 
ComponentName rootActivity = task.baseActivity; 

// Now build an Intent that will bring this task to the front 
Intent intent = new Intent(); 
intent.setComponent(rootActivity); 
// Set the action and category so it appears that the app is being launched 
intent.setAction(Intent.ACTION_MAIN); 
intent.addCategory(Intent.CATEGORY_LAUNCHER); 

Hinweis: Sie müssen GET_TASKS Erlaubnis dafür. Ich habe das nicht versucht und kann nicht garantieren, dass es funktioniert. Die Verwendung von getRunningTasks() wird von der Dokumentation nicht empfohlen, aber das bedeutet nicht, dass es Ihren Zwecken nicht entspricht.

EDIT hinzugefügt Aktion/Kategorie zur Intent

HINWEIS: Ich habe eine kleine app tatsächlich gebaut, dies zu testen. Ich musste die ACTION = MAIN und CATEGORY = LAUNCHER zu der Absicht hinzufügen (die wäre da, wenn Sie PackageManager.getLaunchIntentForPackage() verwenden. Ich habe ein HTC One S, so auf meinem Gerät die App "Galerie" heißt eigentlich com.htc.album/.AlbumMain.ActivityMainDropList, aber dies sollten Sie noch arbeiten.

+0

Haben Sie ein Beispiel mit dem PackageManager? Was passiert, wenn ich eine andere Galerie-App oder Dateimanager-App anstelle der Standard-Galerie-App verwende? – yeahman

+0

Müssen Sie 'ShareActivity' in der Galerie-Aufgabe haben? Wenn nicht, könnten Sie 'ShareActvity' als' launchMode = "singleTask" 'deklarieren. Dies würde "ShareActivity" in einer neuen Aufgabe erzeugen und Sie hätten nicht das Problem, dass Ihre Aktivität in mehreren Aufgaben vorhanden wäre. Sie können das versuchen und sehen, ob es Ihr Problem löst. –

+0

yup ich weiß, dass es möglich ist, es über Singletask thx zu tun, aber ich würde es vorziehen, jedes Mal eine neue Instanz zu haben. mit singletask, der ärger ich bekomme ist wenn ich die shareactivity über galerie app öffnen und ich meine app, es öffnet die shareactivity geöffnet über gallery .. es ist nicht sehr intuitiv – yeahman

4

Set

android:launchMode="singleTop" 

in Ihrem manifest.xml für Ihre Haupttätigkeit und sehen, ob das hilft.

+0

nopes nicht funktioniert :( – yeahman

+0

Sie sind definiere die Flags für die pendingIntent? \t 'i.setFlags (Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);' –

+0

yup! Das Problem, das ich denke, ist, wenn die Aktivität aus der Galerie geöffnet wird, geht die Aktivität den Galeriestack und nicht meine app (nicht sicher, ob es korrekt ist). Also, wenn ich auf Benachrichtigung klicke, versuche ich die Aktivität vom Stapel meiner App zu öffnen, anstatt von der Galerie ... nicht sicher, ob das was ich sage, in Ordnung ist mit dem stack/instance von android im moment – yeahman

22
Notification.Builder mBuilder = 
      new Notification.Builder(this) 
      .setSmallIcon(R.drawable.cmplayer) 
      .setContentTitle("CoderoMusicPlayer") 
      .setContentText("PLayer0!"); 

    Intent resultIntent = new Intent(this, AndroidBuildingMusicPlayerActivity.class); 
    resultIntent.setAction(Intent.ACTION_MAIN); 
    resultIntent.addCategory(Intent.CATEGORY_LAUNCHER); 

    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, 
      resultIntent, 0); 

    mBuilder.setContentIntent(pendingIntent); 
    NotificationManager mNotificationManager = 
     (NotificationManager) getSystemService(NOTIFICATION_SERVICE); 
    mNotificationManager.notify(1, mBuilder.build()); 

den Code einfach kopieren und in Ihrem Haupt-Launcher Aktivität einfügen.

+0

Du hast meinen Tag gerettet. Danke – Zeus

+0

perfekte Arbeitslösung speziell für Dienstprogramme, wo Sie eine einzige Aktivität haben – Ravi

+2

Welcome.Happy Coding. –

0

Dies ist eine Lösung, die ich seit Jahren verwendet haben.

Ihr Problem ist, dass Dein PendingIntent startet sein Ziel von einem appless-Inhalt.

Der erste Schritt besteht darin, das Ergebnis Ihrer Absicht in den Kontext Ihrer App zu bringen. Um dies zu tun eine Sendung Ihre Benachrichtigungsruf müssen „ForwardingReceiver“

Intent newIntent = new Intent(context, ForwardingReceiver.class); 
... 
mBuilder.setContentIntent(PendingIntent.getBroadcast(context, category, newIntent, PendingIntent.FLAG_UPDATE_CURRENT)); 

Die ForwardingReceiver erstreckt BroadcastReceiver und es ist onReceive() Methode, die Sie jetzt haben sind Sie apps aktuellen Kontext und können sendOrderedBroadcast() wie so:

Intent forwardIntent = new Intent(); 
forwardIntent.putExtras(intent.getExtras()); 
forwardIntent.setAction(GenericReceiver.class.getCanonicalName()); 
context.sendOrderedBroadcast(forwardIntent, null); 

Jetzt, der lustige Teil. Sie müssen alle Ihre Apps-Aktivitäten von einem gemeinsamen übergeordneten Aktivitätenelement erweitern. Sie können dies bereits für die Protokollierung oder Analyse tun. In diesem CommonActivityParent onResume() müssen Sie erhalten Sendungen bei einer Priorität registrieren über 0 (wie 10)

mReceiver = new BroadcastReceiver() { 
    @Override 
    public void onReceive(Context context, Intent intent) { 
     performActionUsingIntent(intent); 
    } 
}; 

IntentFilter filter = new IntentFilter(); 
filter.addAction(GenericReceiver.class.getCanonicalName()); 
filter.setPriority(10); 
registerReceiver(mReceiver, filter); 

(Denken Sie daran, dies in onPause() deregistrieren)

Dies bedeutet, dass, wenn Ihre App Im Vordergrund wird der Benachrichtigungsklick (indirekt) angezeigt und Sie können eine Aktion ausführen.

Wenn sich Ihre Aktivität jedoch im Hintergrund befindet, wird dieser Empfänger nicht registriert. Kein Problem, Ihr "GenericReceiver" sollte etwa so aussehen:

@Override 
public void onReceive(Context context, Intent intent) { 
    PackageManager pm = context.getPackageManager(); 
    Intent newIntent = pm.getLaunchIntentForPackage(context.getPackageName()); 
    newIntent.putExtras(intent.getExtras()); 
    context.startActivity(newIntent); 
} 

Welche startet Ihre Startaktivität. Diese Startaktivität sollte Code in onCreate() enthalten, um zu erkennen, ob es der Stamm der Aufgabe ist. Wenn nicht, sollte es sofort geschlossen werden (und ist daher für den Benutzer nie sichtbar).Dies zwingt effektiv die letzte offene Aufgabe in den Vordergrund:

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

    if (!isTaskRoot() 
      && getIntent().hasCategory(Intent.CATEGORY_LAUNCHER) 
      && getIntent().getAction() != null 
      && getIntent().getAction().equals(Intent.ACTION_MAIN)) { 

     // Use this space to add the intent to a static singleton. This will be used in CommonActivityParent to perform an action. 
     CommonActivityParent.sIntent = getIntent(); 
     finish(); 
     return; 
    } 
} 

Um kurz nach Ihrem registerReceiver() Anruf oben in CommonActivityParent zu beenden, stellen Sie sicher, Sie führen die folgenden Kontrolle:

if(sIntent != null) { 
    Intent tempIntent = sIntent; 
    sIntent = null; 
    performActionUsingIntent(tempIntent); 
} 

Ein schwupps - Sie‘ Die App verhält sich nun so, als ob ein Benachrichtigungsklick tatsächlich ein Klick aus Ihrer App ist. Und alles, was dazu nötig war, war verdammt viel Arbeit!

Hoffentlich hat jemand eine weniger komplizierte Art, dies zu tun.

Verwandte Themen