2013-07-01 11 views
7

Sto cercando di implementare la navigazione in base a: http://developer.android.com/training/implementing-navigation/ancestral.htmlAndroid Up di navigazione non funziona

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

ma if (NavUtils.shouldUpRecreateTask(this, upIntent)) { sta tornando FALSE sempre.

Come è utile questo codice? In quali casi restituisce vero?

+0

Ad esempio, se premo il tasto Home, gioco e ritorno alla mia app con task manager, esso restituisce false, anche se non c'è più lo stack delle attività (mi riporta al Task manager, non alla mia attività principale) . – Dandy

risposta

4

Sui dispositivi Bean pre-gelatina, per il 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); 
} 

che utilizza l'azione s' il Activity (vale a dire, ACTION_VIEW, ecc) per determinare se questo Activity è stato lanciato da un fonte esterna. Sui dispositivi Jelly Bean +, utilizza 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; 
    } 
} 

che utilizza Task Affinity per determinare se l'affinità s' dato Activity è lo stesso che l'affinità è stato lanciato con (vale a dire, se Gmail lancia tua Activity, gli sarebbe stata data l'affinità di Gmail, piuttosto che la sua).

NavUtils.navigateUpTo, in tutti i casi, avvia un'attività. Se non sta lanciando l'appropriato Activity, potrebbe essere necessario esaminare la modalità di avvio che si sta utilizzando e fornire dettagli su quale versione della piattaforma non funziona.

+0

Ho provato su 2.3.xe 4.1.x e dovrebbeUpRecreateTask restituisce sempre FALSE. Anche quando torno a casa, gioco e ritorno all'app. Ho aggiunto 'android: taskAffinity =" com.my.app.MainActivity "' a entrambe le attività in Manifest (è corretto?) E continuo a ricevere FALSE. Grazie. – Dandy

+0

@Dandy - e false è la risposta giusta quando la tua app non è stata avviata da un'altra app non di lancio (gli launcher usano "ACTION_MAIN"). La domanda è perché 'navigateUpTo' non sta lanciando il tuo' Attività'. Come ho affermato, se questo è davvero il problema, allora "potresti dover controllare quale modalità di lancio stai usando e fornire dettagli su quale versione della piattaforma non funziona". – ianhanniballake

+0

Grazie. L'ho risolto usando ActivityManager e controllando le voci backStack. Se il mio MainActivity è l'elemento precedente, I to moveTaskToBack (true), in caso contrario, chiamo un nuovo intent. – Dandy

0

Ho risolto il problema utilizzando ActivityManager e controllando le voci di backStack.

Spero che possa essere utile per tutti voi.

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

E avevo bisogno di usare:

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

nel mio manifesto.

Funziona perfettamente, anche se non è la soluzione che avrei voluto. Sfortunatamente, Android è ancora privo di metodi integrati avanzati per ottenere cose semplici, e tutti dobbiamo trovare il modo di fare tutto.

Problemi correlati