做下载时,当sd卡满了或是不可用时,可将内容下载到data下面,但是下载到data下的apk,在安装时,会出现“解析失败”,查看了文件大小,是正确的。
解决办法:在下载前,打开data下文件流时,要设置属性为可读可写:
如:
String filePath=getApplicationContext().getFilesDir().toString() + File.separator+"test.apk";
FileOutputStream fos = new FileOutputStream(new File(filePath));
FileOutputStream fos= getApplicationContext().openFileOutput(fileName,Context.MODE_WORLD_READABLE + Context.MODE_WORLD_WRITEABLE);
断点下载示例:
/* * * 下载升级包线程 * */ class DownApkRunnable implements Runnable { private DownLoadFile dlFile; public DownApkRunnable(DownLoadFile dlFile) { this.dlFile = dlFile; } @Override public synchronized void run() { // 开始下载前先提示 mHandler.sendMessage(mHandler.obtainMessage(MSG_SHOW_TOAST, MainApplication.getInstance().getString( R.string.tip_update_begin))); isStartUpdate = true; // 初始化下载路径,确保下载路径存在并可用 savePath = UriConfig.getSavePath() + "update/"; setState(UPDATE_STATE_UPDATING); ELog.d(Constant.TAG, "start to download update info..."); FileManager.deleteDirectoryContent(savePath); ELog.d(Constant.TAG, "updateDataSavePath=" + savePath); File file = new File(savePath); if (!file.exists()) { boolean isSuccess=file.mkdirs(); ELog.e("创建savePath:"+savePath+" isSuccess="+isSuccess); } dlFile.setSavePath(savePath); // 初始化文件路径及临时存储路径 final String filePath = dlFile.getSavePath() + dlFile.getFileName(); String tempFilePath = savePath + dlFile.getTempFileName(); ELog.i(Constant.TAG, "filePath=" + filePath); ELog.i(Constant.TAG, "tempFilePath=" + tempFilePath); if (tempFilePath == null || (tempFilePath = tempFilePath.trim()).length() <= 0) { updateFailed( mContext.getString(R.string.notification_update_error_title), null); return; } long currLen = 0; long maxLen = 0; InputStream is = null; // 下载失败重试次数 int retryCount = 2; boolean isCreateFileSuccess = false; for (int i = 0; i <= retryCount; i++) { try { ELog.e("第" + i + "次连接网络..."); final File tempfile = new File(tempFilePath); if (tempfile.exists()) { // 第1次连接时,确保临时存放的文件是空的,存在的 if (i == 0) { tempfile.delete(); isCreateFileSuccess = tempfile.createNewFile(); } else {// 重试时,读取临时文件的大小,如支持断点就继续下载,否则从头下载 currLen = tempfile.length(); ELog.v("file has download portion :currLen=" + currLen); isCreateFileSuccess = true; } } else { isCreateFileSuccess = tempfile.createNewFile(); } ELog.e("...isCreateFileSuccess="+isCreateFileSuccess); NetWorkManager netManager = new NetWorkManager(); Header[] mHeaders = null; if (currLen > 0) { mHeaders = new Header[1]; final long tempLen = currLen; Header header = new Header() { @Override public String getValue() { return "bytes=" + tempLen + "-"; } @Override public String getName() { return "RANGE"; } @Override public HeaderElement[] getElements() throws ParseException { return null; } }; mHeaders[0] = header; } HttpResponse response = netManager .sendGetRequestAndWaitHttpEntityResponse(mContext, dlFile.getUrl(), mHeaders); if (response == null) { // throw new Exception(); downLoadStateChanged(dlFile, UPDATE_STATE_UPDATE_ERROR, null); updateFailed( mContext.getString(R.string.notification_update_error_title), mContext.getString(R.string.notification_update_error4)); return; } int respCode = response.getStatusLine().getStatusCode(); ELog.i("升级下载,respCode:" + respCode); HttpEntity httpEntiy; if (respCode == HttpStatus.SC_OK || respCode == HttpStatus.SC_PARTIAL_CONTENT) {// 206表示支持断点续传){ httpEntiy = response.getEntity(); } else { throw new Exception(); } if (httpEntiy == null) { throw new Exception(); } FileOutputStream fos = null; // 判断是否支持断点续传 Header[] allHeaders = response.getAllHeaders(); if (allHeaders != null) { for (Header header : allHeaders) { ELog.w("升级包head: key=" + header.getName() + " value=" + header.getValue()); if (header.getName().equals("Accept-Ranges")) { if ((header.getValue() != null && header .getValue().equalsIgnoreCase("bytes")) || respCode == HttpStatus.SC_PARTIAL_CONTENT) { ELog.i("升级包,支持断点续传的..."); fos = new FileOutputStream(tempfile, true); } else { ELog.i("升级包,不..支持断点续传的..."); fos = new FileOutputStream(tempfile); currLen = 0; } } } } // 长度取第一次联网获取的长度 if (i == 0 && maxLen <= 0) { maxLen = httpEntiy.getContentLength(); } ELog.i("下载,文件大小:" + maxLen + " sd卡剩余空间:" + DownloadTask.getTotalExternalMemorySize()); if (maxLen > DownloadTask.getTotalExternalMemorySize()) { ELog.i("文件下载前比较,空间不足,取消下载..."); downLoadStateChanged(dlFile, UPDATE_STATE_UPDATE_ERROR, null); updateFailed( mContext.getString(R.string.notification_update_error_title), mContext.getString(R.string.notification_update_error2)); return; } setMaxLen(maxLen); setCurrLen(currLen); downLoadProgressChanged(dlFile, maxLen, currLen); is = httpEntiy.getContent(); byte[] data = new byte[1024]; int len; downLoadStateChanged(dlFile, UPDATE_STATE_UPDATING, null); // 流读取完或是文件被暂停后停止读取数据 while ((len = is.read(data)) != -1) { fos.write(data, 0, len); currLen += len; ELog.v(Constant.TAG, "down....currLen=" + currLen); downLoadProgressChanged(dlFile, maxLen, currLen); dlFile.setCurrSize(currLen); } fos.flush(); fos.close(); is.close(); // 当下载完后才重命名 ELog.v(Constant.TAG, dlFile.getTempFileName() + " rename to :" + dlFile.getFileName()); file.renameTo(new File(savePath + dlFile.getFileName())); downLoadFileCompleted(dlFile); downLoadStateChanged(dlFile, UPDATE_STATE_UPDATE_SUCCESS, null); dlFile.setState(DownLoadFileListener.STATE_DOWNCOMPLETE); break; } catch (Exception e) { ELog.e("Error:"+e.getMessage()); e.printStackTrace(); if (!isCreateFileSuccess) { downLoadStateChanged(dlFile, UPDATE_STATE_UPDATE_ERROR, null); updateFailed( mContext.getString(R.string.notification_update_error_title), mContext.getString(R.string.notification_update_error5)); break; } else if (DownloadTask.getTotalExternalMemorySize() <= 0) { downLoadStateChanged(dlFile, UPDATE_STATE_UPDATE_ERROR, null); updateFailed( mContext.getString(R.string.notification_update_error_title), mContext.getString(R.string.notification_update_error2)); break; } else if (i >= retryCount) { if (!Utils.isNetworkAvailable(mContext)) { downLoadStateChanged(dlFile, UPDATE_STATE_UPDATE_ERROR, null); updateFailed( mContext.getString(R.string.notification_update_error_title), mContext.getString(R.string.notification_update_error3)); } else if (e instanceof SocketTimeoutException) { downLoadStateChanged(dlFile, UPDATE_STATE_UPDATE_ERROR, null); updateFailed( mContext.getString(R.string.notification_update_error_title), mContext.getString(R.string.notification_update_error4)); } else { downLoadStateChanged(dlFile, UPDATE_STATE_UPDATE_ERROR, null); updateFailed( mContext.getString(R.string.notification_update_error_title), mContext.getString(R.string.notification_update_error6)); } } } finally { try { if (is != null) { is.close(); is = null; } } catch (IOException e1) { e1.printStackTrace(); } } } } }