NavUtils.navigateUpTo () не запускает никаких действий

У меня есть два вида деятельности

  • MainActivity
  • DeepLinkActivity

Я настроил все, чтобы использовать NavUtils для навигации, как здесь , здесь и здесь .

Я хочу достичь:

  1. Запустите DeepLinkActivity через глубокую ссылку
  2. нажмите на
  3. Перейти к MainActivity

Все работает хорошо, пока в моих приложениях есть какие-либо задачи моего приложения.

Однако, когда я удаляю свое приложение из последних приложений, он ведет себя следующим образом:

  1. Удалите мое приложение из последних приложений.
  2. Запустите DeepLinkActivity через глубокую ссылку
  3. нажмите на
  4. Приложение закрывается, например, при нажатии

Я отлаживал код и NavUtils.shouldUpRecreateTask() , что NavUtils.shouldUpRecreateTask() возвращает false . upIntent есть все, что было в порядке, например, мой Component . Но все же NavUtils.navigateUpTo() ведет себя точно так же, как вызов finish() . Нет логического оператора, ничего.

Любые идеи, как это исправить?

AndroidManifest.xml

 <activity android:name=".DeepLinkActivity" android:parentActivityName="my.package.MainActivity"> <meta-data android:name="android.support.PARENT_ACTIVITY" android:value="my.package.MainActivity"/> <intent-filter> <!-- Some intent filter --> </intent-filter> </activity> 

DeepLinkActivity.java

 @Override public boolean onOptionsItemSelected(final MenuItem item) { switch (item.getItemId()) { case android.R.id.home: Intent upIntent = NavUtils.getParentActivityIntent(this); if (NavUtils.shouldUpRecreateTask(this, upIntent)) { // create new task TaskStackBuilder.create(this).addNextIntentWithParentStack(upIntent) .startActivities(); } else { // Stay in same task NavUtils.navigateUpTo(this, upIntent); } return true; default: return super.onOptionsItemSelected(item); } } 

—– Редактировать —–

Я понял, что несколько Google Apps нарушены одинаково. Если вы перейдете, например, в «Контакты» из поиска, нажмите вверх в AB, и вы окажетесь на главном экране вместо приложения «Контакты». (API19 / CM11)

Solutions Collecting From Web of "NavUtils.navigateUpTo () не запускает никаких действий"

Я думаю, что этот метод прослушивается. Я прочитал исходный код библиотеки поддержки, и этот метод проверяет действие намерения. Он работает только тогда, когда ваше приложение было создано ранее. Как вы описали, если вы его убьете из предварительного просмотра Apps, метод shouldUp перестанет работать.

Я исправил это, используя свою собственную «shouldUpRecreateTask». Когда я получаю Уведомление, которое создает непосредственно действие (например, ваше поведение), я отправляю из своего BroadCastReceiver свое собственное действие внутри намерения. Затем в моем методе я делаю следующее:

 private final boolean shouldUpRecreateTask(Activity from){ String action = from.getIntent().getAction(); return action != null && action.equals(com.xxxxxx.activities.Intent.FROM_NOTIFICATION); } 

……………………..

  if (shouldUpRecreateTask(this)) { TaskStackBuilder.create(this) .addNextIntentWithParentStack(upIntent) .startActivities(); } else { fillUpIntentWithExtras(upIntent); NavUtils.navigateUpTo(this, upIntent); } 

Мое решение проблемы OPs:

 public void navigateUp() { final Intent upIntent = NavUtils.getParentActivityIntent(this); if (NavUtils.shouldUpRecreateTask(this, upIntent) || isTaskRoot()) { Log.v(logTag, "Recreate back stack"); TaskStackBuilder.create(this).addNextIntentWithParentStack(upIntent).startActivities(); } else { NavUtils.navigateUpTo(this, upIntent); } } 

isTaskRoot() вернет true, если DeepLinkActivity является корнем задачи (первоначальный запуск приложения или приложения был ранее завершен через диспетчер задач). Таким образом, я не теряю существующий задний стек, если активность была запущена через ссылку, когда задача приложения уже была на переднем плане.

Похоже, NavUtils.shouldUpRecreateTask(this, upIntent) не подготовлен для этого особого случая.

Моим текущим обходным решением является проверка, если Activity была глубоко связана и принудительно создала новый стек задач для таких случаев.

В моем случае я обхожу объекты внутри EXTRA . Но ACTION и Uri устанавливаются, если Activity запускается извне, следуя ссылке на определенный URL-адрес или касаясь устройств, поддерживающих NFC.

 @Override public boolean onOptionsItemSelected(final MenuItem item) { switch (item.getItemId()) { case android.R.id.home: Intent upIntent = NavUtils.getParentActivityIntent(this); if (NavUtils.shouldUpRecreateTask(this, upIntent) || getIntent().getAction() != null) { // deep linked: force new stack // create new task TaskStackBuilder.create(this).addNextIntentWithParentStack(upIntent) .startActivities(); } else { // Stay in same task NavUtils.navigateUpTo(this, upIntent); } return true; default: return super.onOptionsItemSelected(item); } } 

Используете ли вы <activity-alias> как ваш MAIN / LAUNCHER? Когда я изменяю <activity-alias> на <activity> , работа над навигацией работает правильно. По какой-то нечетной причине навигация не работает должным образом, когда задействованы псевдонимы.

Существует также странный UI-глюк, который указывает, что у native ActivityManager есть ошибка. После navigateUpTo() к основному действию приложения с помощью navigateUpTo() нажмите клавишу возврата устройства. В текущем приложении будет выполняться анимация выхода из процесса, а затем сразу же, следующее самое последнее приложение также выполнит анимацию выхода из действия. Это происходит, даже если вы зашли в текущее приложение с главного экрана Android. Если вы очистите все последние приложения и снова попытаетесь выполнить шаги «вверх-вниз-назад», во время анимации выхода будет представлено случайное (то есть неожиданное) приложение.

Другие приложения никогда не должны быть представлены в этих случаях. Кажется, что менеджер активности не правильно управляет стеком истории.

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

 + public boolean navigateUpTo(IBinder token, Intent destIntent, int resultCode, + Intent resultData) { + ComponentName dest = destIntent.getComponent(); + + synchronized (this) { + ActivityRecord srec = ActivityRecord.forToken(token); + ArrayList<ActivityRecord> history = srec.stack.mHistory; + final int start = history.indexOf(srec); + if (start < 0) { + // Current activity is not in history stack; do nothing. + return false; + } + int finishTo = start - 1; + ActivityRecord parent = null; + boolean foundParentInTask = false; + if (dest != null) { + TaskRecord tr = srec.task; + for (int i = start - 1; i >= 0; i--) { + ActivityRecord r = history.get(i); + if (tr != r.task) { + // Couldn't find parent in the same task; stop at the one above this. + // (Root of current task; in-app "home" behavior) + // Always at least finish the current activity. + finishTo = Math.min(start - 1, i + 1); + parent = history.get(finishTo); + break; + } else if (r.info.packageName.equals(dest.getPackageName()) && + r.info.name.equals(dest.getClassName())) { + finishTo = i; + parent = r; + foundParentInTask = true; + break; + } + } + } + + if (mController != null) { + ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0); + if (next != null) { + // ask watcher if this is allowed + boolean resumeOK = true; + try { + resumeOK = mController.activityResuming(next.packageName); + } catch (RemoteException e) { + mController = null; + } + + if (!resumeOK) { + return false; + } + } + } + final long origId = Binder.clearCallingIdentity(); + for (int i = start; i > finishTo; i--) { + ActivityRecord r = history.get(i); + mMainStack.requestFinishActivityLocked(r.appToken, resultCode, resultData, + "navigate-up"); + // Only return the supplied result for the first activity finished + resultCode = Activity.RESULT_CANCELED; + resultData = null; + } + + if (parent != null && foundParentInTask) { + final int parentLaunchMode = parent.info.launchMode; + final int destIntentFlags = destIntent.getFlags(); + if (parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE || + parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TASK || + parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TOP || + (destIntentFlags & Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) { + parent.deliverNewIntentLocked(srec.app.uid, destIntent); + } else { + try { + ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo( + destIntent.getComponent(), 0, UserId.getCallingUserId()); + int res = mMainStack.startActivityLocked(srec.app.thread, destIntent, + null, aInfo, parent.appToken, null, + 0, -1, parent.launchedFromUid, 0, null, true, null); + foundParentInTask = res == ActivityManager.START_SUCCESS; + } catch (RemoteException e) { + foundParentInTask = false; + } + mMainStack.requestFinishActivityLocked(parent.appToken, resultCode, + resultData, "navigate-up"); + } + } + Binder.restoreCallingIdentity(origId); + return foundParentInTask; + } + } 

Я обнаружил, что для меня это работает. Если активность была глубоко связана с другим действием или уведомлением, стек будет создан при перемещении в противном случае, действия просто будут перенесены на передний план.

 case android.R.id.home: Intent upIntent = NavUtils.getParentActivityIntent(this); upIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); startActivity(upIntent); finish(); return true; 

Если у вас есть

 android:parentActivityName="parent.activity" 

В вашем манифесте

Это не работает для меня тоже. Поэтому я справляюсь с этим:

  @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) { Intent intent = new Intent(this, MainActivity.class); startActivity(intent); finish(); return true; } return super.onOptionsItemSelected(item); } 

Моя MainActivity отмечена как singleTask в манифесте android

 android:launchMode="singleTask" 

Попробуй это :

 @Override public boolean onOptionsItemSelected(final MenuItem item) { switch (item.getItemId()) { case android.R.id.home: Intent upIntent = NavUtils.getParentActivityIntent(this); if (NavUtils.shouldUpRecreateTask(this, upIntent)) { // create new task TaskStackBuilder.create(this).addNextIntentWithParentStack(upIntent) .startActivities(); } else { // Stay in same task NavUtils.navigateUpTo(this, upIntent); } break; default: return super.onOptionsItemSelected(item); } return true; } 

Если вы перейдете к своей деятельности из уведомления, вам нужно будет создать стек при создании уведомления, проверьте этот ответ: NavUtils.shouldUpRecreateTask не работает на JellyBean