android 从通知恢复应用程序和堆栈

70gysomp  于 2023-08-01  发布在  Android
关注(0)|答案(9)|浏览(106)

我想从状态栏通知中恢复我的应用程序,其方式与用户在启动器中点击其图标时完全相同。
也就是说:我希望堆栈处于用户离开它之前的状态。
在通知上设置挂起Intent时的问题是,它始终针对特定的活动。我不想这样我需要像启动器一样恢复应用程序。
因此,如果用户处于活动A中,我希望恢复活动A。如果他从Activity A启动了Activity B,那么我希望在用户点击通知时显示Activity B,并恢复堆栈,以便在用户点击Activity B中的后退按钮时继续A。
还有其他几个问题的问题与类似的标题,但没有解决我的问题。

rqdpfwrv

rqdpfwrv1#

只需使用与Android在启动应用时使用的相同的Intent过滤器:

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

字符串
由于您为从通知栏打开Activity而创建的Intent与用于启动应用的Android相同,因此将显示先前打开的Activity,而不是创建新的Activity

kknvjkwl

kknvjkwl2#

对于您不想/不能硬编码启动器活动的情况,此解决方案有效

Intent i = getPackageManager()
    .getLaunchIntentForPackage(getPackageName())
    .setPackage(null)
    .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);

PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, i, 0);

return new NotificationCompat.Builder(context)
        ...
        .setContentIntent(pendingIntent)
        .build();

字符串

setPackage(null)部分在我的情况下是关键,因为没有它,应用程序无法恢复到上一个任务。我将我的intent与Android启动器中的intent进行了比较,注意到那里没有设置pkg,所以我想出了从intent中删除包名称的方法。

我的特殊情况是,通知是在库中创建的,因此我无法知道启动器活动是什么。

oknwwptz

oknwwptz3#

我也遇到了同样的问题,并试图解决问题,如@Grand的答案:

final Intent notificationIntent = new Intent(context,YourActivity.class);
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);

字符串
毫无疑问,这是可行的,但问题是当你将意图设置为ACTION_MAIN时。然后,您将无法将任何捆绑包设置为Intent。我的意思是,您的原始数据将不会从目标Activity接收,因为ACTION_MAIN不能包含任何额外的数据。
相反,您可以将Activity设置为singleTask,并在不设置ACTION_MAIN的情况下正常调用Intent,然后从目标Activity的onNewIntent()方法接收Intent。
但是如果你调用super.onNewIntent(intent);则将创建活动的第二示例。

vkc1a9a2

vkc1a9a24#

创建活动,然后设置类别和相应的标志...这就是我的工作方式,我必须这样做,因为我这样做是为了支持 API lvl 8

intent.addCategory(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setClass(this, YourActivity.class);

intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT|
                Intent.FLAG_ACTIVITY_SINGLE_TOP);

PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 
                   PendingIntent.FLAG_UPDATE_CURRENT);

字符串
在AndroidManifest中

android:launchMode="singleTask"


因此,真正的诀窍是Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT沿着清单中设置的行。
希望对其他人有帮助。

alen0pnh

alen0pnh5#

最终解决方案:Notification to restore a task rather than a specific activity?

public class YourRootActivity extends Activity 
    {
        @Override
        protected void onCreate(Bundle savedInstanceState) 
        {
            super.onCreate(savedInstanceState);
    
            if (!isTaskRoot()) // checks if this root activity is at root, if not, we presented it from notification and we are resuming the app from previous open state
            {
                 val extras = intent.extras // do stuffs with extras.
                 finish();
                 return;
            }
             // OtherWise start the app as usual
        }
    }

字符串

qlfbtfca

qlfbtfca6#

这很简单,打开你的manifest文件,在activity属性中设置属性Launch modesingleTop

pqwbnv8z

pqwbnv8z7#

这就是我为实现同样的事情所做的工作:

val intent = context.packageManager.getLaunchIntentForPackage(context.packageName)

var flags = PendingIntent.FLAG_ONE_SHOT
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
    flags = flags or PendingIntent.FLAG_IMMUTABLE
}
val pendingIntent = PendingIntent.getActivity(
    context,
    0,
    intent,
    flags
)

字符串
将该pendingIntent设置为您的通知构建器内容Intent。

mlmc2os5

mlmc2os58#

<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.REORDER_TASKS" />

private void bringApplicationToForeground(){
    ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);

    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

      List<ActivityManager.AppTask> tasksList = am.getAppTasks();
      for (ActivityManager.AppTask task : tasksList){
        task.moveToFront();
      }
    }else{

      List<ActivityManager.RunningTaskInfo> tasksList = am.getRunningTasks(Integer.MAX_VALUE);
      if(!tasksList.isEmpty()){
        int nSize = tasksList.size();
        for(int i = 0; i < nSize;  i++){
          if(tasksList.get(i).topActivity.getPackageName().equals(getPackageName())){
            am.moveTaskToFront(tasksList.get(i).id, 0);
          }
        }
      }
    }
}

字符串

v1uwarro

v1uwarro9#

可能有一种更简单的方法,但你可以将数据存储在sqlite数据库中,每当你重新启动应用程序时,无论你保存到数据库中的状态是什么,你都可以检索并设置你的值为它们需要的值。

相关问题