2013-05-18 5 views
8

Имеет некоторые проблемы с пользовательским классом, который расширяет AsyncTask. Мое приложение предназначено для Android 4.0.3, а приведенный ниже код отлично подходит для тестирования более 30 человек. Однако есть два пользователя, которые видят сбой приложения, когда я вызываю новый AsyncRequest, как показано ниже.Создание AsyncTask вызывает сбой

У меня есть рабочий журнал, который записывает текстовый файл в хранилище пользователей и не записывает запись, которая находится в конструкторе AsyncRequest. Поэтому я должен предположить, что авария происходит до вызова конструктора.

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

Внесение каких-либо изменений в причину возникновения сбоя объекта.

String url = "www.google.com"; 

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

А вот полный класс 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: В соответствии с комментариями ниже.

Вот полный метод, из которого я вызываю свой пользовательский AsyncTask. Все журналы, которые я создал для создания AsyncTask, отображаются в журнале. Ни одно из исключений.

Ведение журнала отображает значение URL-адреса непосредственно перед созданием моего AsyncRequest, и URL-адрес вовсе не искажен. Это то, чего я ожидаю.

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

Если вы уже обнаружили ошибку перед этим запросом, покажите код, прежде чем вы его назовете. – Gustek

+0

Вы запустили запись в код в начале создания «AsyncTask»? Возможно, это позволит вам увидеть, какая линия на самом деле терпит неудачу? –

+1

Gustek. Ошибка, кажется, не до того, как я ее вызову. Я добавил метод вызова к моему оригинальному сообщению. – Redshirt

ответ

0

Прежде всего, просто имейте в виде, что executeOnExecutor() не доступна до Апите 11. Вы уже сказали, проблема с 4.0.4 устройства, но просто имейте это в виде.

Вот шаги, которые я предприму, чтобы устранить проблему. Кажется, что вы уже сделали несколько из них со всеми этими заявлениями ReportInfo().

Во-первых, я принимаю ваш звонок до GetServerInfoAsync в пределах try...catch, правильно? Я проверяю из-за вашего использования Throw. Кроме того, вы уже добавили регистрацию, чтобы проверить наличие ошибок с URL-адресом. Поскольку ошибки возникают до их фактического использования, ошибка не может быть связана с URL-адресом или любыми разрешениями в Интернете. Вы вызываете генерацию AsyncTask со ссылками на callback и context. Вы добавили регистрацию через ReportInfo(), который ссылается на контекст, и те работают, да? Поэтому контекст не является вашей проблемой. Однако вы никогда не проверяете, что такое callback. Вы делаете ошибку, если она равна нулю, но вы никогда ничего не делаете с ней, прежде чем позвонить AsyncRequest. Попробуйте ReportInfo(callback.toString()), чтобы увидеть, что это такое.

Если все остальное не работает, это может показаться ошибкой с потоками. Почему бы не попробовать использовать только AsyncTask, а не executeOnExecutor(). Вам действительно нужно больше, чем 1 фоновый поток?

+1

Спасибо за ответ. Моя версия min/target sdk - 15/17, я тестировал без «ExecuteOnExecutor» с тем же отказом. Вызывающий метод действительно окружен try/catch. Как вы сказали, ведение журнала работает в методе GetServerInfoAsync, вплоть до создания экземпляра AsyncTask (или попытки). После работы я попробую предложение Wolframs и надеюсь, что у вас будет более конкретная информация для всех. – Redshirt

0

Извините, что не вернемся к этому раньше. Здесь было много проблем.

Прежде всего ... Благодаря предложению Вольфрама я смог поймать исключение и диагностировать, что проблема в том, что мой FileLogger (и другой класс) был статической ссылкой, и эти две таблицы не смогли найти ссылку во время выполнения , Поэтому я закончил удаление Logging из моих методов async.

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

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