2013-05-18 15 views
8

Avere alcuni problemi con una classe personalizzata che estende AsyncTask. La mia app è Targeting per Android 4.0.3 e il codice seguente funziona correttamente per oltre 30 persone che lo testano. Tuttavia, ci sono due utenti che stanno vedendo l'arresto anomalo dell'app quando chiamo nuovo AsyncRequest come di seguito.La creazione di AsyncTask provoca l'arresto anomalo

Ho un logger funzionante che registra su un file di testo nella memoria degli utenti e non registra la voce che si trova nel costruttore AsyncRequest. Quindi devo supporre che l'arresto si verifichi prima che venga chiamato il costruttore.

Uno dei due dispositivi in ​​cui si verifica questo arresto anomalo sta eseguendo Android 4.0.4 a quanto pare. Non sei sicuro di cosa stia funzionando l'altro dispositivo. Sfortunatamente non ho accesso ai due dispositivi, quindi non posso vedere un output logcat.

Qualsiasi input sul motivo per cui la creazione dell'oggetto sta causando un arresto anomalo sarebbe molto apprezzato.

String url = "www.google.com"; 

new AsyncRequest(callback, context).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, url); 

E qui è la classe completa AsyncRequest

public class AsyncRequest extends AsyncTask<String, String, String>{ 

HttpURLConnection connection; 
InputStream inStream; 
IApiCallback callback; 
Context context_; 

public AsyncRequest(IApiCallback callback, Context context) { 
    // Log entry added for testing. Never gets called. 
    FileLogger.getFileLogger(context).ReportInfo("Enter AsyncRequest Constructor"); 
    this.callback = callback; 
    context_ = context; 
} 

@Override 
protected String doInBackground(String... uri) { 

    try { 
     URL url = new URL(uri[0] + "?format=json"); 
     FileLogger.getFileLogger(context_).ReportInfo("Async Request: Sending HTTP GET to " + url); 

     connection = (HttpURLConnection) url.openConnection(); 
     connection.setConnectTimeout(5000); 
     connection.setReadTimeout(5000); 
     connection.addRequestProperty("Accept-Encoding", "gzip"); 
     connection.addRequestProperty("Cache-Control", "no-cache"); 

     connection.connect(); 

     String encoding = connection.getContentEncoding(); 

     // Determine if the stream is compressed and uncompress it if needed. 
     if (encoding != null && encoding.equalsIgnoreCase("gzip")) { 
      inStream = new GZIPInputStream(connection.getInputStream()); 

     } else { 
      inStream = connection.getInputStream(); 
     } 

     if (inStream != null) { 
      // process response 
      BufferedReader br = new BufferedReader(new InputStreamReader(inStream)); 
      StringBuilder sb = new StringBuilder(); 
      String line; 
      while ((line = br.readLine()) != null) { 
       sb.append(line); 
      } 

      return sb.toString(); 

     } 

    } catch (SocketTimeoutException e) { 
     FileLogger.getFileLogger(context_).ReportException("Async Request: SocketTimeoutException", e); 
     Log.i("AsyncRequest", "Socket Timeout occured"); 
    } catch (MalformedURLException e) { 
     FileLogger.getFileLogger(context_).ReportException("Async Request: MalformedUrlException", e); 
    } catch (IOException e) { 
     FileLogger.getFileLogger(context_).ReportException("Async Request: IOException", e); 
     Log.i("doInBackground:","IOException"); 

     if (e != null && e.getMessage() != null) { 
      Log.i("doInBackground:",e.getMessage()); 
     } 
    } catch (Exception e) { 
     FileLogger.getFileLogger(context_).ReportException("Async Request: Exception", e); 

    } finally { 
     if (connection != null) 
      connection.disconnect(); 
    } 

    return null; 
} 

@Override 
protected void onPostExecute(String result) { 

    if (result != null) 
     FileLogger.getFileLogger(context_).ReportInfo("Async Request: Response is valid"); 
    else 
     FileLogger.getFileLogger(context_).ReportInfo("Async Request: Invalid response"); 

    callback.Execute(result); 
} 
} 

EDIT: Come da commenti qui sotto.

Ecco il metodo completo che chiamo il mio AsyncTask personalizzato da. Tutti i messaggi di registrazione che ho fino a creare AsyncTask vengono visualizzati nel registro. Nessuna delle eccezioni sono.

La registrazione mostra il valore dell'URL appena prima di creare il mio AsyncRequest e l'URL non è affatto malformato. È quello che mi aspetto.

public void GetServerInfoAsync(IApiCallback callback, Context context) throws IllegalArgumentException, Exception { 

    if (callback == null) 
     throw new IllegalArgumentException("callback"); 

    if (context == null) 
     throw new IllegalArgumentException("context"); 

    try { 
     FileLogger.getFileLogger(context).ReportInfo("Build URL"); 
     String url = GetApiUrl("System/Info"); 
     FileLogger.getFileLogger(context).ReportInfo("Finished building URL"); 

     if (url != null) { 
      FileLogger.getFileLogger(context).ReportInfo("GetServerInfoAsync: url is " + url); 
      new AsyncRequest(callback, context).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, url); 
     } else { 
      FileLogger.getFileLogger(context).ReportError("GetServerInfoAsync: url is null"); 
     } 

    } catch (IllegalArgumentException iae) { 
     FileLogger.getFileLogger(context).ReportException("GetServerInfoAsync: IllegalArgumentException", iae); 
     throw iae; 
    } catch (Exception e) { 
     FileLogger.getFileLogger(context).ReportException("GetServerInfoAsync: Exception", e); 
     throw e; 
    } 
} 
+0

Se l'errore è già stato rilevato prima di questa richiesta, mostrare il codice prima di chiamarlo. – Gustek

+0

Hai messo il log in del codice in esecuzione per creare il 'AsyncTask'? Forse questo ti permetterebbe di vedere quale linea in realtà sta fallendo? –

+1

Gustek. L'errore non sembra essere prima che lo chiami. Ho aggiunto il metodo di chiamata al mio post originale. – Redshirt

risposta

0

Prima di tutto, basta tenere a mente che executeOnExecutor() non è disponibile prima di Api 11. Hai già detto che il problema è con un dispositivo 4.0.4, ma basta tenere a mente.

Ecco i passaggi da eseguire per risolvere il problema. Sembra che tu abbia già fatto alcuni di questi con tutte quelle dichiarazioni ReportInfo().

Innanzitutto, presumo che la vostra chiamata a GetServerInfoAsync sia all'interno di un try...catch, corretta? Sto verificando l'utilizzo di Throw. Inoltre, hai già aggiunto la registrazione per verificare gli errori con l'url. Poiché gli errori si verificano prima che tu lo usi effettivamente, l'errore non può essere con l'url o con qualsiasi autorizzazione internet. Si chiama generazione AsyncTask con riferimenti a callback e context. Hai aggiunto la registrazione tramite ReportInfo() che fa riferimento al contesto, e quelli funzionano, sì? Pertanto, il contesto non è il tuo problema. Tuttavia, non si controlla mai cosa sia lo callback. Si genera un errore se è nullo, ma non si fa mai nulla con esso prima di chiamare AsyncRequest. Prova un ReportInfo(callback.toString()) per vedere di cosa si tratta.

Se tutto il resto fallisce, sembrerebbe essere un errore con il threading. Perché non provare a utilizzare solo AsyncTask, anziché executeOnExecutor(). Hai davvero bisogno di più di 1 thread in background?

+1

Grazie per la risposta. Le mie versioni di sdk min/target sono 15/17, ho provato senza 'ExecuteOnExecutor' con lo stesso errore. Il metodo di chiamata è infatti circondato da un try/catch. Come hai suggerito, la registrazione funziona all'interno del metodo GetServerInfoAsync, fino a quando l'istanza AsyncTask non viene creata (o tentata di). Dopo il lavoro proverò a suggerire Wolframs e spero di avere informazioni più concrete per tutti. – Redshirt

0

Ci scusiamo per non essere tornato prima. C'erano numerosi problemi qui.

Prima di tutto ... Grazie al suggerimento di Wolfram sono stato in grado di catturare l'eccezione e diagnosticare che il problema era che la mia FileLogger (e un'altra classe) è stato un riferimento statico e questi due compresse non riusciva a trovare il riferimento in fase di esecuzione . Così ho finito per rimuovere la registrazione dai miei metodi asincroni.

In secondo luogo, dopo aver apportato le modifiche di cui sopra c'era un altro problema che era che un looper doveva essere chiamato dal thread principale. Si è scoperto che questi due tablet non stavano chiamando il mio compito asincrono dal thread principale. Quindi ho dovuto racchiudere la chiamata asincrona in un nuovo gestore usando MainLooper.

Problemi correlati