加载图片和6.0SD卡读写权限

转载请标明出处: :http://blog.csdn.net/huaiyiheyuan/article/details/52473984

一、Semaphore(信号量)

1、先来了解一下这个玩意儿,Semaphore semp = new Semaphore(5); 这 里设置的可以访问的资源个数为5.

2、copy介绍 : Semaphore实现的功能就类似厕所有5个坑,假如有10个人要上厕所,那么同时只能有多少个人去上厕所呢?同时只能有5个人能够占用,当5个人中 的任何一个人让开后,其中等待的另外5个人中又有一个人可以占用了。另外等待的5个人中可以是随机获得优先机会,也可以是按照先来后到的顺序获得机会,这取决于构造Semaphore对象时传入的参数选项。单个信号量的Semaphore对象可以实现互斥锁的功能,并且可以是由一个线程获得了“锁”,再由另一个线程释放“锁”,这可应用于死锁恢复的一些场合。

3、示例

public class TestSemaphore {
    public static void main(String[] args) {
        // 线程池
        ExecutorService exec = Executors.newCachedThreadPool();
        // 只能5个线程同时访问
         Semaphore semp = new Semaphore(5);
        // 模拟20个客户端访问
        for (int index = 0; index < 20; index++) {
            final int NO = index;
            Runnable run = new Runnable() {
                public void run() {
                    try {
                        // 获取许可
                        semp.acquire();
                        System.out.println("Accessing: " + NO);
                        Thread.sleep((long) (Math.random() * 10000));
                        // 访问完后,释放
                        semp.release();
                        System.out.println("-----------------" + semp.availablePermits());
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            };
            exec.execute(run);
        }
        // 退出线程池
        exec.shutdown();
    }
}

REFERENCE: http://www.cnblogs.com/whgw/archive/2011/09/29/2195555.html

二 、接下来要考虑的是图片的存储位置了

前面也有提过android保存文件到sd卡有两种方式

1、内部存储:下面几个特点

它始终可用。

默认情况下只有您的应用可以访问此处保存的文件。

当用户卸载您的应用时,系统会从内部存储中删除您的应用的所有文件。

当您希望确保用户或其他应用均无法访问您的文件时,内部存储是最佳选择。

外部存储 :外部存储又分为 外部私有存储 、外部公有存储

它并非始终可用,因为用户可采用 USB 存储的形式装载外部存储,并在某些情况下会从设 备中将其删除。

它是全局可读的,因此此处保存的文件可能不受您控制地被读取。

当用户卸载您的应用时,只有在您通过 getExternalFilesDir() 将您的应用的文件保存在 目录中时,系统才会从此处删除您的应用的文件。

对于无需访问限制以及您希望与其他应用共享或允许用户使用电脑访问的文件,外部存储是最佳位置。

公共文件

应供其他应用和用户自由使用的文件。 当用户卸载您的应用时,用户应仍可以使用这些文件。

例如,您的应用拍摄的照片或其他已下载的文件。

私有文件

本属于您的应用且应在用户卸载您的应用时删除的文件。尽管这些文件在技术上可被用户和其他应用访问(因为它们在外部存储上),它们是实际上不向您的应用之外的用户提供值的文件。当用户卸载您的应用时,系统会删除应用外部专用目录中的所有文件。

例如,您的应用下载的其他资源或临时介质文件。

2、特别注意 mkdir(),mkdirs(),createNewFile()的区别

createNewFile:新建文件(非目录)

mkdir:新建目录

mkdirs:新建目录,与mkdir的区别是:比如 mkdirs(“D:/test/test2”) 如果test

不存在会创建,然后创建test2,如果是 mkdir(“D:/test/test2”) ,如果

test不存在,会失败。

3、先来看下内部存储

创建内部目录

目录的路径是这样的:

fileDir    /data/data/com.android.imageloaderstorage/files/inner/img

fileCache    /data/data/com.android.imageloaderstorage/cache/inner/img
   /**
     * 创建内部目录
     */
   private String fileInnerName = "/inner/img";
    private String fileOutName = "/outDir/apk";
    private String fileOutPublicName = "/outPublic/outDir";
    protected void createInnerDir() {
        File fileDir = new File(getActivity().getFilesDir(),      fileInnerName);
        File fileCache = new File(getActivity().getCacheDir(), fileInnerName);
        if (!fileDir.exists()) {
            boolean isInner = fileDir.mkdirs();
            System.out.println(isInner);
        }
        if (!fileCache.exists()) {
            boolean isInner = fileCache.mkdirs();
            System.out.println(isInner);
        }
    }

内部存储( 下载图片,后面两种就是修改目录就行了)

我这边自己定义目录,就没用openFileOutput,这里用的FileOutputStream(File),这里File如果有多级目录没有创建得先创建目录,否则写入不成功

  /**
     * 内置存储
     * @param context
     * @param uniqueName
     * @return
     */
    public String getInnerCachPath(Context context, String uniqueName) {
        String cachePath = context.getCacheDir().getPath() + cache_dir;
        if (!new File(cachePath).exists()) {
            new File(cachePath).mkdirs();
        }
        return cachePath + File.separator + uniqueName;
    }
/**
     * 根据url下载图片在指定的文件
     * @param urlStr
     * @param file
     * @return
     */
    public static boolean downloadImgByUrl(String urlStr, File file) {
        FileOutputStream fos = null;
        InputStream is = null;
        try {
            URL url = new URL(urlStr);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            is = conn.getInputStream();
            fos = new FileOutputStream(file);
            byte[] buf = new byte[512];
            int len = 0;
            while ((len = is.read(buf)) != -1) {
                fos.write(buf, 0, len);
            }
            fos.flush();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (is != null)
                    is.close();
            } catch (IOException e) {
            }
            try {
                if (fos != null)
                    fos.close();
            } catch (IOException e) {
            }
        }
        return false;
    }

创建外部私有目录

路径是这样滴:fileOut /storage/emulated/0/Android/data/com.android.imageloaderstorage/cache/outdirfalfjlajlfjllllllllllllllllllllll

/* Checks if external storage is available for read and write */
public boolean isExternalStorageWritable() {
    String state = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED.equals(state)) {
        return true;
    }
    return false;
} 

      /**
     * 创建外部私有目录
     */
    protected void creatOutPrivateDir() {
     if (!isExternalStorageWritable()) {
            return;
        }
        File fileOut = new File(getActivity().getExternalCacheDir() + fileOutName);
        if (!fileOut.exists()) {
            Boolean isInner = fileOut.mkdirs();
            System.out.println(isInner);
        }
    }

外部公共目录

路径:/storage/emulated/0/OutIFOAFOFOJFJFFJ/img

   /**
     * 创建外部公有目录
     */
    protected void createOutPublicDir() {
     if (!isExternalStorageWritable()) {
            return;
        }
        File filePublic = new File(Environment.getExternalStorageDirectory() + fileOutPublicName);
        if (!filePublic.exists()) {
            filePublic.mkdirs();
        }
    }

后面两种只要把存储路径修改就可以了

三、

创建完目录,接下来还要来看下6.0的sd卡去写权限问题了

1、说到权限,那么就要弄清楚 compileSdkVersion 、minSdkVersion、targetSdkVersion的区别  了。

compileSdkVersion :

需要强调的是修改 compileSdkVersion 不会改变运行时的行为。当你修改了 compileSdkVersion 的时候,可能会出现新的编译警告、编译错误,但新的 compileSdkVersion 不会被包含到 APK 中:它纯粹只是在编译的时候使用。(你真的应该修复这些警告,他们的出现一定是有原因的)

因此我们强烈推荐总是使用最新的 SDK 进行编译。在现有代码上使用新的编译检查可以获得很多好处,避免新弃用的 API ,并且为使用新的 API 做好准备。

minSdkVersion:

这个好理解 minSdkVersion 则是应用可以运行的最低要求。minSdkVersion 是 Google Play 商店用来判断用户设备是否可以安装某个应用的标志之一

targetSdkVersion :

targetSdkVersion 是 Android 提供向前兼容的主要依据,就像后面在“外置公有目录”创建快捷方式,targetSdkVersion 22可以创建,targetSdkversion 23不能创建

2、创建代码

外置公有目录(Environment.getExternalStorageDirectory()) 创建

   /**
     * 创建外部公共目录
     */
    protected void createOutPublicDir() {
        if (!isExternalStorageWritable()) {
            return;
        }
        File filePublic = new File(Environment.getExternalStorageDirectory() + fileOutPublicName);
        if (!filePublic.exists()) {
            boolean isCreate = filePublic.mkdirs();
            System.out.println(isCreate);
        }else {
            boolean isDelete = filePublic.delete();
            System.out.println(isDelete);
        }
    }

A、 这是当前版本设置的内容

然后就是跑起来了

结果是这样

B 、接下里把targetSdkVersion 改成 22

运行结果

但是我把版本号马上改回23(没有卸载应用重装),竟然还是可以创建,可能是一个bug吧。

C、如果targetSdkVersion=23 ,我怎么创建目录呢

就是调起 授权弹框

类似于这种效果

Framgent的源码给我们写好了例子

  接着看最后的运行效果

如果我们在低于23的手机上运行,那么它安装试默认给定权限,targetSdkVersion 不管怎么改都没用了

2、接着看外部私有目录(context.getExternalCacheDir())

A、Saving files that are app-private

If you are handling files that are not intended for other apps to use (such as graphic textures or sound effects used by only your app), you should use a private storage directory on the external storage by calling getExternalFilesDir(). This method also takes a type argument to specify the type of subdirectory (such as DIRECTORY_MOVIES). If you don’t need a specific media directory, pass null to receive the root directory of your app’s private directory.

Beginning with Android 4.4, reading or writing files in your app’s private directories does not require the READ_EXTERNAL_STORAGE or WRITE_EXTERNAL_STORAGE permissions. So you can declare the permission should be requested only on the lower versions of Android by adding the maxSdkVersion attribute:

这里是出处: https://developer.android.com/guide/topics/data/data-storage.html#AccessingExtFiles

就是android4.4(api =19)图片和音频文件写入外置私有目录,并且不用声明权限 ,不过为了适配19一下的可以这样写

<manifest ...>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
                     android:maxSdkVersion="18" />
    ...
</manifest>

B.创建私有目录 我在4.1的机器上跑结果是这样

前提是我去掉了 android.permission.WRITE_EXTERNAL_STORAGE

在高于4.4(api =19)的手机上是这样的无论怎么修改都可以创建了

时间: 2024-10-06 00:57:09

加载图片和6.0SD卡读写权限的相关文章

cocos2d-x 3.3 之卡牌设计 NO.6 Loading界面(异步加载图片,plist)

刚开始做卡牌的时候没有想到要做loading,因为小游戏资源不多. 但是后来不断的加图片,直到在真机上发现卡顿的问题,我才知道该需要加loading了...... 首先,我们先定义类: class Loading : public Layer { public: bool init(); CREATE_FUNC( Loading); static Scene* CreateScene(); int total_pic_num;//需加载图片数 int total_sound_num;//需加载声

Android 异步加载图片,使用LruCache和SD卡或手机缓存,效果非常的流畅

转载请注明出处http://blog.csdn.net/xiaanming/article/details/9825113 异步加载图片的例子,网上也比较多,大部分用了HashMap<String, SoftReference<Drawable>> imageCache ,但是现在已经不再推荐使用这种方式了,因为从 Android 2.3 (API Level 9)开始,垃圾回收器会更倾向于回收持有软引用或弱引用的对象,这让软引用和弱引用变得不再可靠.另外,Android 3.0

Android开源框架ImageLoader:加载图片的三级缓存机制

前言:可从  https://github.com/nostra13/Android-Universal-Image-Loader 下载三级缓存机制的开源框架.下文简单介绍该框架中主要的常用方法,掌握这些方法,基本就可应对多数图片下载的需求. 注意:以下代码为示意代码片断,仔细读一下应能知道怎么用.蓝色表示为开源框架中的类. 1.初始化ImageLoader类对象: ImageLoader imageLoader = ImageLoader.getInstance(); imageLoader.

软引用SoftReference异步加载图片

HashMap<String, SoftReference<Drawable>> imageCache 关于SoftReference这个类多少知道些机制,会用就ok了. 机制:简单来说,她会帮助我们管理内存,防止内存溢出,另外一点也就相当于map,临时缓存些图片drawable让我们可以直接引用,很好了解决了OOM异常. 实现代码片段: [java]package com.Tianyou.Mobile.Common;  import java.io.IOException; im

异步加载图片

懒加载 加载出tableView 目标:加载图片 同步加载bug bug1:下载速度慢会卡  ->将耗时操作添加到队列 bug2:重复下载耗流量 NSOperation: 将耗时操作添加到队列中 CGD:把任务添加到队列中,指定执行函数 耗时操作:NSBlockOperation *downloadOperation = [NSBlockOperation blockOpWithBlock] 队列(全局属性):NSOperationQueue *queue 将耗时操作添加到队列 self.que

[原创]cocos2dx加载网络图片&amp;异步加载图片

[动机] 之前看到一款卡牌游戏,当你要看全屏高清卡牌的时候,游戏会单独从网络上下载,本地只存了非高清的,这样可以省点包大小,所以我萌生了实现一个读取网络图片的类. [联想] 之前浏览网页的时候经常看到一张图片渐进(由模糊变清晰)的显示,如果在游戏中,诸如像显示高清卡牌的时候,使用有这种方式去显示一张图片,这样的体验应该会稍微好些 [相关知识] png interlaced:png图片在导出的时候是可以选择 interlaced (Adam7)的,这样的存储的png在网页上显示会渐进显示, 这种i

加载图片问题

1.Android 高效加载大图片 2.Android加载大分辨率图片到手机内存中的实例方法 3.有效解决Android加载大图片时内存溢出的问题 4.Android有效解决加载大图片时内存溢出的问题 5.Android 异步加载图片,使用LruCache和SD卡或手机缓存,效果非常的流畅 6.Android异步加载图片并缓存到内存和SD卡上 7.android读取大图片并缓存的相关推荐 8.android gridview 加载本地图片很卡怎么办 9.基于android示例程序(bitmapf

续说ListView重用之加载图片

最近领养了一直小狗狗,据狗主人说是只阿拉斯加,求大伙见证. 不管他是不是阿拉斯加,我还是得养着,取名"蛋蛋". 继续谈技术. 说到listview里加载图片永远是个说不完的话题. 在listview中如果每个item都有图片需要下载的话,我们就得考虑由于大量图片加载而导致的oom(out of memory)问题. 一个典型的做法是,下载图片的时候看看缓存中有没有该图片,如果缓存中没有,就从sd卡中读取,如果sd卡中还没有,再去服务器下载,下载下来的图片先放在sd卡中,并放到缓存中.如

ImageLoader加载图片

先导universal-image-loader-1.9.3包 在application配置 android:name=".MyApplication" intent权限 package com.ch.day13_imageloaderdemo; import java.io.File; import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiscCache;import com.nostra13.univ