• Android7.0打开sdacrd图片问题


    1.点击item,通过intent打开指定路径的图片。

    2.测试6.0,5.0正常运行代码

    File file=new File(item.address);
    
    Intent intent = new Intent("android.intent.action.VIEW");
    intent.addCategory("android.intent.category.DEFAULT");
    
    intent.addFlags (Intent.FLAG_ACTIVITY_NEW_TASK);
    
    Uri uri = Uri.fromFile(new File(item.address));
    
    intent.setDataAndType (uri, "image/*");
    
    startActivity(intent);
    

      

    3.在7.0上运行报错。

    com.aolian.mychezai, PID: 3881
       android.os.FileUriExposedException: file:///storage/emulated/0/AA/17-03-01%2009-31-08%202335-01%E7%AB%AF%20B%E7%B3%BB%20STU-V-N-LOG.txt exposed beyond app through Intent.getData()
       at android.os.StrictMode.onFileUriExposed(StrictMode.java:1816)
       at android.net.Uri.checkFileUriExposed(Uri.java:2350)
       at android.content.Intent.prepareToLeaveProcess(Intent.java:9076)
       at android.content.Intent.prepareToLeaveProcess(Intent.java:9037)
       at android.app.Instrumentation.execStartActivity(Instrumentation.java:1530)
       at android.app.Activity.startActivityForResult(Activity.java:4391)
       at android.support.v4.app.BaseFragmentActivityJB.startActivityForResult(BaseFragmentActivityJB.java:50)
       at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:79)
       at android.app.Activity.startActivityForResult(Activity.java:4335)
       at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:859)
       at android.app.Activity.startActivity(Activity.java:4697)
       at android.app.Activity.startActivity(Activity.java:4665)
       at com.aolian.mychezai.view.FileManagerActivity$7.onItemLongClick(FileManagerActivity.java:377)
       at android.widget.AbsListView.performLongPress(AbsListView.java:3298)
       at android.widget.AbsListView$CheckForLongPress.run(AbsListView.java:3215)
       at android.os.Handler.handleCallback(Handler.java:755)
                                                                  
    

      

    4. 从Android 7.0开始,一个应用提供自身文件给其它应用使用时,如果给出一个file://格式的URI的话,应用会抛出FileUriExposedException。这是由于谷歌认为目标app可能    不具有文件权限,会造成潜在的问题。所以让这一行为快速失败。详见这里。这里讨论两种解决方式。

    http://blog.csdn.net/xiaoyu940601/article/details/54406725

    <1> FileProvider方式

     (1) manifest声明 
    在manifest中声明一个provider。name(即类名)为android.support.v4.content.FileProvider。(红色为应用包名)

    <manifest>
        ... 
        <application>
            ...
    <provider
         android:name="android.support.v4.content.FileProvider"
         android:authorities="com.aolian.mychezai.fileprovider"
         android:exported="false"
         android:grantUriPermissions="true">
         <meta-data
             android:name="android.support.FILE_PROVIDER_PATHS"
             android:resource="@xml/file_paths" />
     </provider>
     ... </application> </manifest>
    

      

    其中authorities可以自定义。为了避免和其它app冲突,最好带上自己app的包名。file_paths.xml中编写该Provider对外提供文件的目录。文件放置在res/xml/下。 

    (2)编写file_paths.xml  里面的external-path 对应是sdcard路径下的

    <paths xmlns:android="http://schemas.android.com/apk/res/android">
        <files-path name="my_images" path="images/"/>
        ...
    </paths>
    

      

    <?xml version="1.0" encoding="utf-8"?>
    <paths xmlns:android="http://schemas.android.com/apk/res/android">
        <external-path name="my_images" path="AA/"/>
    
    </paths>
    

      

    内部的element可以是files-path,cache-path,external-path,external-files-path,external-cache-path,分别对应Context.getFilesDir(),Context.getCacheDir(),Environment.getExternalStorageDirectory(),Context.getExternalFilesDir(),Context.getExternalCacheDir()等几个方法。后来翻看源码发现还有一个没有写进文档的,但是也可以使用的element,是root-path,直接对应文件系统根目录。不过既然没有写进文档中,其实还是有将来移除的可能的。使用的话需要注意一下风险。

    (3)在Java代码当中使用 以分享一个图片为例:

    File file = ...;    //要分享的图片文件
    Uri uri = FileProvider.getUriForFile(context, "com.mydomain.fileprovider", file);    //第二个参数是manifest中定义的`authorities`
    Intent intent = new Intent(Intent.ACTION_SEND);
    intent.setType("image/*");
    intent.putExtra(Intent.EXTRA_TITLE, title);
    intent.putExtra(Intent.EXTRA_TEXT, text);
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);    //这一步很重要。给目标应用一个临时的授权。
    startActivity(intent);    //或者其它最
    

      

    2 VmPolicy方式

    以上方法固然是推荐使用的,正确的方法。但是我在实际开发中遇到这样的问题。某些应用(此处点名新浪微博)根本无法理解一个指向文件的content://格式的URI。新浪微博接收到这类URI之后,无法加载图片,并会在点击发送微博时崩溃。 
    另一方面,新浪微博对权限管理的处理采取了一种比较流氓的方式。它会在启动时申请文件读写权限,而如果拒绝该权限的话,居然就直接退出了。我反正是不信什么需要文件权限来放缓存放数据的说辞。放缓存放数据有着一堆不需要权限的目录可用。但是这样一来,我们其实是不需要担心传递一个file://格式URI过去而对方没有权限的。 
    话说回来,如何解决这一问题呢?我在调研的时候观察到严格模式的一个方法:StrictMode.VmPolicy.Builder.detectFileUriExposure()。顾名思义,调用这个方法就会检测FileUriExposure这件事。这个方法其实从API18就有了,是不是有可能在API24变成了默认选项呢? 
    在Application.onCreate加入如下代码,置入一个不设防的VmPolicy:

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
        StrictMode.setVmPolicy(builder.build());
    }
    

      

    再用旧的方式直接把file://格式的URI发送出去。没有再抛出FileUriExposedException。

    -----

    5.进入读取文件时 报错显示权限拒绝问题

    Caused by: android.database.sqlite.SQLiteCantOpenDatabaseException: 
    unknown error (Sqlite code 14): Could not open database, (OS error - 13:Permission denied) at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method) at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:219) at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:203)

      

    出现这种问题一般都是6.0以上需要动态申请权限。

    今天多一点积累,明天少一分烦恼
  • 相关阅读:
    POJ 3373 Changing Digits 记忆化搜索
    POJ 3268 Silver Cow Party (Dijkstra + 优先队列)
    ZOJ 1232 Adventure of Super Mario (Floyd + DP)
    POJ 2406 Power Strings KMP算法之next数组的应用
    POJ 1961 Period KMP算法之next数组的应用
    POJ 2492 A Bug's Life 并查集的应用
    POJ 1703 Find them, Catch them 并查集的应用
    POJ 3321 Apple Tree 树状数组+DFS
    POJ 3368 Frequent values 线段树与RMQ解法
    POJ 3264 Balanced Lineup RMQ ST算法
  • 原文地址:https://www.cnblogs.com/galibujianbusana/p/6482992.html
Copyright © 2020-2023  润新知