FileProvider文件分享

        最近在做一个文件分享的Demo,一连看了两天文档,终于把它给弄出来了。下面是文档中的一段话,大致的意思是通过FileProvider在应用程序之间共享文件的安全的。进程间文件的分享,假设两个应用程序分为Server(共享数据一端)和Client(请求数据一端)。

       在所有情况下,将文件从你的应用程序发送至其它应用程序的唯一的安全方法是向接收文件的应用程序发送这个文件的content URI,并对该URI授予临时的访问权限。具有URI临时访问权限的content URI是安全的,因为他们仅应用于接收这个URI的应用程序,并且它们会自动过期。Android的FileProvider组件提供了getUriForFile())方法来创建一个文件的contentURI。需要对应用进行配置来提供安全的文件句柄(Content URI的形式)。

        在Server(共享数据一端)端,FileProvider的使用需要在程序中进行一些配置。因为文件要安全地从你的应用程序发送给其它应用程序,Android的FileProvider组件会基于你在XML文件中的具体配置,为文件创建Content URI。

        首先,FileProvider包含在Support-V4Library中,使用时应查看应用程序是否已包含有。然后,使用ContentProvider那就必须在Manifest文件中进行注册。注册一个provider如下:

        <provider

                 android:name="android.support.v4.content.FileProvider"

                 android:authorities="com.junxu.sharefile.fileprovider"

                 android:grantUriPermissions="true"

                 android:exported="false">

                <meta-data

                          android:name="android.support.FILE_PROVIDER_PATHS"

                           android:resource="@xml/filepaths"/>

        </provider>

 

        上面的android:authorities属性字段指定了你希望使用的Authority,该Authority针对于FileProvider所生成的contentURI。在这个例子中,这个Authority是

“com.junxu.sharefile.fileprovider”。一般情况下,用应用程序包名(android:package的值)之后继续追加“fileprovider”来作为Authority的值。 name注属性的值固定,表示support.v4中的FileProvider类。

contentProvider的属性介绍访问:http://blog.csdn.net/berber78/article/details/39252727

        <provider>下的子标签<meta-data>指向了一个XML文件,该文件指定了你希望共享的目录路径。“android:resource”属性字段是这个文件的路径和名字(无“.xml”后缀)。

一旦你在你的Manifest清单文件中为你的应用添加了FileProvider,你需要指定你希望共享文件的目录路径。为了指定这个路径,首先在“res/xml/”下创建文件“filepaths.xml”。在这个文件中,为每一个想要共享目录添加一个XML标签。下面的是一个“res/xml/filepaths.xml”的内容样例。这个例子也说明了如何在你的内部存储区域共享一个“files/”目录的子目录:

         <?xml version="1.0" encoding="UTF-8"?>

             <resources> 

                <paths > 

                     <files-pathname="myimages" path="images/" /> 

               </paths > 

         </resources> 

         在这个例子中,<files-path>标签共享的是在应用的内部存储中“files/”目录下的目录。“path”属性字段指出了该子目录为“files/”目录下的子目录“images/”。“name”属性字段告知FileProvider向在“files/images/”子目录中的文件的Content URI添加路径分段(path segment)标记:“myimages”。比如上面的<files-path>标签表示共享/data/data/package(包名)/files/images文件夹中的文件或图片。即用path的值接在/data/data/package(包名)/files之后,生成的Uri为content://Authority/ myimages/ in.png(文件名),这个Uri就相当于文件:/data/data/package(包名)/files/images/in.png向外暴露的个体其他应用程序访问的路径。 (注意在生成Uri是,需确保在/data/data/package(包名)/files/下有你要共享的文件夹及文件,即确保共享的数据存在)

         <paths>标签可以有多个子标签,每一个子标签用来指定不同的共享目录。除了<files-path>标签,你还可以使用<external-path>来共享位于外部存储的目录;另外,<cache-path>标签用来共享在你的内部缓存目录下的子目录。到现在FileProvider的配置已经完成了。

        创建一个Activity,这个Activity用于接收其他应用程序发送的文件请求。当其他应用程序需要获取文件时,通过startActivityForResult启动这个Activity,所以这个Activity将共享文件夹下的所有文件显示在这个Activity上,供其他应用程序选择,当用户程序选择了文件之后,生成这个文件的Uri,然后通过setResult返回,并结束本Activity。


为了能让其他应用程序可以启动这个Activity,需要在Manifest文件中注册并配置这个Activity。

      <activity

            android:name="com.junxu.sharefile.FileSelectActivity"

            android:label=".FileSelect">

           <intent-filter >

                <actionandroid:name="android.intent.action.PICK" />

               <categoryandroid:name="android.intent.category.DEFAULT" />

               <categoryandroid:name="android.intent.category.OPENABLE"/>

               <dataandroid:mimeType="text/plain" />

               <dataandroid:mimeType="image/*"/>

         </intent-filter>

       </activity>

        在其Intent过滤器中,匹配ACTION_PICK这一Action,以及CATEGORY_DEFAULT和CATEGORY_OPENABLE这两种Category。另外,还需要为你的应用程序设置MIME类型过滤器,来表明你的应用程序可以向其他应用程序提供哪种类型的文件。

Activity的属性介绍参考:http://blog.csdn.net/voiceofnet/article/details/7770311

 

          //获得手机内部存储路径(/data/data/(包名) )

            mPrivateRootDir = getFilesDir();

            mImagesDir = new File(mPrivateRootDir, "images");//路径(/data/data/(包名) /iamges)

            mImageFiles =mImagesDir.listFiles();    //获取路径下的所有文件

            //将文件保存在list对象中,然后通过listView显示出来

           for(int i=0;i<mImageFiles.length;i++){

                    String path = mImageFiles[i].getAbsolutePath();

                    Bitmap bm = BitmapFactory.decodeFile(path);

                    FileInfo fInfo = newFileInfo(path.substring(path.lastIndexOf("/")+1), path, bm);

                    files.add(fInfo);

           }

 

         @Override

          public voidonItemClick(AdapterView<?> parent, View view, int position, long id) {

                   FilerequestFile = new File(files.get(position).getPath());

                   Stringauthority="com.junxu.sharefile.fileprovider";// authority

                   Log.d("********",files.get(position).getPath());

                   try{

                            UrifileUri = FileProvider.getUriForFile(FileSelectActivity.this, authority,requestFile);//生成对应文件的Uri

                            Log.d("********",fileUri.toString());

                            if(fileUri!=null){

                                     //设置权限, 所授予的权限是临时的,并且当接收文件的应用程序的任务栈终止后,会自动过期

                                     mResultIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

                                     //设置数据类型

                                      mResultIntent.setDataAndType(fileUri,getContentResolver().getType(fileUri));

                                     setResult(Activity.RESULT_OK,mResultIntent);

                                     Log.d("********", "ok"+RESULT_OK);

                             }

                      }catch(IllegalArgumentExceptione){

                             e.printStackTrace();

                              mResultIntent.setDataAndType(null,"");

                              setResult(RESULT_CANCELED,mResultIntent);

                       }

                   finish();//结束当前activity

         }

 

        在Client一端,向服务端应用程序发送文件请求,需要调用startActivityForResult)方法,同时传递给这个方法一个Intent参数,它包含了客户端应用程序能处理的某个Action,比如ACTION_PICK;以及一个MIME类型。示例程序如下:

             Intent mRequestFileIntent = new Intent(Intent.ACTION_PICK);

             mRequestFileIntent.setType("image/jpg");

             startActivityForResult(mRequestFileIntent, 0);

 

       在Client端的Activity中需要重写onActivityResult())方法,接收Server端返回的数据。Client端选择文件之后, 服务端应用程序向客户端应用程序发回包含所选文件的Content URI的Intent,客户端应用程序从这个intent后的文件的Content URI,就可以通过获取其FileDescriptor来访问文件了。

 

        @Override

         protected void onActivityResult(int requestCode, int resultCode,Intent data) {

                      Log.d("******"," 222"+resultCode);

                      if( resultCode !=RESULT_OK ){

                                 return;

                      }else{

                                  Uri fileUri = data.getData();//获得Uri            

                                  Cursor returnCursor = getContentResolver().query(fileUri,null, null, null, null);

                                  //获得文件名

                                   int nameIndex =returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);

                                 //获得文件大小

                                  int sizeIndex =returnCursor.getColumnIndex(OpenableColumns.SIZE);

                                                           returnCursor.moveToFirst();

                          

                                                           info.setText("\t文件名:"+returnCursor.getString(nameIndex)+"\n\t文件大小:"+returnCursor.getString(sizeIndex));

                                                           Log.d("*****",returnCursor.getString(nameIndex));

                                                           Log.d("*****", returnCursor.getString(sizeIndex));

                          

                                                          returnCursor.close(); 

                          

                                    Bitmap bm = null;

                                    //获得图片并显示

                                    try {

                                                    InputStreamis = getContentResolver().openInputStream(fileUri);

                                                   bm= BitmapFactory.decodeStream(is);

                                                     img.setImageBitmap(bm);

                                      } catch(FileNotFoundException e) {

                                                    e.printStackTrace();

                                     }

              }

     }

 

 

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值