今天在做一个实现应用内更新的模块,在把下载的apk文件存入外部存储是遇到一个问题,最后终于解决了。现将过程记录下来。
我们知道,android分内部存储和外部存储,我们通常的理解就是除了sd卡的就是内部存储,而sd就是外部存储。现在大部分手机都没有sd卡,而是16G,8G什么的,其中并不是全部是内部存储,而是有一部分是像SD卡一样也是外部存储。
我们的应用程序就是处于内部存储,他的路径是data/data/<包名>,如果我们想把下载的文件下载在这里,调用Context类的getFileDir()就可以了,但是这样的话,该apk处于应用内部,就无法被其他应用程序使用了,使用如下代码去执行安装时,就会失败了:

/**         * 安装新版本应用         */        private void installApp() throws  Exception{            if(!file.exists()) {                return;            }            // 跳转到新版本应用安装页面            Intent intent = new Intent(Intent.ACTION_VIEW);            intent.setDataAndType(Uri.parse("file://" + file.getPath()),"application/vnd.android.package-archive");            context.startActivity(intent);        }

所以我们需要下载到外部存储中,调用Context类的getExternalFilesDir()就可以了,另外需要在清单文件中添加权限:

这样确实下载成功了,但是之后在华为E887(可能记错,但没关系)中出错,提示没有权限,该系统为android4.4.4 , 4G内存,并且插有2G的SD卡,我就纳闷了,我不是加了权限么?后来查阅google文档发现该方法,在android4.4以下系统中某些设备中既有外部存储(4G内存中也有外部存储),又有sd卡作为外部储存时,该方法无法获取文件的绝对路径进行读写,
可以调用Context类的getExternalFilesDirs()方法,该方法返回一个File数组,数组中的第一项被认为是主要外部存储,除非它不可用。

file=new File(context.getExternalFilesDirs(Environment.DIRECTORY_DOWNLOADS)[0],"Test.apk");

google原文如下:
Sometimes, a device that has allocated a partition of the internal memory for use as the external storage may also offer an SD card slot. When such a device is running Android 4.3 and lower, the getExternalFilesDir() method provides access to only the internal partition and your app cannot read or write to the SD card. Beginning with Android 4.4, however, you can access both locations by calling getExternalFilesDirs(), which returns a File array with entries each location. The first entry in the array is considered the primary external storage and you should use that location unless it’s full or unavailable. If you’d like to access both possible locations while also supporting Android 4.3 and lower, use the support library’s static method, ContextCompat.getExternalFilesDirs(). This also returns a File array, but always includes only one entry on Android 4.3 and lower.

另附一下下载完整代码

 /**         * 下载新版本应用         */        private void downloadApp() {            new Thread(new Runnable() {                @TargetApi(Build.VERSION_CODES.KITKAT)                @Override                public void run() {                    URL url1 = null;                    InputStream in = null;                    FileOutputStream out = null;                    HttpURLConnection conn = null;                    try {                        url1 = new URL(url);                        conn = (HttpURLConnection) url1.openConnection();                        conn.connect();                        long fileLength = conn.getContentLength();                        in = conn.getInputStream();                        file=new File(context.getExternalFilesDirs(Environment.DIRECTORY_DOWNLOADS)[0],"Test.apk");                        out = new FileOutputStream(file);                        byte[] buffer = new byte[1024];                        int len = 0;                        long readedLength =0;                        while((len = in.read(buffer)) != -1) {                            // 用户点击“取消”按钮,下载中断                            if(isCancel) {                                break;                            }                            out.write(buffer, 0, len);                            readedLength += len;                            curProgress = (int) (((float) readedLength / fileLength) * 100);                            handler.sendEmptyMessage(UPDARE_TOKEN);                            if(readedLength >= fileLength) {                                dialog.dismiss();                                // 下载完毕,通知安装                                handler.sendEmptyMessage(INSTALL_TOKEN);                                break;                            }                        }                        out.flush();                    } catch (Exception e) {                        e.printStackTrace();                    } finally {                        if(out != null) {                            try {                                out.close();                            } catch (IOException e) {                                e.printStackTrace();                            }                        }                        if(in != null) {                            try {                                in.close();                            } catch (IOException e) {                                e.printStackTrace();                            }                        }                        if(conn != null) {                            conn.disconnect();                        }                    }                }            }).start();        }

更多相关文章

  1. 跨平台开发:初探PhoneGap移动开发框架
  2. Android工程中的armeabi与armeabi-v7a
  3. Android和iOS应用下载实现合成一个二维码
  4. 《深入探索Android热修复原理》代码热修复总结
  5. Android(安卓)drawable文件夹的使用
  6. Android中实现对/system/bin/surfaceflinger进程进行拦截和注入
  7. Maven系列 1. Maven入门
  8. Android放置图片的三个文件夹
  9. Android中Lottie的简单使用

随机推荐

  1. Android(1.1-4.2) platform 开发包【全版本
  2. Android(安卓)Exported service does not
  3. Android中Fragment的应用(android官方教程
  4. android intent和intent action大全
  5. Android彻底组件化方案实践
  6. Android(安卓)操作系统 获取Root权限 原
  7. Android之——系统进程与用户进程分离
  8. [置顶] Android启动过程的深入研究
  9. Android(安卓)面试问题
  10. Android入门前言(一)之------Android应用