Android应用程序间的内容分享机制

来源:互联网 发布:淘宝买家信誉度怎么看 编辑:程序博客网 时间:2024/05/17 02:40



摘要 当您创建一个intent的时候,您必须指定您想让intent触发的行为。Android定义了若干行为,包括 ACTION_SEND 。您可能猜到了,ACTION_SEND表明intent从一个应用中携带了数据发送给另外一个应用,甚至可以跨线程传输。为了向其他应用发送数据,您所要做的只需要

向其他应用发送内容

当您创建一个intent的时候,您必须指定您想让intent触发的行为。Android定义了若干行为,包括ACTION_SEND。 您可能猜到了,ACTION_SEND表明intent从一个应用中携带了数据发送给另外一个应用,甚至可以跨线程传输。为了向其他应用发送数据,您所要 做的只需要定义数据和它的类型,系统会自动分辨能够接受这些数据的应用,然后显示给用户(如果有多个选项的话)或者立即执行这个应用(如果只有一个选 项)。相对的,您可以在manifest里声明您的应用能够支持的,从其他应用接收的数据类型。

用intents在应用之间发送和接收数据最常被用于分享内容。intents允许用户用他们喜爱的应用,来快速方便的分享信息。

注:向ActionBar添加一个分享按钮最好的方法是使用ShareActionProvider,ShareActionProvider从API level 14开始可用。在有关Adding an Easy Share Action一节有ShareActionProvider的讨论。


发送文本内容

ACTION_SEND行为最直接和和常见的用法是从一个应用向另一个内容发送文本内容。例如内置浏览器程序可以以文本的形式,向任何应用分享当前显示的 页面的URL。这在通过email或者社交网络向朋友分享一个文章或者网站时是很有用的。如下是实现这种分享方式的代码:

1
2
3
4
5
Intent sendIntent = newIntent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT,"This is my text to send.");
sendIntent.setType("text/plain");
startActivity(sendIntent);

如果只有一个已安装应用的过滤器符合ACTION_SEND和text/plain的MIME类型,Android系统会运行这个应用;如果多个应用符合,系统会显示一个消歧对话框(一个选择器)让用户选择应用。如果您为此intent调用java.lang.CharSequence) Intent.createChooser(),Android会始终显示这个选择器。这么做的好处是:

  • 即使用户已经为这个intent预先选择了一个默认的行为,仍然会显示选择器。

  • 如果没有相符的应用,Android会显示一个系统信息。

  • 您可以为这个选择对话框指定一个标题。

share-text-screenshot.png

图一

如下是使用createChooser()的代码:

1
2
3
4
5
Intent sendIntent = newIntent();
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));

结果对话框如图1所示

作为可选项,您可以为您intent的设置一些标准扩展:EXTRA_EMAIL, EXTRA_CC, EXTRA_BCC, EXTRA_SUBJECT。但是,如果接受的应用不是为之设计的,此次行为将被忽略。您同样可以使用自定义扩展,但是除非接收应用能够理解,这些扩展将没有效果。通常情况下,您应该使用接收应用自己定义的自定义扩展。

注:一些e-mail应用-例如Gmail-在接到一些例如EXTRA_EMAIL和EXTRA_CC的扩展时需要一个String[] ,使用java.lang.String[) putExtra(String, String[])]来将这些添加到您的intent中。


发送二进制内容


二进制数据是通过使用ACTION_SEND行为结合设置适当的MIME类型,或者放置URI到名为EXTRA_STREAM的扩展数据里来分享的。这通常被用来分享图像,但也可以分享任何类型的二进制内容:

1
2
3
4
5
Intent shareIntent = newIntent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, uriToImage);
shareIntent.setType("image/jpeg");
startActivity(Intent.createChooser(shareIntent, getResources().getText(R.string.send_to)));

注意:

  • 您可以使用MIME类型"*/*",但是这只会匹配那些能够接收通用数据流的应用。

  • 接收方应用需要能够访问Uri所指向内容的权限。这里有一些方法来处理它:

    • 将数据写在扩展存储或者共享存储(例如SD卡)的文件中.使用Use Uri.fromFile()来建立传递给intent的Uri。但请记住不是所有的应用都能处理file://类型的Uri。

    • 在MODE_WORLD_READABLE模式下,使用(int) openFileOutput()将数据写在您自己的应用目录下的文件中,之后getFileStreamPath()可以用来返回一个文件。和前面一条相同,Uri.fromFile()会为您的intent建立一个file://类型的Uri。

    • 媒体文件和图像相同,可以通过使用scanFile()扫描视频和音频并添加进系统的MediaStore。onScanCompleted()的回调返回一个content://类型的Uri来匹配您的intent。

    • insertImage()可以将图像插入到系统MediaStore中,并返回一个content://类型的Uri来匹配您的intent。

    • 将数据保存到您自己的ContentProvider中,以保证其他应用有正确访问您provider的权限(或者使用per-URI权限)。


发送复杂数据内容


使用ACTION_SEND_MULTIPLE行 为整合指向内容的URI列表,可以发送复合内容。MIME类型会根据您分享内容的组合而改变。例如,如果您分享3个JPEG图像,MIME类型仍然 是"image/jpeg"。对于混合的图像类型,MIME将会设置为"image/*"来匹配可以处理所有类型图像的应用。您应该只将"*/*"用在分 享很多不同类型的时候。如前所述,此将传递给接收应用来解析和处理您的数据。例子如下:


1
2
3
4
5
6
7
8
9
ArrayList<Uri> imageUris = newArrayList<Uri>();
imageUris.add(imageUri1);// Add your image URIs here
imageUris.add(imageUri2);
    
Intent shareIntent = newIntent();
shareIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
shareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, imageUris);
shareIntent.setType("image/*");
startActivity(Intent.createChooser(shareIntent,"Share images to.."));

和之前一样,请确保提供的URI指向接收方应用能够访问的数据。


从其他程序中接收内容

应用程序能够发送数据到其他程序,同样,也能够接收从其他程序发送过来的数据。需要考虑的是用户与应用程序如何进行交互,你想要从其他程序接收哪些数据类型。例如,一个社交网络程序会希望能够从其他程序接受文本数据,像一个有趣的网址链接。Google+ Android application客户端会接受文本数据与单张或者多张图片。通过这个程序,用户可以很方便地从Gallery程序选择一张图片来启动Google+进行发布。


更新Manifest文件 

Intent filters通知Android系统一个程序会接受哪些数据。和Send Content to Other Apps Using Intents一课中用ACTION_SEND动作生成一个intent一样,可以通过在manifest文件中用 <intent-filter>元素标签来定义intent filters以表明程序能够接收哪些intent。下面是个例子,定义的activity分别指定了可以接收文本、单张图片或者多张图片。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<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>

注意:更多关于intent和intent filter的信息,请参考Intents and Intent Filters


当另外一个程序通过创建intent并传给startActivity()以尝试分享一些东西时,你的程序会被呈现在一个列表里面让用户进行选择。如果用户选择了你的程序,相应的activity就应该被调用开启(上面例子中的.ui.MyActivity),这个时候就是你如何处理获取到的数据的问题了。


处理接收到的数据 

为了处理从Intent传过来的数据,可以通过调用getIntent()方法来获取到Intent对象。一旦获取该对象,就可以对里面的数据进行判断,从而决定下一步应该做什么。请记住,如果一个activity可以被其他的程序启动,你需要在检查intent的时候考虑这种情况。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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
        }elseif (type.startsWith("image/")) {
            handleSendImage(intent);// Handle single image being sent
        }
    }elseif (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
    }
}

敬告:因为你无法知道其他程序发送过来的数据内容是文本还是其他的数据,例如设置错误的MIME类型或者发送了过大的图片,因此你需要避免在UI线程里面而是在单独的线程里去处理那些获取到的二进制数据。

更新UI可以像更新EditText一样简单,也可以是比过滤出感兴趣的图片还复杂的操作。因此,接下来会发生什么事情最终要取决于你的程序。

0 0
原创粉丝点击