web-dev-qa-db-fra.com

Démarrage de l'application uniquement si elle n'est pas en cours d'exécution

J'envoie une notification Push aux utilisateurs qui, lorsqu'ils cliquent dessus, ouvrent l'application.

Mon problème est que lorsque l'application est déjà ouverte, un clic sur la notification redémarre l'application.

Je veux seulement qu'il démarre l'application si ce n'est pas déjà en cours d'exécution.

J'utilise l'intention en attente dans la notification:

PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, Splash.class), 0);

J'ai vu des messages qui disent utiliser: 

<activity 
Android:name=".Splash"
Android:launchMode="singleTask"

mais le fait est que mon application en cours d'exécution exécute une autre activité, puis le splash terminé au bout de 7 secondes à compter du début de l'application. Par conséquent, lorsque l'application est en cours d'exécution, Splash n'est pas l'activité actuelle

29
Michael A

Utilisez une "lancez Intent" pour votre application, comme ceci:

PackageManager pm = getPackageManager();
Intent launchIntent = pm.getLaunchIntentForPackage("your.package.name");
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, launchIntent, 0);

Remplacez "your.package.name" par le nom de votre package dans le manifeste Android.

En outre, vous devez supprimer le launchMode="singleTask" spécial de votre manifeste. Le comportement standard d'Android fera ce que vous voulez.

26
David Wasser

Pour ceux qui utilisent Xamarin.Android . La version Xamarin de David Wasser est ci-dessous:

        //Create notification
        var notificationManager = GetSystemService(Context.NotificationService) as NotificationManager;
        Intent uiIntent = PackageManager.GetLaunchIntentForPackage("com.company.app");

        //Create the notification
        var notification = new Notification(Android.Resource.Drawable.SymActionEmail, title);

        //Auto-cancel will remove the notification once the user touches it
        notification.Flags = NotificationFlags.AutoCancel;

        //Set the notification info
        //we use the pending intent, passing our ui intent over, which will get called
        //when the notification is tapped.
        notification.SetLatestEventInfo(this, title, desc, PendingIntent.GetActivity(this, 0, uiIntent, PendingIntentFlags.OneShot));

        //Show the notification
        notificationManager.Notify(0, notification);
3
chris hu
String appPackageName = "";

private void isApplicationInForeground() throws Exception {
    ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
        final List<ActivityManager.RunningAppProcessInfo> processInfos = am
                .getRunningAppProcesses();
        ActivityManager.RunningAppProcessInfo processInfo = processInfos
                .get(0);
        // for (ActivityManager.RunningAppProcessInfo processInfo : processInfos) {
        if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
            // getting process at 0th index means our application is on top on all apps or currently open 
            appPackageName = (Arrays.asList(processInfo.pkgList).get(0));
        }
        // }
    }
    else {
        List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
        ComponentName componentInfo = null;
        componentInfo = taskInfo.get(0).topActivity;
        appPackageName = componentInfo.getPackageName();
    }
}

private void notifyMessage(String text) {
    if (appPackageName.contains("com.example.test")) {
        // do not notify
    }
    else {          
        // create notification and notify user  
    }
}
3
Haris Qureshi

Utilisez Splash comme fragment au lieu d’activité. Conservez le fragment Splash (7 secondes), remplacez-le par celui souhaité (page de destination).

Ajoutez launchMode = "singleTask" au manifeste.

Comme déjà indiqué par Rahul , onNewIntent() être appelé si l'application est déjà en cours d'exécution, sinon onCreate()

@Override
protected void onNewIntent(Intent intent) 
{   
    super.onNewIntent(intent);
}

OU 

Aller avec David réponse, semble prometteur.

1
Azhar Shaikh

Au lieu d'afficher l'activité Splash lors d'un clic de notification, affichez votre activité MainActivity, car celle-ci se ferme au bout d'un certain temps, mais MainActivity reste ouverte et 

<activity 
Android:name=".MainActivity"
Android:launchMode="singleTask"
1
Kartheek

Vous pouvez utiliser une diffusion ordonnée pour accomplir cela.

1) Modifiez votre PendingIntent pour démarrer une BroadcastReceiver qui décidera de démarrer l'activité ou de ne rien faire:

PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(this, DecisionReceiver.class), 0);

2) Créez la décision BroadcastReceiver:

public class DecisionReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        context.sendOrderedBroadcast(new Intent(MainActivity.NOTIFICATION_ACTION), null, new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (getResultCode() == MainActivity.IS_ALIVE) {
                    // Activity is in the foreground
                }
                else {
                    // Activity is not in the foreground
                }
            }
        }, null, 0, null, null);
    }
}

3) Créez une BroadcastReceiver dans votre activité qui signalera son existence:

public static final String NOTIFICATION_ACTION = "com.mypackage.myapplication.NOTIFICATION";
public static final int IS_ALIVE = 1;
private BroadcastReceiver mAliveReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        setResultCode(IS_ALIVE);
    }
};

// Register onResume, unregister onPause
// Essentially receiver only responds if the activity is the foreground activity
@Override
protected void onResume() {
    super.onResume();
    registerReceiver(mAliveReceiver, new IntentFilter(NOTIFICATION_ACTION));
}

@Override
protected void onPause() {
    super.onPause();
    unregisterReceiver(mAliveReceiver);
}
0
tachyonflux

notificationIntent.addFlags (Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);

notificationIntent.putExtras(bundle);
PendingIntent pintent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
0
Rahul

lorsque la notification a été cliquée et que votre code a été redirigé vers votre écran souhaité, il vous suffit de remplacer ce code en appelant cette méthode et de le rediriger vers un écran particulier sur la base du résultat "vrai/faux".

    private boolean isAppOnForeground(Context context) {
    ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    List<RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
    if (appProcesses == null) {
      return false;
    }
    final String packageName = context.getPackageName();
    for (RunningAppProcessInfo appProcess : appProcesses) {
      if (appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND && appProcess.processName.equals(packageName)) {
        return true;
      }
    }
    return false;
  }
0
krunal shah
Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT

Et peut-être ne commencez pas l'activité Splash et ne rouvrez pas (ne mettez pas au premier plan) MainActivity et ne mettez pas à jour l'interface utilisateur avec un écouteur vous indiquant que vous avez une nouvelle notification (avec un drapeau - boolean ou une interface pour créer un écouteur) .

0
Tazz