FileProvider的Server和Client

来源:互联网 发布:栗山千明知乎 编辑:程序博客网 时间:2024/05/16 12:33

实例1

ServerTest

当你配置了FileProvider,且当有应用向你请求文件时,你需提供一个窗体,该窗体能实现如下功能:(三步)
→可以被请求文件的应用唤起(就是能被隐式Intent唤起)。
→将自己能够分享的文件显示在窗体里(你可以用ListView实现,安卓官方教程也以这个控件作为例子实现)。
→当用户点击了某个文件,该窗体能提供这个文件的URL(就是将URL返回给调用他的窗体)。

配置清单文件的过滤器
AndroidManifest.xml

<activity    android:name=".ShowFile"    android:label="@string/title_activity_show_file"    android:theme="@style/AppTheme.NoActionBar">    <intent-filter>        <action android:name="android.intent.action.PICK"/>        <category android:name="android.intent.category.DEFAULT"/>        <data android:mimeType="text/plain"/>        <data android:mimeType="image/*"/>    </intent-filter></activity><provider    android:name="android.support.v4.content.FileProvider"    android:authorities="com.example.servertest.fileprovider"    android:exported="false"    android:grantUriPermissions="true">    <meta-data        android:name="android.support.FILE_PROVIDER_PATHS"        android:resource="@xml/file_paths" /></provider>

在res里面创建一个xml文件夹,在里面再创建一个file_paths.xml

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

content_show_file.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="match_parent"    android:layout_height="match_parent">    <ListView        android:id="@+id/file_list"        android:layout_width="match_parent"        android:layout_height="wrap_content"/></LinearLayout>

showFile.class
通过配置ListView实现(我的代码将分享的路径:手机内存/files/images/ )

public class ShowFile extends AppCompatActivity {    private File filesDir;//他将指向内存路径files    private File imageDir;//指向images子路径的:files/images    private File[] imageFiles;//images子路径的所有文件    private String[] imageFileNames;//images子路径的所有文件名字    private Uri fileUri;//image图片地址    private Intent resultIntent;//返回的intent    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.content_show_file);        //获取ListView        ListView fileListView = (ListView)findViewById(R.id.file_list);        //设置Intent        resultIntent = new Intent("com.example.clienttest.ACTION_RETURN_FILE");        //获取文件路径以及名字        filesDir = Environment.getExternalStorageDirectory();        imageDir = new File(filesDir, "images");        //判断目录是否存在        if(!imageDir.exists()){            imageDir.mkdirs();            try{                File file = new File(imageDir,"picture.jpg");                OutputStream out = new FileOutputStream(file);                Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.picture);                //把drawable下的图片拷贝到sdcard的images目录下                bitmap.compress(Bitmap.CompressFormat.JPEG,90,out);                out.flush();                out.close();            }catch (IOException e){                e.printStackTrace();            }        }        //获取images子路径下所有文件        imageFiles = imageDir.listFiles();        //将文件的名字装填        imageFileNames = new String[imageFiles.length];        for(int i = 0; i<imageFiles.length; i++){            imageFileNames[i] = imageFiles[i].getName();        }         /*           通过ListView将文件的名字显示出来           同时设置ListView响应用户对文件的选择        */        fileListView.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,imageFileNames));        fileListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {            @Override            public void onItemClick(AdapterView<?> adapterView, View view, int postion, long l) {                Log.e("server","1");                File requestFile = new File(imageDir,imageFileNames[postion]);                try{                    //标识为"com.example.servertest.provider"的FileProvider获取到文件requestFile,并返回被封装过的URI                    fileUri = FileProvider.getUriForFile(ShowFile.this,                            "com.example.servertest.fileprovider",requestFile);                }catch (Exception e){                    e.printStackTrace();                }                /*                  当用户选择了某个文件,而且服务器成功地得到文件的URI,将URI返回给客户端。                */                if(fileUri!=null){                    //为RUI添加访问权限                    resultIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);                    //设置数据以及数据类型                    resultIntent.setDataAndType(fileUri,getContentResolver().getType(fileUri));                    ShowFile.this.setResult(RESULT_OK,resultIntent);                    finish();                } else {                    resultIntent.setDataAndType(null,"");                    ShowFile.this.setResult(RESULT_CANCELED,resultIntent);                    finish();                }            }        });    }}

现在,服务器的设置已经完成,当有应用需要请求文件,你将可以将你自己的文件给提供出去

△总结:到底服务器都做了什么
→配置FileProvider,指定authorities,指定可分享文件的那个路径(通过配置xml文件)。
→配置,使他能被客户端的隐式Intent唤起。
→配置ListView,当服务器被唤起时,提供一个可被分享的文件的列表。
→配置点击事件响应,当客户端选择文件,生成文件的URI,同时提供相关权限,并且将该文件的URI给客户端(setResult()方法)。




ClientTest

概述:客户端即请求获取某些文件的应用程序。
客户端要做些什么:
→配置Intent,指定客户端想请求访问什么文件
(1)intent.setAction(Intent.ACTION_PICK);
(2)intent.setType(“image/*”);
→启动访问:当用户想访问某些文件,一般情况下,应当是在某个按钮点击事件响应函数里面执行:执行方法: startActivityForResult(intent, 0);
→当服务器提供了想要的文件,客户端要处理自己所得到的文件。
onActivityResult(int requestCode, int resultCode, Intent returnIntent);
方法里面,returnIntent参数,他带着从服务器里返回来的文件URL,通过他来打开我们想访问的文件

AndroidManifest.xml

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>    <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" />                <action android:name="com.example.clienttest.ACTION_RETURN_FILE"/>                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>    </application>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="match_parent"    android:layout_height="match_parent">    <Button        android:id="@+id/button"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="获取图片"/>    <TextView        android:id="@+id/file_uri"        android:layout_width="match_parent"        android:layout_height="wrap_content" />    <TextView        android:id="@+id/file_type"        android:layout_width="match_parent"        android:layout_height="wrap_content" />    <TextView        android:id="@+id/file_name"        android:layout_width="match_parent"        android:layout_height="wrap_content" />    <TextView        android:id="@+id/file_size"        android:layout_width="match_parent"        android:layout_height="wrap_content" />    <ImageView        android:id="@+id/imageview"        android:layout_width="match_parent"        android:layout_height="wrap_content" /></LinearLayout>

MainActivity.class

public class MainActivity extends AppCompatActivity {    private TextView fileUri;    private TextView fileType;    private TextView fileName;    private TextView fileSize;    private ImageView imageView;    private Intent requestIntent;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        requestIntent = new Intent(Intent.ACTION_PICK);        requestIntent.setType("image/jpg");        Button button = (Button) findViewById(R.id.button);        fileUri = (TextView) findViewById(R.id.file_uri);        fileType = (TextView) findViewById(R.id.file_type);        fileName = (TextView) findViewById(R.id.file_name);        fileSize = (TextView) findViewById(R.id.file_size);        imageView = (ImageView) findViewById(R.id.imageview);        button.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                startActivityForResult(requestIntent,0);            }        });    }    @Override    protected void onActivityResult(int requestCode, int resultCode, Intent data) {        super.onActivityResult(requestCode, resultCode, data);        switch (requestCode) {            case 0:                if (resultCode == RESULT_OK) {                    Uri returnUri = data.getData();                    fileUri.setText("uri: " + returnUri);                    fileType.setText("type: " + getContentResolver().getType(returnUri));                    Cursor cursor = getContentResolver().query(returnUri, null, null, null, null);                    int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);                    int sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE);                    cursor.moveToNext();                    fileName.setText("name: " + cursor.getString(nameIndex));                    fileSize.setText("size: " + cursor.getLong(sizeIndex));                    imageView.setImageURI(returnUri);                }                break;            default:                break;        }    }}

当服务器窗体退出之后,客户端的onActivityResult()将被调用。returnIntent参数,就是服务器返回的Intent。Intent包含了文件URI,URI里包含文件各种信息。openFileDescriptor()方法返回ParcelFileDesctiptor,通过ParcelFileDescriptor实例,可以得到FileDescriptor对象,客户端可以通过”FileDescriptor”对象读取那个文件。

△总结:客户端到底做了什么事
→配置一个启动服务器的Intent
→调用方法启动访问
→当得到了服务器的返回信息,处理信息。

原创粉丝点击