2013-05-18 8 views
8

AsyncTaskを拡張するカスタムクラスに問題があります。私のアプリはAndroid 4.0.3をターゲットにしており、以下のコードは30人以上の人がテストしても問題ありません。しかし、以下のように新しいAsyncRequestを呼び出すと、アプリケーションがクラッシュするのを2人のユーザーが見ています。AsyncTaskを作成するとクラッシュする

ユーザーストレージ上のテキストファイルに記録している作業用ロガーがあり、AsyncRequestコンストラクタにあるエントリは記録されません。だから私は、コンストラクタが呼び出される前にクラッシュが起きていると仮定しなければなりません。

このクラッシュを経験している2つのデバイスの1つは、明らかにAndroid 4.0.4を実行しています。他のデバイスが実行していることを確認しないでください。残念ながら、私は2つのデバイスにアクセスできないので、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); 
} 
} 

編集:以下のコメントを1として。

ここで私がカスタムAsyncTaskと呼ぶ完全なメソッドを示します。 AsyncTaskを作成するまでのすべてのログメッセージがログに表示されます。例外はありません。

ログには、自分のAsyncRequestを作成する直前にurl値が表示され、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またはインターネットのアクセス権ではありません。 callbackおよびcontextへの参照を使用してAsyncTask生成を呼び出します。コンテキストを参照するReportInfo()経由のログを追加しました。これらは動作していますか?したがって、文脈はあなたの問題ではありません。しかし、callbackが何であるかは決して確認しません。 nullの場合はエラーをスローしますが、AsyncRequestを呼び出す前に何もしないでください。それが何であるかを確認するにはReportInfo(callback.toString())を試してください。

他のすべてが失敗した場合、スレッド化にはエラーがあるようです。 executeOnExecutor()の代わりにAsyncTaskだけを試してみてください。本当に1つ以上のバックグラウンドスレッドが必要ですか?

+1

返信ありがとうございます。私のmin/target sdkのバージョンは15/17です、私は 'ExecuteOnExecutor'なしで同じ失敗でテストしました。呼び出し元のメソッドは実際にtry/catchで囲まれています。あなたが提案したように、AsyncTaskインスタンスが作成される(または試みられる)まで、ログはGetServerInfoAsyncメソッド内で動作します。仕事が終わったら、私はWolframsの提案をしてくれるでしょうし、うまくいけば皆のためにもっと具体的な情報を持っています。 – Redshirt

0

申し訳ありませんが早くこれに戻ることはありません。ここには多くの問題がありました。

最初にオフ... Wolframの提案のおかげで、私は例外をキャッチして、FileLogger(および別のクラス)が静的な参照であり、これらの2つのタブレットが実行時に参照を見つけることができなかったことを診断できました。だから私は非同期メソッドからロギングを削除してしまいました。

第2に、上記の変更を加えた後、ルーパーがメインスレッドから呼び出されなければならないという別の問題がありました。これらの2つのタブレットは、メインスレッドから非同期タスクを呼び出さないことが判明しました。だから私は非同期呼び出しをMainLooperを使って新しいHandlerに囲まなければなりませんでした。

関連する問題