Autore Topic: Eccezione TransactionTooLargeException nel metodo doInBackground  (Letto 927 volte)

Offline CrotaNexus

  • Utente normale
  • ***
  • Post: 156
  • Vuolsi così colà dove si puote ciò che si vuole
  • Respect: +25
    • Google+
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    SimoneDev
  • Sistema operativo:
    Windows 8.1
Eccezione TransactionTooLargeException nel metodo doInBackground
« il: 09 Febbraio 2014, 13:59:30 CET »
0
Ciao a tutti, io uso un AsynkTask per procurarmi la lista delle applicazioni installate nel dispositivo. Ieri mi è arrivata nella console un crash che riporta un eccezione del tipo TransactionTooLargeException, che da quanto ho capito leggendo la documentazione ufficiale e su Stack Overflow, viene causato quando le dimensioni dell'oggetto/operazione eseguita supera 1 MB. Il codice che utilizzo nel doInBackground() è questo:
Codice (Java): [Seleziona]
            appInfoArrayList = new ArrayList<AppInfo>();
            PackageManager mPackageManager = getPackageManager();
            List<ResolveInfo> resolveInfos;
            // In teoria il problema dovrebbe essere qui. Essendo molte le applicazioni installate va in crash.
            // Una possibile soluzione sarebbe quella di ciclare ogni elemento ma con quale criterio? Il problema si risolverebbe?
            Intent queryIntent = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_LAUNCHER);
            resolveInfos = mPackageManager.queryIntentActivities(queryIntent, 0);
            for (ResolveInfo ri : resolveInfos) {
                AppInfo ai = new AppInfo();
                ai.icon = ri.loadIcon(mPackageManager);
                ai.label = ri.loadLabel(mPackageManager);
                ai.packagename = ri.activityInfo.packageName;
                ai.packageclass = ri.activityInfo.name;
                ai.componentName = new ComponentName(ai.packagename, ai.packageclass);
                Intent i = new Intent(Intent.ACTION_MAIN);
                i.addCategory(Intent.CATEGORY_LAUNCHER);
                i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
                i.setComponent(ai.componentName);
                ai.intent = i;
                appInfoArrayList.add(ai);

L'errore ottenuto è questo:
Codice: [Seleziona]
java.lang.RuntimeException: An error occured while executing doInBackground()
   at android.os.AsyncTask$3.done(AsyncTask.java:300)
   at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
   at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
   at java.util.concurrent.FutureTask.run(FutureTask.java:242)
   at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
   at java.lang.Thread.run(Thread.java:811)
Caused by: java.lang.RuntimeException: Package manager has died
   at android.app.ApplicationPackageManager.queryIntentActivitiesAsUser(ApplicationPackageManager.java:499)
   at android.app.ApplicationPackageManager.queryIntentActivities(ApplicationPackageManager.java:485)
   at com.simonedev.androtools.GestoreApps$LoadApplications.doInBackground(GestoreApps.java:363)
   at com.simonedev.androtools.GestoreApps$LoadApplications.doInBackground(GestoreApps.java:1)
   at android.os.AsyncTask$2.call(AsyncTask.java:288)
   at java.util.concurrent.FutureTask.run(FutureTask.java:237)
   ... 4 more
Caused by: android.os.TransactionTooLargeException
   at android.os.BinderProxy.transact(Native Method)
   at android.content.pm.IPackageManager$Stub$Proxy.queryIntentActivities(IPackageManager.java:2165)
   at android.app.ApplicationPackageManager.queryIntentActivitiesAsUser(ApplicationPackageManager.java:493)
   ... 9 more

In soldoni, dovrebbe essere causato quando si hanno molte applicazioni installate... La causa mi è nota, la soluzione no e cercando tra le varie domande di Stack Overflow non mi sembra sia riportata una vera e propria soluzione. Qualche idea? Grazie in anticipo a tutti.
« Ultima modifica: 09 Febbraio 2014, 16:17:05 CET da CrotaNexus »
SimoneDev @ Google Play Store

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:Eccezione TransactionTooLargeException nel metodo doInBackground
« Risposta #1 il: 10 Febbraio 2014, 08:46:28 CET »
+1
Non ho letto attentamente il codice, ma credo di aver riconosciuto il problema. Ho avuto lo stesso problema qualche anno fa quando scrissi l'app GuardianDroid. Se non ricordo male, o limiti la quantità di informazioni richiesta, oppure prima ottieni la lista dei package e poi uno per volta prelevi le informazioni necessarie.
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline CrotaNexus

  • Utente normale
  • ***
  • Post: 156
  • Vuolsi così colà dove si puote ciò che si vuole
  • Respect: +25
    • Google+
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    SimoneDev
  • Sistema operativo:
    Windows 8.1
Re:Eccezione TransactionTooLargeException nel metodo doInBackground
« Risposta #2 il: 10 Febbraio 2014, 15:07:55 CET »
0
Inanzitutto Thanks per aver risposto. Non ho capito se il crash è dovuto dall'ingente mole di informazioni che sto prelevando (icona, nome applicazione e nome package) oppure da tutte le applicazioni che essendo troppe "intoppano" questa riga:

Codice (Java): [Seleziona]
resolveInfos = packageManager.queryIntentActivities(queryIntent, 0);
In termini pratici, come si potrebbe risolvere? Mi è stato suggerito l'attributo android:largeHeap="true", in tal caso potrebbe essere considerato un vero e proprio fix? Preferirei ottimizzare il codice sinceramente. Grazie in anticipo.

SimoneDev @ Google Play Store

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:Eccezione TransactionTooLargeException nel metodo doInBackground
« Risposta #3 il: 10 Febbraio 2014, 15:31:05 CET »
+1
In termini pratici, come si potrebbe risolvere? Mi è stato suggerito l'attributo android:largeHeap="true", in tal caso potrebbe essere considerato un vero e proprio fix? Preferirei ottimizzare il codice sinceramente. Grazie in anticipo.

Dal mio punto di vista una tale soluzione non risolve il problema, semplicemente sposta più in alto la soglia di allarme. Per risolvere il problema si devono chiedere meno informazioni tutte insieme. Io a suo tempo ho risolto riducendo le informazioni complessive richieste in una sola interrogazione. Se mi avesse ugualmente creato problemi (e sono sicuro che con migliaia di app installate lo farebbe), il passo dopo sarebbe fare una interrogazione per ciascuna app (ovviamente in thread a parte).
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline CrotaNexus

  • Utente normale
  • ***
  • Post: 156
  • Vuolsi così colà dove si puote ciò che si vuole
  • Respect: +25
    • Google+
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    SimoneDev
  • Sistema operativo:
    Windows 8.1
Re:Eccezione TransactionTooLargeException nel metodo doInBackground
« Risposta #4 il: 10 Febbraio 2014, 20:36:02 CET »
0
Su suggerimento di un utente ho adottato questa soluzione:
Codice (Java): [Seleziona]
            Intent queryIntent = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_LAUNCHER);
            resolveInfos = packageManager.queryIntentActivities(queryIntent, 0);
            numeroApps = resolveInfos.size();
            appInfoArrayList = new ArrayList<AppInfo>();
           
            for(int indice=0; indice<5; indice++) {
                indice = 0;
            for (ResolveInfo ri : resolveInfos) {
                AppInfo ai = new AppInfo();
                ai.icon = ri.loadIcon(packageManager);
                ai.label = ri.loadLabel(packageManager);
                ai.packagename = ri.activityInfo.packageName;
                ai.packageclass = ri.activityInfo.name;
                ai.componentName = new ComponentName(ai.packagename, ai.packageclass);
                Intent i = new Intent(Intent.ACTION_MAIN);
                i.addCategory(Intent.CATEGORY_LAUNCHER);
                i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
                i.setComponent(ai.componentName);
                ai.intent = i;
                appInfoArrayList.add(ai);
                indice++;
            }
            }

Secondo te la situazione potrebbe migliorare? Anche se non è una vera e propria soluzione ho messo comunque quell'attributo nel Manifest.
SimoneDev @ Google Play Store