之前做过一个电视台app,电视台app每次启动时会访问服务器,判断是否需要下载新版本
但是下载时老是下载失败,apk包总是下载不下来.到底是什么原因呢?
服务器下载接口如下:
/*** * 下载apk * @param path * @param request * @return * @throws IOException */ @RequestMapping(value = "/download"/*, headers = {"content-type=application/json"}*/) public ResponseEntity<byte[]> download( String path,HttpServletRequest request) throws IOException { AccessLog accessLog=logInto(request); accessLog.setDescription("下载客户端"); if(!ValueWidget.isNullOrEmpty(request.getContentType())&& request.getContentType().toLowerCase().contains("application/json")){ String requestStr=WebServletUtil.getRequestQueryStr(request, null); System.out.println(requestStr); Map queryMap=JSONPUtil.getMapFromJson(requestStr); if(!ValueWidget.isNullOrEmpty(queryMap)){ path=(String) queryMap.get("path"); } } if(ValueWidget.isNullOrEmpty(path)){ System.out.println("download failed"); accessLog.setOperateResult("下载失败,没有传递path参数"); logSave(accessLog, request); return null; } String realpath =WebServletUtil.getUploadPath(request, "upload/download/apk", request .getSession().getServletContext(), Constant2.SRC_MAIN_WEBAPP); if(!realpath.endsWith(File.separator)){ realpath=realpath+File.separator; } HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); String fullpath=realpath+path; System.out.println("download path:"+fullpath); headers.set(Constant2.CONTENT_DISPOSITION,WebServletUtil.getContentDisposition(true, path)); accessLog.setOperateResult("下载成功,下载文件:"+fullpath+" ,size:"+FileUtils.getFileSize2(fullpath)); logSave(accessLog, request); return new ResponseEntity<byte[]>(FileUtils.getBytes4File(fullpath), headers, HttpStatus.CREATED); }
安卓端调用的下载方法(核心代码)如下:
/*** * * @param huc * @param sendBytes * @param mode * @param isWrite2file * : 是否写入文件 * @return * @throws Exception */ private static byte[] connection(HttpURLConnection huc, boolean isWrite2file, Object file, String sizeHeadKey) throws Exception { int resCode = huc.getResponseCode(); if (resCode == HttpURLConnection.HTTP_OK) { int contentLength = 0; if (ValueWidget.isNullOrEmpty(sizeHeadKey)) {// 若header中没有size contentLength = huc.getContentLength(); } else { String sizeHeaderValue = huc.getHeaderField(sizeHeadKey); if (!ValueWidget.isNullOrEmpty(sizeHeaderValue)) { contentLength = Integer.parseInt(sizeHeaderValue); } } if (isDetail) { System.out .println("[connection]contentLength:" + contentLength); responseHeaderFields = huc.getHeaderFields(); String downloadHeader = "Content-Disposition"; if (!ValueWidget.isNullOrEmpty(responseHeaderFields)) { List<String> ContentDispositions = responseHeaderFields .get(downloadHeader); if (!ValueWidget.isNullOrEmpty(ContentDispositions)) { String ContentDisposition = ContentDispositions.get(0); System.out.println("ContentDisposition:" + ContentDisposition); System.out.println("ContentDisposition convertISO2UTF:" + SystemHWUtil .convertISO2UTF(ContentDisposition)); System.out .println("ContentDisposition convertISO2GBK: " + SystemHWUtil .convertISO2GBK(ContentDisposition)); } } for (Object obj : responseHeaderFields.keySet()) { List<String> list = responseHeaderFields.get(obj); if (!ValueWidget.isNullOrEmpty(list)) { System.out.println(obj + " : " + SystemHWUtil.formatArr(list, ";")); } } System.out .println("[connection]contentLength:" + contentLength); } if (contentLength > 0) { if (isDetail) System.out .println("[HttpSocketUtil.connection]httputil,contentLength:" + contentLength); // return readData(huc); File file2 = null; if (isWrite2file) { if (file instanceof File) { file2 = (File) file; writeFileFromLength(huc, contentLength, file2); if (isDetail) { System.out.println("download success:" + file2.getAbsolutePath()); } } else { writeFileFromLength(huc, contentLength, (OutputStream) file); } return null; } else { return readDataFromLength(huc, contentLength); } } else { if (isWrite2file) { InputStream in = huc.getInputStream(); FileUtils.writeIn2OutputCloseAll(in, new FileOutputStream( (File) file)); if (isDetail) { System.out.println("download success:" + ((File) file).getAbsolutePath()); } return null; } return readData(huc); } } else { System.out.println("response Code:" + resCode); } return null; }
代码本身是没有逻辑错误的.花了很长时间才找到原因,是定义的response的status code不一致.
后台设置的status code是201,而android端判断的status code是200,不一致导致下载流程没有走到下载逻辑.
修改方法:把后台的status code改为200 就OK了
相关推荐
5. **错误处理**:提供良好的错误恢复机制,以防下载或安装过程中出现问题。 总之,Android的自动更新功能是通过Google Play服务和开发者自定义策略相结合实现的,旨在为用户提供最新的应用体验和安全保障。理解并...
2. 错误处理:在更新过程中,要处理各种可能出现的问题,如网络异常、下载中断等。 3. 用户隐私:在处理用户数据时,必须遵循隐私政策,不得滥用用户信息。 4. 更新频率:避免过于频繁的更新,以免打扰用户,同时...
在开发 Delphi Android 应用程序时,自动更新功能是一个重要的组成部分,它允许用户方便快捷地获取应用的最新版本,而无需手动下载安装。本文将详细介绍如何使用 RAD Studio 10.3.3 实现这一功能,并在 Android 10 ...
本篇文章将聚焦于“Android源码下载出现问题”这一主题,探讨在尝试下载Android源码时可能遇到的常见问题及其解决方案。 首先,下载Android源码主要依赖于Google的repo工具,它是一个版本控制系统,用于管理和同步...
总之,Android应用的自动更新机制涉及到网络通信、数据解析、文件下载和安装等多个环节,其中正则表达式作为一种强大的文本处理工具,在处理服务器返回的更新信息时起到关键作用。理解这一过程对于开发高效且用户...
在Android平台上,实现“自动更新功能”是一项关键的系统服务,它允许应用程序在有新版本可用时自动检测、下载并安装更新,确保用户始终运行的是最新版本。这一过程通常涉及多个组件和技术,包括网络请求、文件下载...
然而,在使用 Android Studio 时,可能会遇到一些问题,例如更新问题。 一、 Android Studio 更新问题 Android Studio 的更新问题是指在升级到新版本后,出现的一些问题,例如项目无法打开、SDK 版本不兼容等。这...
客户端接收到更新信息后,下载新的jar包到特定的本地目录,然后利用Java的动态加载机制,在运行时替换旧的jar包。这个过程需要注意安全性和兼容性问题,确保新旧版本之间的接口兼容,并且更新过程中不影响应用的正常...
4. `ExecutePermissionsRequest`: 自Android 6.0(API级别23)开始,运行时权限管理要求在安装时请求某些敏感权限。如果需要这些权限,此方法会处理权限请求流程。 在实际实现过程中,你还需要考虑一些额外的细节,...
在压缩包内的文件`android环境搭配_运行android_sdk_manager时出现错误问题解决方法.doc`中,可能详细列举了具体的错误情况和解决步骤,打开该文档仔细阅读,按照指南操作,应该能有效解决运行Android SDK Manager时...
而实时更新下载管理界面的进度条则是提供良好用户体验的关键。以下是对这一主题的详细阐述: 1. **多任务下载原理** 多任务下载通常涉及到线程池的使用,如Java的`ExecutorService`或Android的`AsyncTask`。每个...
本文将深入探讨如何解决Android10以下及以上的系统版本中,下载更新的APK自动安装失败的问题,为开发者提供实用的解决方案。 首先,我们需要了解Android在不同版本中对于安装APK权限的改变。自Android6.0(API级别...
1. **Android模拟器连接问题**:在使用模拟器时,不能使用`localhost`作为服务器地址,应使用`10.0.2.2`。 2. **文件放置位置**:新版本的APK文件和版本信息的JSON文件需放置在服务器的`/var/lib/tomcat7/webapps/...
此外,更新的APK应该签名与原应用一致,以避免安装时出现安全警告。 9. **UpdateSoftDemo项目**:这个项目的名称暗示它是一个演示了上述更新流程的示例代码。开发者可以通过分析和运行这个项目来学习如何在自己的...
服务器端负责存储最新的APK文件,客户端则定时或在特定条件触发时检查服务器是否有新版本,并在检测到更新后下载并安装。 二、检查更新流程 1. **请求服务器**:客户端通过网络向服务器发送请求,请求中可能包含...
这个"android更新模块"的讨论重点是如何有效地管理和实施应用的更新过程,以确保用户能够方便、快捷地获取到最新版本。下面我们将深入探讨这个话题。 首先,Android应用更新通常有两种方式:自动更新和手动更新。...
分段下载则将大文件分割成多个小块,每个线程负责下载一个或多个小块,这样即使网络出现问题,也只需要重试相应的小块,提高了下载的可靠性。 在这个实例中,`DemoDownloadThread`可能是类名,表示一个用于下载的...
- 自动更新组件需要处理Android系统的权限问题,比如读写存储权限,以允许应用安装APK文件。在Android 6.0及以上版本,需要在运行时请求权限。 5. **安全验证**: - 在安装更新前,组件应验证APK文件的签名,确保...
创建一个Notification,设置适当的图标、标题和消息,更新下载进度,用户可以通过点击Notification来查看或暂停下载。 综上所述,实现Android App更新服务下载涉及Service的创建与管理、下载管理器的使用、广播接收...
在网络请求、下载或安装过程中可能出现错误,因此需要构建适当的错误处理机制,例如重试下载、检查网络连接、提示用户问题等。 9. **安全考虑**: 在整个更新过程中,要确保APK来源的安全性,防止恶意软件的注入...