Android 分享文件

来源:互联网 发布:apache tomcat 6 编辑:程序博客网 时间:2024/05/16 19:43

第一部分:发送简单数据给其他App


最简单的方式是通过Intent:

比如要分享文本给其他App,可以这样


Intent sendIntent= new Intent();sendIntent.setAction(Intent.ACTION_SEND);sendIntent.putExtra(Intent.EXTRA_TEXT, "This is my text to send.");sendIntent.setType("text/plain");startActivity(sendIntent);
如果有一个安装的应用程序与过滤器相匹配action_send和MIME类型,Android系统将运行它;如果有多个应用程序匹配,系统显示一个对话框(消歧“选择器”),允许用户选择一个应用程序。但是这种方式如果只有一个或者用户之前操作已经选择了默认打开该类型的App则不会显示选择对话框。如果你要总是显示选择对话框,可以这样定义:


Intent sendIntent = new Intent();sendIntent.setAction(Intent.ACTION_SEND);sendIntent.putExtra(Intent.EXTRA_TEXT, "This is my text to send.");sendIntent.setType("text/plain");startActivity(Intent.createChooser(sendIntent, getResources().getText(R.string.send_to)));

如果你要一次分享多条数据,可以使用ACTION_SEND_MULTIPLE:


比如

ArrayList<Uri> imageUris = new ArrayList<Uri>();imageUris.add(imageUri1); // Add your image URIs hereimageUris.add(imageUri2);Intent shareIntent = new Intent();shareIntent.setAction(Intent.ACTION_SEND_MULTIPLE);shareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, imageUris);shareIntent.setType("image/*");startActivity(Intent.createChooser(shareIntent, "Share images to.."));
如果你的应用需要支持处理某种类型的数据可以在manifest文件中加过滤器,比如


<activity android:name=".ui.MyActivity" >    <intent-filter>        <action android:name="android.intent.action.SEND" />        <category android:name="android.intent.category.DEFAULT" />        <data android:mimeType="image/*" />    </intent-filter>    <intent-filter>        <action android:name="android.intent.action.SEND" />        <category android:name="android.intent.category.DEFAULT" />        <data android:mimeType="text/plain" />    </intent-filter>    <intent-filter>        <action android:name="android.intent.action.SEND_MULTIPLE" />        <category android:name="android.intent.category.DEFAULT" />        <data android:mimeType="image/*" />    </intent-filter></activity>
处理传进来的数据,可以按照一下方式处理:


void onCreate (Bundle savedInstanceState) {    ...    // Get intent, action and MIME type    Intent intent = getIntent();    String action = intent.getAction();    String type = intent.getType();    if (Intent.ACTION_SEND.equals(action) && type != null) {        if ("text/plain".equals(type)) {            handleSendText(intent); // Handle text being sent        } else if (type.startsWith("image/")) {            handleSendImage(intent); // Handle single image being sent        }    } else if (Intent.ACTION_SEND_MULTIPLE.equals(action) && type != null) {        if (type.startsWith("image/")) {            handleSendMultipleImages(intent); // Handle multiple images being sent        }    } else {        // Handle other intents, such as being started from the home screen    }    ...}void handleSendText(Intent intent) {    String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);    if (sharedText != null) {        // Update UI to reflect text being shared    }}void handleSendImage(Intent intent) {    Uri imageUri = (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM);    if (imageUri != null) {        // Update UI to reflect image being shared    }}void handleSendMultipleImages(Intent intent) {    ArrayList<Uri> imageUris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);    if (imageUris != null) {        // Update UI to reflect multiple images being shared    }}
如果你要通过Actionbar菜单的方式来分享数据,可以这样


menu菜单可以这样定义


<menu xmlns:android="http://schemas.android.com/apk/res/android">    <item            android:id="@+id/menu_item_share"            android:showAsAction="ifRoom"            android:title="Share"            android:actionProviderClass=                "android.widget.ShareActionProvider" />    ...</menu>
在Activity中可以这样使用


private ShareActionProvider mShareActionProvider;...@Overridepublic boolean onCreateOptionsMenu(Menu menu) {    // Inflate menu resource file.    getMenuInflater().inflate(R.menu.share_menu, menu);    // Locate MenuItem with ShareActionProvider    MenuItem item = menu.findItem(R.id.menu_item_share);    // Fetch and store ShareActionProvider    mShareActionProvider = (ShareActionProvider) item.getActionProvider();    // Return true to display menu    return true;}// Call to update the share intentprivate void setShareIntent(Intent shareIntent) {    if (mShareActionProvider != null) {        mShareActionProvider.setShareIntent(shareIntent);    }}

第二部分发送文件给App(它是通过 FileProvider来实现的)

实现步骤如下

第一步,在xml文件加下面新建一个文件(比如名字叫filepaths)


filepaths.xml文件内容如下

<paths>    <files-path path="images/" name="myimages" /></paths>
paths节点下面总共有如下子节点"root-path","files-path","cache-path""external-path",

"external-files-path","external-cache-path",子节点属性只有path和name。path就是共享文件路径,name就是你给当前
这个子节点分享的文件取的一个别名。
第二步就是在manifest文件下添加如下定义
<provider            android:name="android.support.v4.content.FileProvider"            android:authorities="com.example.myapp.fileprovider"            android:grantUriPermissions="true"            android:exported="false">            <meta-data                android:name="android.support.FILE_PROVIDER_PATHS"                android:resource="@xml/filepaths" />        </provider>
其中meta-data属性一定要,它指定了分享文件的name,这个name是系统指定的,不能随便填写,resource指定了分享文件的xml
我们再在客户端的manifest文件中在显示共享文件的Activity下面添加如下配置
<activity                android:name=".FileSelectActivity"                android:label="@File Selector" >                <intent-filter>                    <action                        android:name="android.intent.action.PICK"/>                    <category                        android:name="android.intent.category.DEFAULT"/>                    <category                        android:name="android.intent.category.OPENABLE"/>                    <data android:mimeType="text/plain"/>                    <data android:mimeType="image/*"/>                </intent-filter>            </activity>

当别的App请求访问我们提供的文件(图片),并且我们的图片很多的时候,我们会显示一个列表(比如ListView)给它选择
,这个时候我们Item点击事件可以如下定义
protected void onCreate(Bundle savedInstanceState) {
 // Set up an Intent to send back to apps that request a file        mResultIntent =new Intent("com.example.myapp.ACTION_RETURN_FILE");
        ...
//set  up an Intent to send back to apps that requesst a file
mResutIntent=new Intent("com.example.myapp.ACTION_RETURN_FILE")        // Define a listener that responds to clicks on a file in the ListView        mFileListView.setOnItemClickListener(                new AdapterView.OnItemClickListener() {            @Override            /*             * When a filename in the ListView is clicked, get its             * content URI and send it to the requesting app             */            public void onItemClick(AdapterView<?> adapterView,                    View view,                    int position,                    long rowId) {                /*                 * Get a File for the selected file name.                 * Assume that the file names are in the                 * mImageFilename array.                 */                File requestFile = new File(mImageFilename[position]);                /*                 * Most file-related method calls need to be in                 * try-catch blocks.                 */                // Use the FileProvider to get a content URI                try {                    fileUri = FileProvider.getUriForFile(                            MainActivity.this,                            "com.example.myapp.fileprovider",                            requestFile);                } catch (IllegalArgumentException e) {                    Log.e("File Selector",                          "The selected file can't be shared: " +                          clickedFilename);                }
if (fileUri != null) {
// Grant temporary read permission to the content URI                    mResultIntent.addFlags(                        Intent.FLAG_GRANT_READ_URI_PERMISSION);
                    ...                    // Put the Uri and MIME type in the result Intent                    mResultIntent.setDataAndType(                            fileUri,                            getContentResolver().getType(fileUri));                    // Set the result                    MainActivity.this.setResult(Activity.RESULT_OK,                            mResultIntent);                    } else {                        mResultIntent.setDataAndType(null, "");                        MainActivity.this.setResult(RESULT_CANCELED,                                mResultIntent);                    }
            }        });        ...    }
到这里我们服务端即共享文件端的配置已经配置好了。
接下来就是客户端的,也就是请求接受共享文件端
 
public class MainActivity extends Activity {    private Intent mRequestFileIntent;    private ParcelFileDescriptor mInputPFD;    ...    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        mRequestFileIntent = new Intent(Intent.ACTION_PICK);        mRequestFileIntent.setType("image/jpg");        ...    }    ...    protected void requestFile() {        /**         * When the user requests a file, send an Intent to the         * server app.         * files.         */            startActivityForResult(mRequestFileIntent, 0);        ...    }    ...}
我们接着重写client即请求共享文件App的onActivityResult回调
 /*     * When the Activity of the app that hosts files sets a result and calls     * finish(), this method is invoked. The returned Intent contains the     * content URI of a selected file. The result code indicates if the     * selection worked or not.     */    @Override    public void onActivityResult(int requestCode, int resultCode,            Intent returnIntent) {        // If the selection didn't work        if (resultCode != RESULT_OK) {            // Exit without doing anything else            return;        } else {            // Get the file's content URI from the incoming Intent            Uri returnUri = returnIntent.getData();            /*             * Try to open the file for "read" access using the             * returned URI. If the file isn't found, write to the             * error log and return.             */            try {                /*                 * Get the content resolver instance for this context, and use it                 * to get a ParcelFileDescriptor for the file.                 */                mInputPFD = getContentResolver().openFileDescriptor(returnUri, "r");            } catch (FileNotFoundException e) {                e.printStackTrace();                Log.e("MainActivity", "File not found.");                return;            }            // Get a regular file descriptor for the file            FileDescriptor fd = mInputPFD.getFileDescriptor();            ...        }    }

到这里文件共享方式就完毕了.
由于这个URI不包含目录路径,客户端应用程序无法发现和服务器应用程序打开的任何其他文件。
只有客户端应用程序才可以访问该文件,并且只对服务器应用程序授予的权限进行访问。权限是临时的,
所以一旦客户端应用程序的任务堆栈完成,该文件将不再在服务器应用程序之外访问。
当接收活动的Activity等组件的堆栈处于活动状态时,在意图中授予的权限保持有效。当堆栈完成后,权限将被自动移除。
授予客户端应用程序中的一个活动的权限将自动扩展到该应用程序的其他组件。





0 0
原创粉丝点击