精华内容
下载资源
问答
  • FileProvider

    千次阅读 2018-06-26 22:39:11
    FileProvider 我对FileProvider的理解 如下: android7.0开始,不再允许在app之间,使用file://的方式传递File,否则会抛出FileUriExposedException异常 1,可以使用FileProvider,content://解决这...

    FileProvider


    我对FileProvider的理解
    如下:

    android7.0开始,不再允许在app之间,使用file://的方式传递File,否则会抛出FileUriExposedException异常

    1,可以使用FileProvider,content://解决这个问题
    2,也可以把targetSdkVersion小于24(<7.0),但我相信不会有人这样做

    FileProvider是ContentProvider的子类,所以需要在 AndroidManifest.xml中配置,使用ContentProvider可以向其他的app分享数据
    FileProvider可将这些数据转换成File文件

    1,AndroidManifest.xml中配置FileProvider(可配置多个)
    这里写图片描述

    name:配置的是FileProvider实现类,这里使用的系统的是v4包下( name就是指定FileProvider
    对于一个 App Module 而言,如果只是自己使用,可以直接使用 v4 包下的 FileProvider ,但是如果是作为一个 Lib Module 来供其他项目使用,最好还是重新空继承一个 FileProvider ,这里填写我们的继承类即可。)
    authorities:配置一个 FileProvider 的名字,它在当前系统内需要是唯一值(一般使用包名)。
    exported:表示 FileProvider 是否需要公开出去
    granUriPermissions:表示是否授权文件的临时访问权限

    meta-data指定FileProvider提供出去的路径
    name:固定写法
    resource指定了一个xml文件夹下的的filepaths文件,文件里面配置了路径(这里是在res下面新建了一个xml文件夹,并且xml中新建一个filepaths.xml)
    这里写图片描述

    filepaths的xml文件
    如下:
    这里写图片描述
    paths必须最少都要配置一个XXXXXX-path标签,而这个标签其实表示的是一个路径

    在FileProvider的类中可以看到
    标签的类型如下:

    private static final String TAG_ROOT_PATH = “root-path”;
    private static final String TAG_FILES_PATH = “files-path”;
    private static final String TAG_CACHE_PATH = “cache-path”;
    private static final String TAG_EXTERNAL = “external-path”;
    private static final String TAG_EXTERNAL_FILES = “external-files-path”;
    private static final String TAG_EXTERNAL_CACHE = “external-cache-path”;

    在parsePathStrategy就可以看到所代表的路径

      private static PathStrategy parsePathStrategy(Context context, String authority)
                throws IOException, XmlPullParserException {
            final SimplePathStrategy strat = new SimplePathStrategy(authority);
    
            final ProviderInfo info = context.getPackageManager()
                    .resolveContentProvider(authority, PackageManager.GET_META_DATA);
            final XmlResourceParser in = info.loadXmlMetaData(
                    context.getPackageManager(), META_DATA_FILE_PROVIDER_PATHS);
            if (in == null) {
                throw new IllegalArgumentException(
                        "Missing " + META_DATA_FILE_PROVIDER_PATHS + " meta-data");
            }
    
            int type;
            while ((type = in.next()) != END_DOCUMENT) {
                if (type == START_TAG) {
                    final String tag = in.getName();
    
                    final String name = in.getAttributeValue(null, ATTR_NAME);
                    String path = in.getAttributeValue(null, ATTR_PATH);
    
                    File target = null;
                    if (TAG_ROOT_PATH.equals(tag)) {
                        target = DEVICE_ROOT;
                    } else if (TAG_FILES_PATH.equals(tag)) {
                        target = context.getFilesDir();
                    } else if (TAG_CACHE_PATH.equals(tag)) {
                        target = context.getCacheDir();
                    } else if (TAG_EXTERNAL.equals(tag)) {
                        target = Environment.getExternalStorageDirectory();
                    } else if (TAG_EXTERNAL_FILES.equals(tag)) {
                        File[] externalFilesDirs = ContextCompat.getExternalFilesDirs(context, null);
                        if (externalFilesDirs.length > 0) {
                            target = externalFilesDirs[0];
                        }
                    } else if (TAG_EXTERNAL_CACHE.equals(tag)) {
                        File[] externalCacheDirs = ContextCompat.getExternalCacheDirs(context);
                        if (externalCacheDirs.length > 0) {
                            target = externalCacheDirs[0];
                        }
                    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
                            && TAG_EXTERNAL_MEDIA.equals(tag)) {
                        File[] externalMediaDirs = context.getExternalMediaDirs();
                        if (externalMediaDirs.length > 0) {
                            target = externalMediaDirs[0];
                        }
                    }
    
                    if (target != null) {
                        strat.addRoot(name, buildPath(target, path));
                    }
                }
            }
    
            return strat;
        }
    

    明显,我的path标签如下:表示的是外部存储

    if (TAG_EXTERNAL.equals(tag)) {
                  target = Environment.getExternalStorageDirectory();
    }
    

    好这里都配置好了,那就开始使用了喔,使用getUriForFile获取需要使用的Uri,参数就是一个context,authorities(配置一个 FileProvider 的名字,它在当前系统内需要是唯一值),然后需要一个文件

    public static Uri getUriForFile(Context context, String authority, File file) {
            final PathStrategy strategy = getPathStrategy(context, authority);
            return strategy.getUriForFile(file);
     }
    

    调用此方法,会自动得到一个 file:// 转换成 content:// 的 一个 Uri 对象,可以供我们直接使用。
    配置 provider 标签的时候,有一个属性 android:grantUriPermissions=“true” ,它表示允许它授予 Uri 临时的权限。

    当我们生成出一个 content:// 的 Uri 对象之后,其实也无法对其直接使用,还需要对这个 Uri 接收的 App 赋予对应的权限才可以。

    这个授权的动作,提供了两种方式来授权
    使用 Context.grantUriPermission() 为其他 App 授予 Uri 对象的访问权限

    toPackage :表示授予权限的 App 的包名。

    uri:授予权限的 content:// 的 Uri。

    modeFlags:前面提到的读写权限。

    这种情况下,授权的有效期限,从授权一刻开始,截止于设备重启或者手动调用 Context.revokeUriPermission() 方法,才会收回对此 Uri 的授权

    配合 Intent.addFlags() 授权。
    既然这是一个 Intent 的 Flag,Intent 也提供了另外一种比较方便的授权方式,那就是使用 Intent.setFlags() 或者 Intent.addFlag 的方式
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

    Intent.addFlags() 的方式,一旦授权将无法主动回收

    拥有了授权权限的 content:// 的 Uri 之后,就可以通过 startXxx 或者 setResult() 的方式,将 Uri 传递给其他的 App

    简单例子:

    String path = Environment.getExternalStorageDirectory().getAbsolutePath()
                    + File.separator +“ImageDir / img.png”
            File imgFile = new File(path);
            if (!imgFile.getParentFile().exists())
                imgFile.getParentFile().mkdirs();
            if (null != imgFile) {
                Uri photoUri;
                Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                takePhotoIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    
                if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) {
                    photoUri = Uri.fromFile(imgFile);
                } else {
                    /**
                     * 7.0 调用系统相机拍照不再允许使用Uri方式,应该替换为FileProvider
                     * 并且这样可以解决MIUI系统上拍照返回size为0的情况
                     */
                    photoUri = FileProvider.getUriForFile(context, context.getPackageName() + ".provider", imgFile);
                }
                takePhotoIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
                context.startActivityForResult(takePhotoIntent, REQUESTCODE);
            }
    
    <paths>
      <external-path path="images/imghead/" name="photos" />
    </paths>
    

    external-path中的name表示什么呢?

    <provider
                android:name="android.support.v4.content.FileProvider"
                android:authorities="${applicationid}.fileprovider"
                android:grantUriPermissions="true"
                android:exported="false">
                <meta-data
                    android:name="android.support.FILE_PROVIDER_PATHS"
                    android:resource="@xml/filepaths" />
            </provider>
    

    如果:
    Environment.getExternalStorageDirectory() 等于 “/storage/emulated/0”

    android系统 会把/storage/emulated/0/images/imghead/
    映射到content://(authorities字段的值)/name/

    假如:
    (authorities字段的值) = “com.android.www”
    name = photos
    拼接起来:content://com.android.www/photos/

    如果发现有错,望告知!!!!

    展开全文
  • Attribute provider#android.support.v4.content.FileProvider@authorities value=(com.example.xd.videotest) from AndroidManifest.xml:47:13-59 is also present at [:ringtonelib-release:] AndroidM...

    问题提示:

    Attribute provider#android.support.v4.content.FileProvider@authorities value=(com.example.xd.videotest) from AndroidManifest.xml:47:13-59
        is also present at [:ringtonelib-release:] AndroidManifest.xml:35:13-55 value=(net.xxx.app.provider).
        Suggestion: add 'tools:replace="android:authorities"' to <provider> element at AndroidManifest.xml:45:9-53:20 to override.

     

    在加入三方.arr后就报这样的问题,搜了很久,发现是三方的FileProvider和我自己的FileProvider冲突了,所以解决办法如下

     解决方案:
    <provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="com.example.xd.videotest"
    android:exported="false"
    android:grantUriPermissions="true"
    tools:replace="android:authorities">
    <meta-data
    android:name="android.support.FILE_PROVIDER_PATHS"
    android:resource="@xml/file_paths"
    tools:replace="android:resource" />
    </provider>

    为其添加 tools:replace="android:authorities" tools:replace="android:resource"

    我的问题是这样解决的,如果 有不同的可以根据提示来解决

    展开全文
  • FileProvider的用法

    千次阅读 2017-11-11 15:32:15
    FileProvider

    前一阵子接触这个东西,开始一直不理解是什么意思,一般来说我们运用Uri.fromFile来直接将文件路径加载为Uri,但是安卓6.0之后,就不能这样做了,按照Android N的要求,若要在应用间共享文件,您应发送一项 content://URI,并授予 URI 临时访问权限。
    而进行此授权的最简单方式是使用 FileProvider类。(修改后的伪代码在讲述FileProvider的使用时会写)
    所以应用件的共享数据就必须用到这个类,直接上例子进行验证
    我们以打开摄像机机型拍照为例

    package com.example.fang.myapplication;
    
    import android.content.Intent;
    import android.database.Cursor;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.net.Uri;
    import android.provider.MediaStore;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.MotionEvent;
    import android.view.View;
    import android.widget.Button;
    import android.widget.ImageView;
    
    import java.io.File;
    import java.io.FileNotFoundException;
    
    public class MainActivity extends AppCompatActivity implements View.OnTouchListener {
        File file;
        Uri uri;
      ImageView imageView;
        Button button;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        imageView= (ImageView) findViewById(R.id.imageView);
            button= (Button) findViewById(R.id.button);
            button.setOnTouchListener(this);
        }
    
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            switch (requestCode) {
                case 0: {
                   if(resultCode==RESULT_OK){
    
                       try {
                           Bitmap bitmap= BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
                           imageView.setImageBitmap(bitmap);
                       } catch (FileNotFoundException e) {
                           e.printStackTrace();
                       }
                   }
                    break;
                }
            }
        }
    
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            file = new File(getBaseContext().getExternalCacheDir(), "image.jpg");//使用的是应用缓存目录
            uri = Uri.fromFile(file);
            Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
            intent.putExtra(MediaStore.EXTRA_OUTPUT, file);
            startActivityForResult(intent, 0);
            return true;
        }
    }
    

    运行结果如下这里写图片描述

    tmd出错了,刚才还能拍照,以为写错了,看来是对的了,另外我们悬着了应用的缓存目录,因为6.0开始,读写SD卡属于危险权限,需要运行时权限,而通过这一点,我们可以跳过这一步

    现在我们使用应用fileProvider来实现这种功能,
    布局代码

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context="com.example.fang.myapplication.MainActivity">
    
        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="拍照" />
    
        <ImageView
            android:id="@+id/imageView"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    
    </LinearLayout>
    

    java文件

    package com.example.fang.myapplication;
    
    import android.content.Intent;
    import android.database.Cursor;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.net.Uri;
    import android.provider.MediaStore;
    import android.support.v4.content.FileProvider;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.MotionEvent;
    import android.view.View;
    import android.widget.Button;
    import android.widget.ImageView;
    
    import java.io.File;
    import java.io.FileNotFoundException;
    
    public class MainActivity extends AppCompatActivity implements View.OnTouchListener {
        File file;
        Uri uri;
      ImageView imageView;
        Button button;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        imageView= (ImageView) findViewById(R.id.imageView);
            button= (Button) findViewById(R.id.button);
            button.setOnTouchListener(this);
        }
    
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            switch (requestCode) {
                case 0: {
                   if(resultCode==RESULT_OK){
                       try {
                             Bitmap bitmap= BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
                           imageView.setImageBitmap(bitmap);
                       } catch (FileNotFoundException e) {
                           e.printStackTrace();
                       }
                   }
                    break;
                }
            }
        }
    
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            file = new File(getBaseContext().getExternalCacheDir(), "image.jpg");//使用的是应用缓存目录
           // uri = Uri.fromFile(file);
              uri=FileProvider.getUriForFile(this,"com.example.fang.myapplication",file);
            Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
            intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
            startActivityForResult(intent, 0);
            return true;
        }
    }
    

    由于这里是FileProvider,所以同样,我们需要在配置文件中进行注册

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.fang.myapplication">
    
        <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
            <activity android:name=".MainActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
            <provider
                android:name="android.support.v4.content.FileProvider"
                android:authorities="com.example.fang.myapplication"
                android:exported="false" android:grantUriPermissions="true">
                <meta-data
                    android:name="android.support.FILE_PROVIDER_PATHS"
                    android:resource="@xml/file_paths"></meta-data>
            </provider>
        </application>
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
    </manifest>

    在Provider中有个meta-data,里面的就是共享地址,我们在里面引用了@xml/file_paths文件,创建代码如下

    <?xml version="1.0" encoding="utf-8"?>
    <paths>
    <external-path name="my_images" path=""/>
    </paths>

    在这里external-path是指定uri共享的,有三种共享方式
    file-path代表的根目录:context.getFilesDir();分享app内部存储
    external-path代表的根目录:environment.getExternalStorageDirectory();分享外部存储
    cache-path代表的根目录:getcacheDir()//分享内部缓冲目录
    //注意,这里对应的文件目录要与共享的文件目录所对应,不然会报错

    展开全文
  • fileprovider使用

    2019-04-09 15:41:16
    <provider android:authorities="com.hexy.yidongapp.provider" android:name="android.support.v4.content.FileProvider" android:grantUriPermissions="true" ...
    <provider
                android:authorities="com.hexy.yidongapp.provider"
                android:name="android.support.v4.content.FileProvider"
                android:grantUriPermissions="true"
                android:exported="false">
                <meta-data
                    android:name="android.support.FILE_PROVIDER_PATHS"
                    android:resource="@xml/yidongfilepaths"/>
            </provider>
    

    name的值一般都固定为android.support.v4.content.FileProvider。如果开发者继承了FileProvider,则可以写上其绝对路径。
    authorities字段的值用来表明使用的使用者,在FileProvider的函数getUriForFile需要传入该参数。
    exported 的值为false,表示该FileProvider只能本应用使用,不是public的。
    grantUriPermissions 的值为true,表示允许赋予临时权限。Intent.setFlags()来添加权限

    <paths xmlns:android="http://schemas.android.com/apk/res/android">
        <files-path name="name" path="path/"/>
        <cache-path name="name" path="path" />
        <external-files-path name="name" path="path" />
        <external-cache-path name="name" path="path" />
        <external-path name="name" path="path" />
    </paths>
    
    files-path:   对应Context.getFilesDir() + “/path/”,即/data/data/<package-name>/files/path/。
    cache-path:   对应Context.getCacheDir() + “/path/”,即/data/data/<package-name>/cache/path/。
    external-files-path:  对应Context.getExternalFilesDir(null) + “/path/”,即/storage/emulated/0/Android/data/<package_name>/files/path/。
    external-cache-path:  对应Context.getExternalCacheDir() + “/path/”,即/storage/emulated/0/Android/data/<package-name>/cache/path/。
    external-path:        对应Environment.getExternalStorageDirectory() + “/path/”,即/storage/emulated/0/path/。
    
    展开全文
  • FileProvider使用

    万次阅读 2017-04-05 16:34:48
    *** FileProvider只能为你指定的目录下files生成content URI。通过属性paths,在xml文件中指定它的内存区域和路径。例如,下面的paths告诉FileProvider,打算为你的私有文件images/子目录请求content URIs。至少一个...
  • 开发SDK过程中,为了兼容Android 7.0以上文件访问问题,引入了FileProvider,但业务方在使用SDK的过程中也引入了FileProvider,导致多个FileProvider共存时,打出的apk包Manifest中少了一个FileProvider或res/xml...
  • android-fileprovider

    2019-04-24 11:00:37
    https://developer.android.com/reference/android/support/v4/content/FileProvider.html ...Defining a FileProvider Specifying Available Files Retrieving the Content URI for a File Granting Tempo...
  • FileProvider详解

    2020-12-10 16:43:39
    Android提供FileProvider类来供应用之间共享数据。 如: <paths xmlns:android="http://schemas.android.com/apk/res/android"> <files-path name="my_images" path="images/"/> ... </paths> ...
  • FileProvider 通用写法

    2019-10-15 16:34:10
    问题 1 声明 在 主module 的manifest 文件中 声明如下...-- FileProvider配置访问路径,适配7.0及其以上 --> <provider android:name="android.support.v4.content.FileProvider" android:authorities="${...
  • 配置FileProvider

    2018-08-06 11:44:18
    配置FileProvider 注意:如果您想兼容Android N或者以上的设备,必须要在AndroidManifest.xml文件中配置FileProvider来访问共享路径的文件。 &lt;provider android:name="android.support.v4.content...
  • Android之FileProvider的使用

    千次阅读 2020-08-24 19:45:25
    文章目录一、FileProvider是什么?二、FileProvider使用步骤1.定义一个FileProvider2.指定可访问的文件3.获取指定文件的Uri4.授予临时权限给Uri5.提供Uri给其他App三、案例 一、FileProvider是什么? FileProvider...
  • 前言 随着Android 7.0的到来,为了进一步提高私有文件的安全性,Android不再由开发者放宽私有...因此,为了更好的适配Android 7.0,例如相机拍照这类涉及到文件地址传递的地方就用上了FileProvider,FileProvide...
  • FileProvider的使用

    千次阅读 2019-08-02 06:58:20
    第一步 声明FIleProvider 第二步 编写XML文件 第三步 使用FileProvider 第一步 声明FIleProvider 为什么要声明呢? 因为FileProvider是ContentProvider子类 注意需要设置一个meta-data,里面...
  • android 7.0 FileProvider

    2018-05-25 11:46:22
    android 7.0及以上版本,应用私有目录被限制访问。此设置可防止私有文件的元数据泄漏,如它们...FileProvider介绍FileProvider是ContentProvider的一个特殊子类,通过content://代替file:///,有助于安全地共享与应...
  • Android FileProvider详细解析和踩坑指南

    万次阅读 多人点赞 2018-12-07 14:29:46
    详细梳理一下android的文件系统,以及做一下FileProvider的解析。
  • FileProvider文件共享

    千次阅读 2017-05-18 11:46:35
    本文是在查看Android文档关于拍照与文件共享知识,看到关于FileProvider相关内容后,尝试使用并遇到一些问题时决定做的笔记。 一、FileProvider 1.FileProvider的出现 Android7.0之前,使用file://URI通常会给出该...
  • 最近在开发flutter项目,遇到fileProvider冲突问题。下面我详细说说这到底是个什么问题。 项目引用了install_plugin自动安装插件、flutter_webview_plugin网页浏览插件。因为这两个插件都需要配置fileProvider。...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 126,530
精华内容 50,612
关键字:

fileprovider