Ho un app Android che fa questo:Risoluzione intenti per URL è a volte nullo, getta NullPointerException
PackageManager pm = getApplicationContext().getPackageManager();
Intent browserIntent = new Intent();
browserIntent.setAction(Intent.ACTION_VIEW);
browserIntent.addCategory(Intent.CATEGORY_BROWSABLE);
browserIntent.setData(Uri.parse("http://www.google.com"));
ResolveInfo resolveInfo = pm.resolveActivity(browserIntent, PackageManager.MATCH_DEFAULT_ONLY);
try {
String browserType = nutent.activityInfo.packageName;
} catch (NullPointerException npe) {
npe.printStackTrace();
}
Ho testato questo su 4 ricevitori diversi e molte configurazioni diverse emulatore. Tutti funzionano bene. Ma sto ottenendo rapporti di arresto anomalo da applicazioni distribuite in natura lanciando un NPE poiché resolInfo è talvolta nullo.
La correzione immediata consiste nel prendere l'NPE e gestirlo prima che si blocchi la mia app (come fatto sopra). Ma ho cercato per giorni di riprodurlo da solo e non ci riesco. Su un emulatore con un unico browser di default installato, si risolve a com.android.browser.BrowserActivity:
ResolveInfo{411ef228 com.android.browser.BrowserActivity p=0 o=0 m=0x208000}
Allo stesso modo, su un portatile con più browser installati, questo risolve un po 'diverso ... a com.android. internal.app.ResolverActivity:
ResolveInfo{415c13b8 com.android.internal.app.ResolverActivity p=0 o=0 m=0x0}
il resolveActivity() documenti here stato:
Ritorna un ResolveInfo contenente l'intento finale di attività che era determ creato per essere l'azione migliore. Restituisce null se non è stata trovata alcuna attività corrispondente. Se vengono trovate più attività di corrispondenza e non esiste un set predefinito, restituisce un ResolveInfo che contiene qualcos'altro, come il risolutore di attività.
Quindi ho coperto il primo scenario, quello di un'attività intenzionata a essere l'azione migliore. Anche l'ultimo scenario, quello di più attività di abbinamento senza azione predefinita, che restituisce ResolverActivity.
Mi piacerebbe molto riprodurre lo scenario di resolveActivity() assegnandomi un valore null quando si richiede l'attività di un URL. Qualcuno ha qualche idea su come questo possa essere fatto senza, ad esempio, il rooting del dispositivo?
Per inciso, per "mangiare" l'eccezione, come fai tu, è una cattiva pratica. Le eccezioni vengono lanciate per una buona ragione e mentre si accede a una risorsa esterna, ci sono diversi motivi per cui potrebbe non riuscire e il proprio codice dovrebbe gestirli. – Simon
Questo è in realtà solo un intento "fittizio" che viene utilizzato solo per recuperare il tipo e la versione del browser (se disponibile), non viene mai utilizzato per recuperare pagine Web o altro. Credo che, in questo caso, mangiare l'eccezione e impostare il mio tipo di browser e le stringhe di versione su "sconosciuto" sia adeguato. Non c'è nient'altro che vorrei fare con l'eccezione. – AWT
Buona domanda. Non lo so per certo, ma la mia ipotesi è che forse non hai coperto l'ultimo scenario "quello di più attività di abbinamento senza azione predefinita" anche se pensi di averlo, perché stai specificando MATCH_DEFAULT_ONLY. Non ho incrinato la fonte di PackageManager (buon passo successivo), ma mi chiedo che cosa fa se si dice che corrisponde a predefinito, e non esiste un valore predefinito, restituire null?Hai provato su un dispositivo o emulatore con più browser e nessun set DEFAULT? (Assicurati che il selettore si avvicini se fai clic su un collegamento, ecc.) –