Android知识要点整理(4)----简单数据分享

内容分享是Android App很重要的一个功能。借助内容分享的功能,你可以发送数据给其他APP,可以接收其他APP发来的数据,还可以发送文件或者图片到其他的设备,实现文件的分享功能。下面就从3个方面总结一下Android的内容分享功能。

1. 分享简单数据

在Activity中发送数据给另一个Activity或者另一个APP都可以通过action 为 ACTION_SEND的Intent来完成。Intent中可以设置要分享的数据以及分享的数据类型。系统会根据Intent查找有哪些APP可以处理该Intent,如果有多个应用能够处理该Intent,那么系统会弹出一个选择列表给用户选择,如果只有一个则会直接调起该应用来处理Intent。

分享文本内容

最常见的情况是分享一些文本内容给其他APP。比如我们浏览器APP可以分享当前页面的URL链接给其他应用,通常是分享一篇文章或者一个网址。下面代码片段发送一段简单的文字给其他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_SENDtext/plain类型的数据的APP,系统就会启动它来处理。如果有多个的就会弹出如下类似的对话框:
Android知识要点整理(4)----简单数据分享_第1张图片
有时候我们希望在任何情况下都弹出选择框让用户选择,这时我们可以用到Intent.createChooser,这种方式还可以指定对话框的标题

startActivity(Intent.createChooser(intent,"分享文字到"));

Android知识要点整理(4)----简单数据分享_第2张图片
上面分享的数据是通过EXTRA_TEXT字段指定的,其实我们还可指定其他字段诸如EXTRA_EMAILEXTRA_CCEXTRA_BCCEXTRA_SUBJECT,这些通常用于发送邮件内容,不过在如果目标APP不需要这些内容可以直接忽略。

分享二进制内容

二进制内容通常是一些图片文件,通过EXTRA_STREAM可以指定要分享的二进制内容。

Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_STREAM, mImageUri);
intent.setType("image/jpeg");
startActivity(Intent.createChooser(intent,"分享到"));

需要注意的是,处理该分享Intent的APP必须要有访问图片的权限,否则将不能正确处理请求。有2中方法可以达到目的:

  • 将需要分享的二进制内容存储在自定义的ContentProvider中,确保其他应用能够访问到该provider。通常的做法是针对当前的URI提供访问权限,这种授权是临时的并且只针对接收该Intent的应用。系统提供的FileProvider类,让我们可以很容易做到这一点。关于FileProvider的用法,我们会在下一篇文章中讲到。

  • 第二种方法是使用系统的MediaStore类。在Android 3.0之前,MediaStore主要用来存储图片、音视频等内容,从3.0开始也可以用来存储其他类型的二进制内容。MediaStore通过扫描文件(scanFile()方法)将文件信息插入到MediaStore,扫描完后onScanComplete方法会被回调,该回调方法会传入一个形如content://格式的uri用于分享。扫描通常是在外存目录(Music、Image等目录)中有新的文件时自动进行的。

同时分享多个内容

有时候我们想同时分享多张图片,这时候需要用到ACTION_SEND_MULTIPLE。通过指定一系列图片的URI来同时分享多张图片。同样我们要确保其他应用有访问这些uri的权限。

ArrayList<Uri> imageUris = new ArrayList<Uri>();
imageUris.add(imageUri1); // 在这里添加要分享的图片的uri
imageUris.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, "分享图片到"));

2. 接收简单数据

上面讲述了如何分享数据给其他的APP,接下来讲一下如何接收处理来自其他APP的分享数据。

定义Intent-filter

首先要定义处理IntentActivity,并在AndroidManifest.xml中注册能够接受的IntentFilter.例如,下面的代码片段定义了一个能够处理来自其他APP分享的文本和图片内容的Activity:

<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>

当有APP通过构造这样的Intent来分享数据时,我的APP就会出现在弹出的选择框中供用户选择。如果用户选择了我们的APP,那么上面注册的MyActivity就会被启动运行。接下来要做的就是在MyActivity里完成处理这些分享的逻辑代码。

处理接收到的分享内容

private void handleIntent() {
    Intent intent = getIntent();
    String action = intent.getAction();
    String type = intent.getType();
    if(TextUtils.equals(Intent.ACTION_SEND,action) && type != null) {
        if (TextUtils.equals(type, "text/plain")) {
            //处理文本内容
            handleTextIntent(intent);
        } else {
            //处理图片内容
            handleImageIntent(intent);
        }
    }
}

private void handleImageIntent(Intent pIntent) {
    Uri uri = pIntent.getParcelableExtra(Intent.EXTRA_STREAM);
    if(uri == null) return;
    mImageIv.setImageURI(uri);
}

private void handleTextIntent(Intent pIntent) {
    String content = pIntent.getStringExtra(Intent.EXTRA_TEXT);
    mContentTv.setText(content == null ? "no content" : content);
}

处理数据时一定要检查数据的合理性,因为我们不知道接收的是何种数据,所以一定要考虑的各种情况,增强APP的健壮性。

3. 添加一种简单的分享操作

讲完了简单数据的分享和处理,还跟大家讲一讲在Android 4.0中新增的一种分享操作ShareActionProvider。分享操作的按钮一般放在Toolbar中,通过使用ShareActionProvider可以简单高效并且很友好的实现分享操作。

定义分享菜单

像为Toolbar添加普通的菜单项一样,我们需要声明一个用于分享的菜单项。不同的是,我们要在菜单项中指定android:actionProviderClass属性。代码如下:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">
    <item android:id="@+id/menu_share" app:showAsAction="always" android:title="分享" android:actionProviderClass="android.widget.ShareActionProvider"/>
</menu>

上述代码中,我们指定android:actionProviderClass的值为系统类ShareActionProvider,这个类为我们做了分享操作的大部分工作,我们只需要在适当的时候设置要分享的内容的Intent给它就行了。

设置分享内容Intent

为了让ShareActionProvider正常工作,我们必需要给它设置要分享的内容的Intent。Intent的构造方法和普通的Intent一样,指定action 为 ACTION_SENDACTION_SEND_MULTIPLE,同时设定分享内容和所属的类型,然后调用ShareActionProvider#setShareIntent方法。这样当我们触发分享菜单项时,就会执行相应的分享操作。代码如下:

//初始化菜单,获取ShareActionProvider对象
 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
     getMenuInflater().inflate(R.menu.menu_itmes, menu);
     MenuItem shareItem = menu.findItem(R.id.menu_share);
     mActionProvider = (ShareActionProvider)shareItem.getActionProvider();
     return true;
 }
......
//监听文本内容变化,更新要分享的Intent
@Override
public void afterTextChanged(Editable s) {
    String text = s.toString();
    Intent intent = new Intent(Intent.ACTION_SEND);
    intent.putExtra(Intent.EXTRA_TEXT, text);
    intent.setType("text/plain");
    setShareIntent(intent);
}
......
//设置Intent到ShareActionProvider
private void setShareIntent(Intent pIntent) {
    if(mActionProvider != null){
        mActionProvider.setShareIntent(pIntent);
    }
}

4. ACTION_SENDACTION_SENDTO对比

ACTION_SEND的发送动作的目标是没有指定的,只要匹配了action和dataType的activity都可以处理。
ACTION_SENDTO是发送给特定的目标,目标通常通过data uri来指定,即除了匹配action和dataType,还必须匹配data uri,如果Intent中没有指定 data URI 则系统匹配不到任何ACTIVITY。

分享简单的文本内容是Android APP中常用的功能,但是文本内容太少,很多时候需要分享图片,大文件的操作,这就涉及到文件分享,下一章将详细介绍分享文件的一些重点知识,敬请期待。

你可能感兴趣的:(Android知识要点整理(4)----简单数据分享)