我们有一个内部应用程序,检查更新时,启动。它不是在Play Store上发布的,因为它仅供内部使用。
下面的更新代码在我的测试设备(API 23)上运行得很好。但是,我最近发布了一个更新,它可以在测试设备上下载,但是报告:
解析错误-解析包时出现了一个问题
在我自己的设备(API 24)上,应用程序下载应用程序,然后崩溃。
public class UpdateApp extends AsyncTask<String,Void,Void> {
private Context context;
public void setContext(Context contextf){
context = contextf;
}
@Override
protected Void doInBackground(String... arg0) {
try {
URL url = new URL(arg0[0]);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setDoOutput(true);
conn.connect();
File file = context.getCacheDir();
file.mkdirs();
outputFile = new File(file, "update.apk");
if(outputFile.exists()){
outputFile.delete();
}
FileOutputStream fos = new FileOutputStream(outputFile);
InputStream is = conn.getInputStream();
byte[] buffer = new byte[1024];
int len1 = 0;
while ((len1 = is.read(buffer)) != -1) {
fos.write(buffer, 0, len1);
}
fos.close();
is.close();
outputFile.setReadable(true, false);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(outputFile), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
} catch (Throwable ex) {
Toast.makeText(context, ex.toString(), Toast.LENGTH_LONG).show();
}
return null;
}在这两种设备上,更新的APK都是在抛出错误(API 23)或崩溃(API 24)之前下载的。我不明白这个应用程序怎么会崩溃,因为所有的代码都在try块中,其中有一个Throwable类的catch,所以它应该catch所有的错误和异常!
以下是我的API 24设备在下载文件后进行更新时的logcat输出。除了指出AysncTask类的问题外,我无法从中找出任何有用的东西。
2018-11-04 16:47:27.593 966-1017/? E/PROXIMITY: ProximitySensor: unknown event (type=3, code=0)
2018-11-04 16:47:27.704 23431-23476/uk.co.letsdelight.letsdelight E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
Process: uk.co.letsdelight.letsdelight, PID: 23431
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:318)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at java.lang.Thread.run(Thread.java:761)
Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:208)
at android.os.Handler.<init>(Handler.java:122)
at android.widget.Toast$TN.<init>(Toast.java:351)
at android.widget.Toast.<init>(Toast.java:106)
at android.widget.Toast.makeText(Toast.java:265)
at uk.co.letsdelight.letsdelight.Update$UpdateApp.doInBackground(Update.java:123)
at uk.co.letsdelight.letsdelight.Update$UpdateApp.doInBackground(Update.java:83)
at android.os.AsyncTask$2.call(AsyncTask.java:304)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at java.lang.Thread.run(Thread.java:761)
2018-11-04 16:47:27.716 966-989/? W/ActivityManager: Force finishing activity uk.co.letsdelight.letsdelight/.MainActivity
2018-11-04 16:47:27.745 966-23481/? W/AES: Exception Log handling...我还能做些什么来解决这个问题,或者让代码更加健壮,这样我们就不会有进一步更新的问题了?
发布于 2018-11-04 17:21:25
第1步:用其他方法替换Toast。不能在后台线程上显示Toast,这是错误消息告诉您的(Can't create handler inside thread that has not called Looper.prepare())。考虑到您仍然在使用AsyncTask,一个典型的解决方案是将Exception保存在AsyncTask中的一个字段中,然后在onPostExecute()中对其执行一些操作,因为这是在主应用程序线程上执行的。
步骤2:始终记录异常。至少,您应该登录到LogCat。如果您已经集成了ACRA、Crashlytics或类似的解决方案,您应该采取步骤确保您的异常也在那里得到报告。现在,您的catch块只是试图显示一个Toast,这意味着您无法知道具体问题是什么(例如,缺乏连接性)。
第三步: Android 7.0+的一个特定问题是您不能很好地使用Uri.fromFile(),因为file Uri值是被禁止的。在这些设备上,使用FileProvider将APK提供给安装程序,并使用FileProvider.getUriForFile()将Uri放到Intent中。不幸的是,在Android6.0和更旧的设备上,您不能使用FileProvider,因为安装程序将不支持content Uri值。因此,您需要检测您的版本(Build.VERSION.SDK_INT)并根据版本使用正确的Uri。
发布于 2018-11-05 01:54:09
有时,java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()在AsyncTasks中发生,因为您在后台线程中调用execute。您可以附加调试器并检查是否在后台执行此asyncTask。如果Thread.currentThread().getId()返回1,则可以使用评估器获取它的值--这意味着您位于主线程上,如果没有,请在应用程序的主线程中调用execute。
https://stackoverflow.com/questions/53143260
复制相似问题