2013-07-01 4 views
7

Я пытаюсь осуществить навигацию в соответствии с: http://developer.android.com/training/implementing-navigation/ancestral.htmlAndroid Up навигация не работает

@Override 
public boolean onOptionsItemSelected(MenuItem item) { 
    switch (item.getItemId()) { 
    // Respond to the action bar's Up/Home button 
    case android.R.id.home: 
     Intent upIntent = NavUtils.getParentActivityIntent(this); 
     if (NavUtils.shouldUpRecreateTask(this, upIntent)) { 
      // This activity is NOT part of this app's task, so create a new task 
      // when navigating up, with a synthesized back stack. 
      TaskStackBuilder.create(this) 
        // Add all of this activity's parents to the back stack 
        .addNextIntentWithParentStack(upIntent) 
        // Navigate up to the closest parent 
        .startActivities(); 
     } else { 
      // This activity is part of this app's task, so simply 
      // navigate up to the logical parent activity. 
      NavUtils.navigateUpTo(this, upIntent); 
     } 
     return true; 
    } 
    return super.onOptionsItemSelected(item); 
} 

но if (NavUtils.shouldUpRecreateTask(this, upIntent)) { возвращает FALSE всегда.

Как этот код полезный? В каких случаях это верно?

+0

Например, если нажать кнопку «Домой», поиграть и вернуться к моему приложению с диспетчером задач, он по-прежнему возвращает false, даже больше нет стека задач (он возвращает меня в диспетчер задач, а не мое основное действие) , – Dandy

ответ

4

На предварительных Jelly Bean устройств, согласно source code of NavUtils, shouldUpRecreateTask является:

public boolean shouldUpRecreateTask(Activity activity, Intent targetIntent) { 
    String action = activity.getIntent().getAction(); 
    return action != null && !action.equals(Intent.ACTION_MAIN); 
} 

который использует действие, Activity «s (т.е. ACTION_VIEW и т.д.), чтобы определить, является ли этот Activity был запущен из внешний источник. На Jelly Bean + устройства, он использует Activity.shouldUpRecreateTask (source code):

public boolean shouldUpRecreateTask(Intent targetIntent) { 
    try { 
     PackageManager pm = getPackageManager(); 
     ComponentName cn = targetIntent.getComponent(); 
     if (cn == null) { 
      cn = targetIntent.resolveActivity(pm); 
     } 
     ActivityInfo info = pm.getActivityInfo(cn, 0); 
     if (info.taskAffinity == null) { 
      return false; 
     } 
     return !ActivityManagerNative.getDefault() 
       .targetTaskAffinityMatchesActivity(mToken, info.taskAffinity); 
    } catch (RemoteException e) { 
     return false; 
    } catch (NameNotFoundException e) { 
     return false; 
    } 
} 

который использует Task Affinity, чтобы определить, является ли сродства данного Activity «s так же, как сродства он был запущен с (то есть, если Gmail запустит Activity, ему будет придана близость Gmail, а не ее собственная).

NavUtils.navigateUpTo, во всех случаях запускает мероприятие. Если он не запускает соответствующий Activity, вам может потребоваться посмотреть, какой режим запуска вы используете, и предоставить подробную информацию о том, какая версия платформы она не работает.

+0

Я тестировал на 2.3.x и 4.1.x, и shouldUpRecreateTask всегда возвращает FALSE. Даже когда я иду домой, поиграю и вернусь в приложение. Я добавил 'android: taskAffinity =" com.my.app.MainActivity "' для обоих действий в манифесте (это правильно?), И я все равно получаю FALSE. Благодарю. – Dandy

+0

@Dandy - и неверный правильный ответ, когда ваше приложение не было запущено из другого приложения без запуска (пусковые установки используют 'ACTION_MAIN'). Вопрос в том, почему 'navigateUpTo' не запускает вашу' Activity'. Как я уже сказал, если это действительно проблема, «вам может потребоваться посмотреть, какой режим запуска вы используете, и предоставить подробную информацию о том, какая версия платформы она не работает». – ianhanniballake

+0

Спасибо. Я решил это, используя ActivityManager и проверив записи backStack. Если мой MainActivity - это предыдущий элемент, я должен moveTaskToBack (true), если нет, я призываю новое намерение. – Dandy

0

Я решил его с помощью ActivityManager и проверки записей backStack.

Я надеюсь, что это будет полезно для всех вас.

@Override 
public boolean onOptionsItemSelected(MenuItem item) { 
    switch (item.getItemId()) { 
     case android.R.id.home: 

      ActivityManager am = (ActivityManager) getApplicationContext().getSystemService(getApplicationContext().ACTIVITY_SERVICE); 
      List<RunningTaskInfo> runningTaskInfoList = am.getRunningTasks(10); 
      List<String> backStack = new ArrayList<String>(); 
      Iterator<RunningTaskInfo> itr = runningTaskInfoList.iterator(); 
      while(itr.hasNext()){ 
       RunningTaskInfo runningTaskInfo = (RunningTaskInfo)itr.next(); 
       String topActivity = runningTaskInfo.topActivity.getShortClassName(); 
       backStack.add(topActivity.trim()); 
      } 
      if(backStack!=null){ 
       if(backStack.get(1).equals(".MainActivity")){ 
        moveTaskToBack(true); // or finish() if you want to finish it. I don't. 
       } else { 
        Intent intent = new Intent(this, MainActivity.class); 
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
        startActivity(intent); 
        finish(); 
       } 
      } 

     break; 
    } 
} 

И мне нужно использовать:

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

в моем манифесте.

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

Смежные вопросы