android设备出现更新apk失败问题

应用程序检测到版本不一致时会跳更新页面,让用户点击更新操作,但是有些机器总是出现下载对话框是进度条不动,然后自动关闭进度条的现象。代码中使用简单的下载,代码如下:

public class UpdateService {

    private static OkHttpClient okHttpClient;

    public static void download(final String fileName,String url, final UpdateCallback callback) {
        Request request = new Request.Builder()
                .addHeader("Accept-Encoding", "identity")
                .url(url).build();

        if (okHttpClient == null) {
            okHttpClient = new OkHttpClient();
        }

        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                callback.onFailure();
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.body() == null) {
                    callback.onFailure();
                    return;
                }

                File filePath = new File(CommonConstants.DOWNLOAD_PATH);
                if (!filePath.exists()) {
                    filePath.mkdirs();
                }

                long contentLength = response.body().contentLength();
                byte[] buffer = new byte[1024];
                File file = new File(filePath.getCanonicalPath(), fileName);
                try (InputStream is = response.body().byteStream();
                     FileOutputStream fos = new FileOutputStream(file)) {
                     //Log.d("保存路径:" , file.getAbsolutePath());

                    int length;
                    long sum = 0;
                    while ((length = is.read(buffer)) != -1) {
                        fos.write(buffer, 0, length);
                        sum += length;
                        int progress = (int) (sum * 1.0f / contentLength * 100);
                        callback.onProgress(progress);
                    }
                    fos.flush();

                    callback.onSuccess();
                } catch (Exception e) {
                    callback.onFailure();
                }
            }
        });
    }

    public interface UpdateCallback {

        void onSuccess();

        void onProgress(int progress);

        void onFailure();
    }

}


业务中检测到不一致时执行如下代码:

UpdateService.download(fileName,apkUpdateUrl, new UpdateService.UpdateCallback() {
            @Override
            public void onSuccess() {
                dialog.dismiss();
                if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                    return;
                }

                File file = new File(CommonConstants.DOWNLOAD_PATH + fileName);
                try {
                   //下载成功好调用安装
                    installApk(file);
                } catch (Exception e) {
                    Log.e("获取打开方式错误", e.getMessage());
                }
            }

            @Override
            public void onProgress(int progress) {
                dialog.setProgress(progress);
            }

            @Override
            public void onFailure() {
                dialog.dismiss();
            }
        });

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
这种情况可能是由于网络问题导致下载失败。你可以在下载的过程中添加一些额外的处理来排除一些可能的问题。

  1. 检查网络连接状态:由于下载涉及到网络,所以应该首先检查设备的网络连接状态。可以使用ConnectivityManager类来获取设备的网络状态信息。

  2. 设置下载超时:设定下载的超时时间,防止在下载文件时网络连接被中断而下载失败。

修改网络请求代码如下:

public static void download(final String fileName, String url, final UpdateCallback callback) {
    Request request = new Request.Builder()
        .addHeader("Accept-Encoding", "identity")
        .url(url)
        .build();

    if (okHttpClient == null) {
        okHttpClient = new OkHttpClient.Builder()
            .connectTimeout(10, TimeUnit.SECONDS)
            .readTimeout(10, TimeUnit.SECONDS)
            .writeTimeout(10, TimeUnit.SECONDS)
            .build();
    }

    okHttpClient.newCall(request).enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
            callback.onFailure();
        }

        @Override
        public void onResponse(Call call, Response response) throws IOException {
            if (response.body() == null) {
                callback.onFailure();
                return;
            }

            File filePath = new File(CommonConstants.DOWNLOAD_PATH);
            if (!filePath.exists()) {
                filePath.mkdirs();
            }

            long contentLength = response.body().contentLength();
            byte[] buffer = new byte[1024];
            File file = new File(filePath.getCanonicalPath(), fileName);
            try (InputStream is = response.body().byteStream();
                 FileOutputStream fos = new FileOutputStream(file)) {
                 
                int length;
                long sum = 0;
                while ((length = is.read(buffer)) != -1) {
                    fos.write(buffer, 0, length);
                    sum += length;
                    int progress = (int) (sum * 1.0f / contentLength * 100);
                    callback.onProgress(progress);
                }
                fos.flush();

                callback.onSuccess();
            } catch (Exception e) {
                callback.onFailure();
            }
        }
    });
}
  1. 添加下载失败重试机制:在下载过程中,如果下载失败了,可以再次尝试下载。可以添加一个计数器,在下载失败时递增,当达到一定次数时,提示用户下载失败。

修改下载过程中的回调方法如下:

@Override
public void onFailure(Call call, IOException e) {
    if (retryCount < MAX_RETRY_COUNT) {
        // 继续尝试下载,重试次数+1
        retryCount++;
        download(fileName, url, callback);
    } else {
        callback.onFailure();
    }
}

完整的更新代码如下:

public class UpdateService {
    private static final int MAX_RETRY_COUNT = 3; // 最大重试次数
    private static OkHttpClient okHttpClient;

    public static void download(final String fileName, String url, final UpdateCallback callback) {
        Request request = new Request.Builder()
            .addHeader("Accept-Encoding", "identity")
            .url(url)
            .build();

        if (okHttpClient == null) {
            okHttpClient = new OkHttpClient.Builder()
                .connectTimeout(10, TimeUnit.SECONDS)
                .readTimeout(10, TimeUnit.SECONDS)
                .writeTimeout(10, TimeUnit.SECONDS)
                .build();
        }

        okHttpClient.newCall(request).enqueue(new Callback() {
            private int retryCount = 0;

            @Override
            public void onFailure(Call call, IOException e) {
                if (retryCount < MAX_RETRY_COUNT) {
                    // 继续尝试下载,重试次数+1
                    retryCount++;
                    download(fileName, url, callback);
                } else {
                    callback.onFailure();
                }
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.body() == null) {
                    callback.onFailure();
                    return;
                }

                File filePath = new File(CommonConstants.DOWNLOAD_PATH);
                if (!filePath.exists()) {
                    filePath.mkdirs();
                }

                long contentLength = response.body().contentLength();
                byte[] buffer = new byte[1024];
                File file = new File(filePath.getCanonicalPath(), fileName);
                try (InputStream is = response.body().byteStream();
                     FileOutputStream fos = new FileOutputStream(file)) {

                    int length;
                    long sum = 0;
                    while ((length = is.read(buffer)) != -1) {
                        fos.write(buffer, 0, length);
                        sum += length;
                        int progress = (int) (sum * 1.0f / contentLength * 100);
                        callback.onProgress(progress);
                    }
                    fos.flush();

                    callback.onSuccess();
                } catch (Exception e) {
                    callback.onFailure();
                }
            }
        });
    }

    public interface UpdateCallback {

        void onSuccess();

        void onProgress(int progress);

        void onFailure();
    }
    
    // 其他方法
}

如果我的回答解决了您的问题,请采纳!

  • 这有个类似的问题, 你可以参考下: https://ask.csdn.net/questions/240448
  • 这篇博客也不错, 你可以看下【Android 插件化】静态分析应用 APK 安装包是否使用了插件化引擎 ( 虚拟化引擎运行特点 | 恶意软件特点 )
  • 除此之外, 这篇博客: Android锁屏功能的开发与实现中的 2.不废话了,直接看看效果图吧,不过吧,锁屏也没什么图能截的,最好是把我最后给的源码里的apk安装体验一下吧 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 这里写图片描述

  • 您还可以看一下 张添翔老师的安卓手机渗透测试课程中的 APK文件反编译小节, 巩固相关知识点
  • 以下回答由chatgpt基于相关博客总结生成:

    我很抱歉,以上参考资料与问题不符,无法给出与问题相关的解决方案。但就问题本身而言,以下是一些可能的解决方案:

    1. 检查网络连接是否正常。下载对话框不动的情况可能是由于网络连接问题导致的。可以通过使用Android SDK提供的网络状态检测方法来确认网络连接是否正常。

    2. 使用异步任务来下载APK。在当前的代码中,下载操作是在UI线程中进行的,这可能会导致UI线程阻塞,使下载对话框不动。可以使用Android SDK提供的异步任务(AsyncTask)来进行下载,这样下载操作就可以在后台线程中完成,不会阻塞UI线程。

    以下是使用异步任务下载APK的示例代码:

    private class DownloadTask extends AsyncTask<String, Void, Boolean> {
        protected Boolean doInBackground(String... urls) {
            try {
                URL url = new URL(urls[0]);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.connect();
                int responseCode = conn.getResponseCode();
                if (responseCode == HttpURLConnection.HTTP_OK) {
                    // 获取下载文件的长度
                    int contentLength = conn.getContentLength();
                    // 根据文件长度创建一个输入流
                    InputStream is = conn.getInputStream();
                    // 创建一个输出流,用于将下载的文件写入磁盘
                    FileOutputStream fos = new FileOutputStream(mApkFilePath);
                    byte[] buffer = new byte[4096];
                    int len = -1;
                    int downloadedSize = 0;
                    while ((len = is.read(buffer)) != -1) {
                        fos.write(buffer, 0, len);
                        downloadedSize += len;
                        // 发送下载进度到主线程
                        publishProgress(downloadedSize, contentLength);
                    }
                    fos.flush();
                    fos.close();
                    is.close();
                    return true;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return false;
        }
    
        protected void onProgressUpdate(Integer... progress) {
            int downloadedSize = progress[0];
            int contentLength = progress[1];
            int percent = (int) ((downloadedSize * 100) / contentLength);
            // 发送下载进度到主线程
            sendMessage(MSG_DOWNLOAD_PROGRESS, percent);
        }
    
        protected void onPostExecute(Boolean result) {
            if (result) {
                // 下载完成,安装APK
                installApk();
            } else {
                // 下载出错,请重试
                showToast("下载出错,请重试");
            }
        }
    }
    

    在使用异步任务下载APK时,需要在doInBackground()方法中实现下载操作,在onProgressUpdate()方法中发送下载进度到主线程,在onPostExecute()方法中安装APK或提示下载出错信息。

    1. 检查SD卡是否可用。如果下载对话框不动的情况是由于APK文件写入SD卡失败导致的,需要检查SD卡是否可用。可以通过使用Android SDK提供的SD卡状态检测方法来确认SD卡是否可用。

该回答通过自己思路及引用到GPTᴼᴾᴱᴺᴬᴵ搜索,得到内容具体如下:
这种情况可能是因为在某些 Android 设备上,下载文件时可能会遇到某些限制或问题,导致下载失败或进度条不更新。以下是一些可能导致问题的原因和解决方法:

  1. 网络问题:检查设备网络连接是否正常,以及是否能够连接到下载服务器。如果网络不稳定或者下载服务器出现问题,可能会导致下载失败或者进度条不更新。

  2. 存储问题:检查设备存储空间是否充足,是否有读写权限等。如果存储空间不足或者没有读写权限,可能会导致下载失败。

  3. 应用权限:检查应用是否已经获取了下载权限。如果没有获取权限,可能会导致下载失败或者进度条不更新。可以在应用的 AndroidManifest.xml 文件中添加以下权限:

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    
  4. OkHttp 库问题:检查使用的 OkHttp 库版本是否过低或者存在已知的问题。可以尝试升级 OkHttp 库版本或者切换到其他网络请求库。

  5. 代码问题:检查代码实现是否存在问题。可以尝试使用其他下载方式,例如使用系统自带的下载功能,或者使用其他第三方下载库。可以尝试添加日志或者调试信息,查看是否有错误或异常发生。

希望这些解决方法能够帮助你解决下载问题。


如果以上回答对您有所帮助,点击一下采纳该答案~谢谢

引用chatGPT作答,这种情况可能是由于某些机型在下载文件时出现了一些问题,导致下载进度条停止更新并且进度条窗口关闭。这可能与你在代码中设置的下载进度条相关。

你可以尝试以下几个解决方案:

1.使用Android提供的DownloadManager类,它可以在后台下载文件并显示下载进度,从而避免了一些设备在下载时出现问题的可能性。

2.检查机器上是否已经禁用了“下载管理器”应用程序或“下载提醒”功能。如果是这种情况,可以通过在系统设置中启用这些选项来解决问题。

3.检查手机存储空间是否足够,如果存储空间不足可能会导致下载失败。

4.在代码中检查下载进度条的实现,确保它能够正确更新下载进度并且不会在下载完成后自动关闭。可以尝试在进度更新后加上调试语句,以便查看下载进度的实时变化,以便更好地诊断问题。