Android 异步任务创建导致崩溃
扩展AsyncTask的自定义类存在一些问题。我的应用程序是针对安卓4.0.3的,下面的代码可以很好地为30多人测试。然而,当我调用新的AsyncRequest时,有两个用户看到应用程序崩溃,如下所示 我有一个正在工作的记录器,它正在记录到用户存储上的文本文件中,而不记录AsyncRequest构造函数中的条目。所以我必须假设崩溃发生在调用构造函数之前 正在经历这次崩溃的两台设备中,有一台运行的是安卓4.0.4。不确定其他设备正在运行什么。不幸的是,我无法访问这两个设备,因此无法看到logcat输出 任何关于对象创建导致崩溃的原因的输入都将非常感谢Android 异步任务创建导致崩溃,android,android-asynctask,Android,Android Asynctask,扩展AsyncTask的自定义类存在一些问题。我的应用程序是针对安卓4.0.3的,下面的代码可以很好地为30多人测试。然而,当我调用新的AsyncRequest时,有两个用户看到应用程序崩溃,如下所示 我有一个正在工作的记录器,它正在记录到用户存储上的文本文件中,而不记录AsyncRequest构造函数中的条目。所以我必须假设崩溃发生在调用构造函数之前 正在经历这次崩溃的两台设备中,有一台运行的是安卓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);
}
}
首先,请记住,
executeOnExecutor()
在Api 11之前不可用。您已经说过问题出在4.0.4设备上,但请记住这一点
以下是我将采取的步骤,以排除问题所在。似乎您已经用所有这些ReportInfo()
语句完成了其中一些
首先,我假设您对GetServerInfoAsync
的调用在try…catch
中,对吗?我检查是因为您使用了Throw
。另外,您已经添加了日志记录来检查url的错误。由于错误发生在您实际使用它之前,因此该错误不能与url或任何internet权限关联。
通过引用回调
和上下文
调用异步任务生成。您已经通过引用上下文的ReportInfo()
添加了日志记录,这些都可以工作,是吗?因此,上下文不是你的问题。但是,您从不检查什么是callback
。如果错误为null,则抛出错误,但在调用AsyncRequest
之前,您从未对其执行任何操作。尝试使用ReportInfo(callback.toString())
查看它是什么
如果所有这些都失败了,那似乎是线程错误。为什么不尝试使用AsyncTask而不是
executeOnExecutor()
。你真的需要一个以上的后台线程吗?很抱歉没有早点回到这里。这里有许多问题
首先。。。感谢Wolfram的建议,我能够捕捉到异常并诊断出问题在于我的FileLogger(和另一个类)是一个静态引用,而这两个平板电脑在运行时找不到引用。因此,我最终从异步方法中删除了日志记录
其次,在进行上述更改之后,还有一个问题,那就是必须从主线程调用活套。原来这两个平板电脑并没有从主线程调用我的异步任务。因此,我必须使用MainLooper将异步调用封装在一个新的处理程序中。如果您已经发现错误在该请求之前,请在调用它之前显示代码。Gustek。在我调用它之前,错误似乎不存在。我已将调用方法附加到我的原始帖子中。可能是offtopic,但您可能希望将String更改为String。。。在onPostExecute签名中,您似乎能够获取错误日志(否则,您如何知道构造函数中的条目未被记录)。那么,为什么不添加更多设备信息(设备类型、SDK版本、可用内存)并使用
线程.UncaughtExceptionHandler
?@Wolfram。我不好意思说我不知道Thread.UncaughtExceptionHandler。明天我将把它烘焙成一个构建,看看它能提供什么额外的信息。我已经记录了有限的设备信息。这两个设备都有几百兆的可用空间,并且每个应用程序都有48MB的内存级别。一台设备的屏幕分辨率为1280x752(Acer Iconia A200)。另一个是谢谢你的回复。我的min/target sdk版本是15/17,我在没有执行ExecuteExecutor的情况下进行了测试,但同样失败。调用方法确实被try/catch包围。正如您所建议的,在创建(或尝试创建)AsyncTask实例之前,日志记录确实在GetServerInfoAsync方法中工作。下班后,我会尝试Wolframs的建议,希望能为大家提供更多的具体信息。
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;
}
}