Запуск приложения только в том случае, если оно не запущено в данный момент



Я посылаю push-уведомление пользователям, которые при нажатии на него открывают приложение.



Моя проблема заключается в том, что, когда приложение уже открыто, нажав на уведомление, запустите приложение снова.



Я только хочу, чтобы он запустил приложение, если оно еще не запущено.



Я использую отложенное намерение в уведомлении:



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


Я видел сообщения, которые говорят использовать:



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


Но дело в том, что мое запущенное приложение запускает другую активность, а затем всплеск, который заканчивается после 7 секунды с момента запуска приложения, так что когда приложение работает всплеск не является текущей активностью

674   11  

11 ответов:

Используйте "запуск Intent" для вашего приложения, например:

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

Заменить "your.package.name - с именем вашего пакета из манифеста Андроида.

Кроме того, вы должны удалить специальный launchMode="singleTask" из вашего манифеста. Стандартное поведение Андроида сделает то, что вы хотите.

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

Для тех, кто использует Xamarin.Андроид . Xamarin версия ответа David Wasser приведена ниже:

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

Вместо того, чтобы показывать активность всплеска при щелчке уведомления, покажите свою основную активность, потому что ваша активность всплеска будет закрыта через некоторое время, но основная активность останется открытой и

<activity 
android:name=".MainActivity"
android:launchMode="singleTask"

Используйте взрывом фрагмент, а не активность. Сохраните фрагмент всплеска (7 секунд), замените его на нужный(целевая страница).

Добавьте в манифест launchMode="singleTask".

Как уже сказал Рахул, onNewIntent() вызывается, если приложение уже запущено else onCreate()

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

Или

Идите с ответомДэвида , кажется многообещающим.

Когда уведомление нажато и ваш код, который перенаправляет на ваш экран желания, просто замените этот код вызовом этого метода и перенаправьте на определенный экран на основе результата "true / false".

    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;
  }
Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT

И, возможно, не начинайте всплеск активности и снова откройте (выведите на передний план) MainActivity и обновите пользовательский интерфейс с помощью прослушивателя, который сообщает вам, что у вас есть новое уведомление (с флагом - boolean или с интерфейсом, чтобы сделать прослушиватель).

Для этого можно использовать упорядоченную трансляцию.

1) измените свой PendingIntent, чтобы начать BroadcastReceiver , который решит, начинать ли действие или ничего не делать:

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

2) Создайте решение 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) Создайте BroadcastReceiver в своей деятельности, которая будет сигнализировать о том, что она жива:

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

NotificationIntent.addFlags (намерение.FLAG_ACTIVITY_SINGLE_TOP / намерение.FLAG_ACTIVITY_CLEAR_TOP / Intent.FLAG_ACTIVITY_NEW_TASK);

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

Попробуйте добавить это к вашему намерению вывести активность на передний план, если она выполняется в фоновом режиме

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

Прежде всего задайте задачу по умолчанию android:taskAffinity="com.example.testp.yourPreferredName" в вашем элементе Application в файле манифеста. Поддерживайте ваш android:launchMode="singleTask" на вашем SplashActivity. Теперь, поскольку ваш SplashActivity является вашей основной записью, добавьте этот код к обоим onResume(), onNewIntent() и еще onCreate() (на второй мысли onResume() не рекомендуется) - следуйте комментариям в коде

//Note these following lines of code will work like magic only if its UPVOTED.
//so upvote before you try it.-or it will crash with SecurityException
ActivityManager am = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);

List< ActivityManager.RunningTaskInfo > taskInfo = am.getRunningTasks(1000);    
    for(int i =0; i< taskInfo.size(); i++){
        String PackageName = taskInfo.get(i).baseActivity.getPackageName();
        if(PackageName.equals("packagename.appname")){// suppose stackoverflow.answerer.Elltz
            //if the current runing actiivity is not the splash activity. it will be 1
            //only if this is the first time your <taskAffinity> is be called as a task
            if(taskInfo.get(i).numActivities >1){
                //other activities are running, so kill this splash dead!! reload!!                 
                finish();
                // i am dying in onCreate..(the user didnt see nothing, that's the good part)
                //about this code. its a silent assassin
            }
            //Operation kill the Splash is done so retreat to base.
            break;
        }
    }

Этот код не будет работать на api 21+; чтобы заставить его работать, вам нужно использовать AppTask , это сэкономит вам дополнительные строки кода, так как вы не будете в цикле, чтобы найдите свой Task.

Надеюсь, это поможет

Comments

    Ничего не найдено.