12) 十分钟学会android--APP通信传递消息之简单数据传输
程序间可以互相通信是Android程序中最棒的功能之一。当一个功能已存在于其他app中,且并不是本程序的核心功能时,完全没有必要重新对其进行编写。
本章节会讲述一些通在不同程序之间通过使用Intent APIs与ActionProvider对象来发送与接受content的常用方法。
Lessons
向其他App发送简单的数据 - Sending Simple Data to Other Apps
学习如何使用intent向其他app发送text与binary数据。
接收从其他App返回的数据 - Receiving Simple Data from Other Apps
学习如何通过Intent在我们的app中接收来自其他app的text与binary数据。
给ActionBar增加分享功能 - Adding an Easy Share Action
学习如何在Acitonbar上添加一个分享功能。
给其他App发送简单的数据
在构建一个intent时,必须指定这个intent需要触发的actions。Android定义了一些actions,比如ACTION_SEND,该action表明该intent用于从一个activity发送数据到另外一个activity的,甚至可以是跨进程之间的数据发送。
为了发送数据到另外一个activity,我们只需要指定数据与数据的类型,系统会自动识别出能够兼容接受的这些数据的activity。如果这些选择有多个,则把这些activity显示给用户进行选择;如果只有一个,则立即启动该Activity。同样的,我们可以在manifest文件的Activity描述中添加接受的数据类型。
在不同的程序之间使用intent收发数据是在社交分享内容时最常用的方法。Intent使用户能够通过最常用的程序进行快速简单的分享信息。
注意:为ActionBar添加分享功能的最佳方法是使用ShareActionProvider,其运行与API level 14以上的系统。ShareActionProvider将在第3课中进行详细介绍。
分享文本内容(Send Text Content)
ACTION_SEND最直接常用的地方是从一个Activity发送文本内容到另外一个Activity。例如,Android内置的浏览器可以将当前显示页面的URL作为文本内容分享到其他程序。这一功能对于通过邮件或者社交网络来分享文章或者网址给好友而言是非常有用的。下面是一段Sample Code:
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类型为text/plain的程序,则Android系统会立即执行它。若有多个匹配的程序,则系统会把他们都给筛选出来,并呈现Dialog给用户进行选择。
如果为intent调用了Intent.createChooser(),那么Android总是会显示可供选择。这样有一些好处:
- 即使用户之前为这个intent设置了默认的action,选择界面还是会被显示。
- 如果没有匹配的程序,Android会显示系统信息。
- 我们可以指定选择界面的标题。
下面是更新后的代码:
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));
效果图如下:
另外,我们可以为intent设置一些标准的附加值,例如:EXTRA_EMAIL, EXTRA_CC, EXTRA_BCC, EXTRA_SUBJECT等。然而,如果接收程序没有针对那些做特殊的处理,则不会有对应的反应。
注意:一些e-mail程序,例如Gmail,对应接收的是EXTRA_EMAIL与EXTRA_CC,他们都是String类型的,可以使用putExtra(string,string[])方法来添加至intent中。
分享二进制内容(Send Binary Content)
分享二进制的数据需要结合设置特定的MIME类型,需要在
EXTRA_STREAM`里面放置数据的URI,下面有个分享图片的例子,该例子也可以修改用于分享任何类型的二进制数据:
Intent shareIntent = new Intent();
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类型,但是这仅仅会match到那些能够处理一般数据类型的Activity(即一般的Activity无法详尽所有的MIME类型) - 接收的程序需要有访问URI资源的权限。下面有一些方法来处理这个问题:
- 将数据存储在ContentProvider中,确保其他程序有访问provider的权限。较好的提供访问权限的方法是使用 per-URI permissions,其对接收程序而言是只是暂时拥有该许可权限。类似于这样创建ContentProvider的一种简单的方法是使用FileProvider helper类。
- 使用MediaStore系统。MediaStore系统主要用于音视频及图片的MIME类型。但在Android3.0之后,其也可以用于存储非多媒体类型。
发送多块内容(Send Multiple Pieces of Content)
为了同时分享多种不同类型的内容,需要使用ACTION_SEND_MULTIPLE
与指定到那些数据的URIs列表。MIME类型会根据分享的混合内容而不同。例如,如果分享3张JPEG的图片,那么MIME类型仍然是image/jpeg
。如果是不同图片格式的话,应该是用image/*
来匹配那些可以接收任何图片类型的activity。如果需要分享多种不同类型的数据,可以使用*/*
来表示MIME。像前面描述的那样,这取决于那些接收的程序解析并处理我们的数据。下面是一个例子:
ArrayList<Uri> imageUris = new ArrayList<Uri>();
imageUris.add(imageUri1); // Add your image URIs here
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, "Share images to.."));
当然,请确保指定到数据的URIs能够被接收程序所访问(添加访问权限)。
接收从其他App传送来的数据
就像我们的程序能够分享数据给其他程序一样,其也能方便的接收来自其他程序的数据。需要考虑的是用户与我们的程序如何进行交互,以及我们想要从其他程序接收数据的类型。例如,一个社交网络程序可能会希望能够从其他程序接受文本数据,比如一个有趣的网址链接。Google+的Android客户端会接受文本数据与单张或者多张图片。用户可以简单的从Gallery程序选择一张图片来启动Google+,并利用其发布文本或图片。
更新我们的manifest文件(Update Your Manifest)
Intent filters告诉Android系统一个程序愿意接受的数据类型。类似于上一课,我们可以创建intent filters来表明程序能够接收的action类型。下面是个例子,对三个activit分别指定接受单张图片,文本与多张图片。(Intent filter相关资料,请参考Intents and Intent Filters)
<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并将其传递给startActivity来分享一些东西时,我们的程序会被呈现在一个列表中让用户进行选择。如果用户选择了我们的程序,相应的activity会被调用开启,这个时候就是我们如何处理获取到的数据的问题了。
处理接受到的数据(Handle the Incoming Content)
为了处理从Intent带来的数据,可以通过调用getIntent()方法来获取到Intent对象。拿到这个对象后,我们可以对其中面的数据进行判断,从而决定下一步行为。请记住,如果一个activity可以被其他的程序启动,我们需要在检查intent的时候考虑这种情况(是被其他程序而调用启动的)。
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
}
}
请注意,由于无法知道其他程序发送过来的数据内容是文本还是其他类型的数据,若数据量巨大,则需要大量处理时间,因此我们应避免在UI线程里面去处理那些获取到的数据。
更新UI可以像更新EditText一样简单,也可以是更加复杂一点的操作,例如过滤出感兴趣的图片。这完全取决于我们的应用接下来要做些什么。
添加一个简便的分享功能
Android4.0之后系统中ActionProvider的引入使在ActionBar中添加分享功能变得更为简单。它会handle出现share功能的appearance与behavior。在ShareActionProvider的例子里面,我们只需要提供一个share intent,剩下的就交给ShareActionProvider来做。
更新菜单声明(Update Menu Declarations)
使用ShareActionProvider的第一步,在menu resources对应item中定义android:actionProviderClass
属性。
<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>
这表明了该item的appearance与function需要与ShareActionProvider匹配。此外,你还需要告诉provider想分享的内容。
Set the Share Intent(设置分享的intent)
为了实现ShareActionProvider的功能,我们必须为它提供一个intent。该share intent应该像第一课讲的那样,带有ACTION_SEND
和附加数据(例如EXTRA_TEXT
与 EXTRA_STREAM
)的。使用ShareActionProvider的例子如下:
private ShareActionProvider mShareActionProvider;
... @Override
public 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 intent
private void setShareIntent(Intent shareIntent) {
if (mShareActionProvider != null) {
mShareActionProvider.setShareIntent(shareIntent);
}
}
也许在创建菜单的时候仅仅需要设置一次share intent就满足需求了,或者说我们可能想先设置share intent,然后根据UI的变化来对intent进行更新。例如,当在Gallery里面全图查看照片的时候,share intent会在切换图片时候进行改变。 更多关于ShareActionProvider的内容,请查看Action Bar 。
12) 十分钟学会android--APP通信传递消息之简单数据传输的更多相关文章
- 11) 十分钟学会android--Intent消息处理与传递详解
一个Android app通常都会有多个activities. 每个activity的界面都扮演者用户接口的角色,允许用户执行一些特定任务(例如查看地图或者是开始拍照等).为了让用户能够从一个acti ...
- PHP学习过程_Symfony_(3)_整理_十分钟学会Symfony
这篇文章主要介绍了Symfony学习十分钟入门教程,详细介绍了Symfony的安装配置,项目初始化,建立Bundle,设计实体,添加约束,增删改查等基本操作技巧,需要的朋友可以参考下 (此文章已被多人 ...
- 3) 十分钟学会android--建立第一个APP,建立简单的用户界面
在本小节里,我们将学习如何用 XML 创建一个带有文本输入框和按钮的界面.下一节课将学会使 APP 对按钮做出响应——按钮被按下时,文本框里的内容被发送到另外一个 Activity. Android ...
- 快速入门:十分钟学会Python
初试牛刀 假设你希望学习Python这门语言,却苦于找不到一个简短而全面的入门教程.那么本教程将花费十分钟的时间带你走入Python的大门.本文的内容介于教程(Toturial)和速查手册(Cheat ...
- Python十分钟学会
初试牛刀 假设你希望学习Python这门语言,却苦于找不到一个简短而全面的入门教程.那么本教程将花费十分钟的时间带你走入Python的大门.本文的内容介于教程(Toturial)和速查手册(Cheat ...
- 快速入门:十分钟学会Python(转)
初试牛刀 假设你希望学习Python这门语言,却苦于找不到一个简短而全面的入门教程.那么本教程将花费十分钟的时间带你走入Python的大门.本文的内容介于教程(Toturial)和速查手册(Cheat ...
- 十分钟学会 tmux
tmux 是一款终端复用命令行工具,一般用于 Terminal 的窗口管理.在 macOS 下,使用 iTerm2 能应付绝大多数窗口管理的需求. 如上图所示,iTerm2 能新建多个标签页(快捷键 ...
- 高速入门:十分钟学会Python
初试牛刀 如果你希望学习Python这门语言.却苦于找不到一个简短而全面的新手教程.那么本教程将花费十分钟的时间带你走入Python的大门.本文的内容介于教程(Toturial)和速查手冊(Cheat ...
- 10) 十分钟学会android--app数据保存三种方式
虽然可以在onPause()时保存一些信息以免用户的使用进度被丢失,但大多数Android app仍然是需执行保存数据的动作.大多数较好的apps都需要保存用户的设置信息,而且有一些apps必须维护大 ...
随机推荐
- vue.js的ajax和jsonp请求
首先要声明使用ajax 在 router下边的 Index.js中 import VueResource from 'vue-resource'; Vue.use(VueResource); ajax ...
- 团体程序设计天梯赛-练习集-L1-047. 装睡
L1-047. 装睡 你永远叫不醒一个装睡的人 —— 但是通过分析一个人的呼吸频率和脉搏,你可以发现谁在装睡!医生告诉我们,正常人睡眠时的呼吸频率是每分钟15-20次,脉搏是每分钟50-70次.下面给 ...
- 用doxygen风格注释代码生成文档
目录 用doxygen风格注释代码生成文档 1. 说明 2. 具体操作 2.1 生成头部注释 2.2 安装doxygen 2.3 工程配置 3. 总结 用doxygen风格注释代码生成文档 1. 说明 ...
- 解决@vue/cli 创建项目是安装chromedriver时失败的问题
最近在使用新版vue的命令行工具创建项目时,安装chromedriver老是失败,导致后面的步骤也没有进行.网上搜索了一下,全是使用 工作中常见问题汇总及解决方案 npm install chrome ...
- html_entity_decode()、空格、 乱码问题
普通 ASCII 码空格为 32,但是浏览器会对普通空格进行自动归并,也就是如果你输入10个 0x20 的空格在HTML页面里面,可能会被合并成一个空格. 如果想要一致的呈现多个空格,就要用到 编码标 ...
- setTimeout(fn,0)的作用分析
众所周知,大家对setTimeout的用法肯定都比较熟悉了,但是不是还是会经常忘记使用呢,例如博主阿里面试时就忘了,见阿里前端面试. 今天跟大家讨论一下setTimeout(fn,0)的用法,相信很多 ...
- D - Mayor's posters
D - Mayor's posters POJ - 2528 思路:线段树+离散化. 离散化时注意特殊情况,如果两个数相差大于一,离散时也应该差1.比如 1 3 离散后应该为 1 2. 错因: 1.二 ...
- HDU 3537
翻硬币游戏,纯.. 注意要判重 #include <iostream> #include <cstdio> #include <cstring> #include ...
- UVA - 348Optimal Array Multiplication Sequence(递推)
id=19208">题目:Optimal Array Multiplication Sequence 题目大意:给出N个矩阵相乘.求这些矩阵相乘乘法次数最少的顺序. 解题思路:矩阵相乘 ...
- Android 源代码解析 之 setContentView
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/41894125,本文出自:[张鸿洋的博客] 大家在平时的开发中.对于setCont ...