本课程教你如何产生一个在app和设备间共享数据的app。
Sharing Simple Data
Sharing Files
Sharing Files with NFC
Sharing Simple Data
Android应用最伟大之处之一就是不同应用间的通信和整合的能力。如果一个功能在其他的app里已经实现了,而这些功能并不是你的app的“主业”,为什么自己再重新实现这些功能呢?
本文讲述几种方式用来在不同的应用之间使用Intent API和ActionProvider
对象发送和接收简单数据。
Lessons
Sending Simple Data to Other Apps
学习如何通过Intent从你的application向其他的application发送文本和二进制数据
Receiving Simple Data from Other Apps
学习如何在你的application里获取从intent里传入的文本和二进制数据
学习如何在你的Action Bar里添加“share” action 条目
Sending Simple Data to Other Apps
当你构建一个intent时,你必须指定你想要该intent触发的action。Android定义了许多action,例如ACTION_SEND,该action表明intent从一个activity向另一个activity传递数据,甚至在不同进程间传递数据。为了向另一个activity发送数据,你需要做的是指定数据和类型,系统会识别能处理该intent的所有activity,然后将这些activity展示给用户(当不止一个activity时)或者立即的开启一个activity(如果仅仅有一个能处理的activity时)。相似地,你能在你的manifest文件里定义数据类型以表明你的activity能接收和处理来自其他application的哪些intent。
在不同application之间使用intent来发送和接收数据是最常见和通用的内容共享方式。Intent能让用户很快很容易的共享信息。
注:在ActionBar里添加一个共享action item的最好的方式是使用ShareActionProvider,该类在API 14及以上版本中才可用。
Send Text Content
ACTION_SEND action最直接和最通用的方式是从一个activity到另一个activity发送文本内容。例如,内建浏览器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_SEND和MIME类型为text/plain的过滤器,Android系统将运行和启动该应用。如果不止一个app匹配,系统展示多选对话框(“chooser”)来让用户选择一个app。
然而,如果你调用Intent.createChooser(),传递给你的intent对象,该调用将返回你的intent的版本,总是展示该chooser。这样有一些优点:
- 即使用户先前已选择了一个默认的ACTION来处理该intent,chooser仍然将会展示给用户。
- 如果没有匹配的app,Android展示系统消息。
- 你能为chooser对话框指定一个title。
下面是更新了的代码:
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)));
结果对话框如下图一所示:
Figure 1. Screenshot of ACTION_SEND
intent chooser on a handset.
还有一些其他的标准的extras: EXTRA_EMAIL
, EXTRA_CC
, EXTRA_BCC
, EXTRA_SUBJECT,
如果接收application不使用它们,系统简单地忽略它们。
注:一些email应用,例如Gmail,需要一个字符串数组String[]
给extras,例如 EXTRA_EMAIL
和 EXTRA_CC
, 可以使用putExtra(String, String[])
加这些到你的intent。
Send Binary Content
共享二进制数据也是使用ACTION_SEND action,需要设置合适的MIME类型,和添加URI到extra的数据里,该URI名叫EXTRA_STREAM。
这通常用于共享图片数据,但也能共享任何类型的二进制内容。
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类型,但是这将仅仅匹配能处理一般数据流的activity。
- 响应app需要访问URi指向数据的权限。推荐如下方式实现:
- 在你自己的
ContentProvider
存储数据 ,确保其他的app有相应的权限访问你的provider。更好的提供的访问机制是使用per-URI permissions ,该权限是临时的,仅仅保证对响应app的访问。一个容易的方式是使用FileProvider帮助类产生一个ContentProvider。 - 使用系统
MediaStore.MediaStore
其主要目的是用于视频、音频和图片MIME类型,然而,从Android3.0(API11)开始,该类也用于存储非媒体类型(seeMediaStore.Files
for more info)的数据。文件。文件能通过scanFile()
插入MediaStore。在after which acontent://
styleUri
suitable for sharing is passed to the providedonScanCompleted()
callback。注意:一旦加入到系统MediaStore,设备上的任何app都能访问存储在MediaStore里的数据。
Send Multiple Pieces of Content
为了共享多部分内容,使用ACTION_SEND_MULTIPLE
action配合一组指向内容的URIs。MIME类型依据你共享的内容而定。例如,如果你共享3个JPEG图片,MIME类型仍然是”image/jpeg“.例如如果是各种格式的图片,类型应该是”image/*",如果你正共享的是各种类型的数据,你应该使用“*/*” 像先前描述的,这决定了哪些app解析和处理你的数据。下面是一个例子:
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访问。
Receiving Simple Data from Other Apps
你的app能发送数据给其他的应用,当然,你的app也能接收来自其他app的数据。想想用户怎么和你的app交互,以及你想要从其他的app接收什么类型的数据。例如,一个社交app很可能需要接收文本内容,如来自于其他app的一个感兴趣的web URL数据。Google+ Android application既可以接收文本也可以接收图片数据。
Update Your Manifest
意图过滤器通知系统某个app的组件将接受什么意图。类似于Sending Simple Data to Other Apps这节讲的如何使用action ACTION_SEND
构造Intent,为了能接受intent,你能使用该action产生意图过滤器。你在你的manifest里使用<intent-filter>
元素定义意图过滤器。如果你的app想要处理文本类型、一种或者多种图片格式的数据,你的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>注:更多的关于意图过滤器和意图的介绍请看见Intents and Intent Filters
当另一个app通过构造一个intent试图共享如上manfest定义的数据,然后传递该intent给startActivity()
时,你的app将在intent chooser里作为一个选项被列出。如果用户选择你的app,响应的activity(对应上面例子中的.ui.MyActivity)将被调起。然后由你确定在你的代码和UI里如何处理传递过来的数据。
Handle the Incoming Content
为了处理一个intent投递过来的数据,首页调用getIntent()
得到该Intent对象。一旦你有了该对象,你能检查它里面的内容以决定接下来如何做。记住,如果activity能被系统的其他部分(例如launcher)调起,那么当你检查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 } }
注意:需要特别关注对传入的数据进行check。你不能知道一些其他的app将送你什么数据。例如,传递过来的intent里可能设置了错误的MIME类型,或者发送过来的image可能极其的大。还要记住,在单独的线程而不是主线程(UI线程)处理二进制数据。
有些UI更新可能很简单,像填充EditText一样,也有像更新图片这样的复杂的UI更新,收到数据后怎么处理和更新UI因app而异。
Adding an Easy Share Action
通过使用Android4.0(API 14)里介绍的ActionProvider能在ActionBar里容易的实现一个有效的、用户友好的共享action。ActionProvider,一旦附件到actionbar里的某天menu item,既能处理该item的展示也能该item的行为。以ShareActionProvider为例,你提供一个共享intent,剩下的事由它来做。
注:ShareActionProvider在API 14或者更高的版本才有效。
Update Menu Declarations
为了能使用ShareActionProvider,在你的menu resource 文件的相应<item>定义android: action ProviderClass属性:
<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>这表示ShareActionProvider处理item的展现和功能。然而,你需要告诉provider你想要share什么。
Figure 1. TheShareActionProvider
in the Gallery app.
Set the Share Intent
为了ShareActionProvider有效,你必须提供share intent给它。这共享intent应该和Sending Simple Data to Other Apps节里描述的相似,action为ACTION_SEND,通过extras设置EXTRA_TEXT和EXTRA_STREAM额外的数据。为了指派共享intent,首先当在Activity或者Fragment里渲染你的menu资源时找到相应的MenuItem。接下来,调用MenuItem.getActionProvider()
方法检索ShareActionProvider实例。使用 setShareIntent()
更新相关联的action item的共享意图。如下是例子:
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); } }
你可能只需要在menu产生期间设置share action一次,或者你可能当UI改变时设置或者更新它。例如,当你在Gallery app里全屏浏览照片时,share action当你在照片间滑动时改变。
更多关于ShareActionProvider
对象的讨论,参见 Action Bar guide。
相关推荐
Data Modeling Made Simple with Embarcadero ER/Studio Data Architect: Adapting to Agile Data Modeling in a Big Data World Build a working knowledge of data modeling concepts and best practices, along ...
After that, he uses each chapter to introduce one piece of the big data stack—sharing how to source the software and how to install it. You learn by simple example, step by step and chapter by ...
Chapter 3, Data Structures in Game Development, introduces all the simple and complex data structures in C++ and shows how to use them effectively in games. Chapter 4, Algorithms for Game Development...
然后,你可以创建各种类型的窗口,如`win = env.scatter(data, win='scatter plot')`。 2. 更新数据:使用`env.line`或`env.scatter`等函数的`update`方法,可以实时更新图表的数据。 3. 参数配置:每个可视化窗口...
So you can build rich web, mobile and desktop client applications while sharing a lot of the same code. This will reduce development time, cost and eliminate the learning curve of having to learn ...
So you can build rich web, mobile and desktop client applications while sharing a lot of the same code. This will reduce development time, cost and eliminate the learning curve of having to learn ...
So you can build rich web, mobile and desktop client applications while sharing a lot of the same code. This will reduce development time, cost and eliminate the learning curve of having to learn ...
.This model makes it easy to extend the application’s data model to meet all users’ individual needs, and restoring a user’s data from backups in a failure is a relatively simple thing[9].But ...
标签"sds"在IT领域中可能代表“Simple Data Sharing”或者“Secure Digital Storage”,但这仍不足以构建一个详细的知识点解释。而压缩包子文件的文件名"setunajtrj_33lc.com"看起来像一个随机字符串,通常在没有上...
It's useful for beginners as it offers a simple interface to write and test Python code. 3. **Resources for Learning Python**: - **Books**: Books like "Learning Python" by Mark Lutz and David ...
Sharing the same data between scenes Using mlab Using the core Mayavi API Changing the interaction with a scene Accelerating a Mayavi script Miscellaneous Citing Mayavi Getting help Tests for ...
simple-datamining-online 用 Spring Boot + Vue 实现的一个简单的在线数据挖掘,可上传查看数据、选择模型、查看性能度量结果。[2020/04] covid-19-realtime-info-visualization 一个展示 COVID-19 全球实时趋势的...
Along the way, you’ll build example projects, including a simple Objective-C application, a custom view, a simple video player application, and an app that displays calendar events for the user. ...
Professional Themes and Simple Styling Get 12+ themes including Metro, Office and Expression for the entire studio. Plus, with built-in ClearStyle technology, you can easily change control colors ...
Professional Themes and Simple Styling Get 12+ themes including Metro, Office and Expression for the entire studio. Plus, with built-in ClearStyle technology, you can easily change control colors ...
Professional Themes and Simple Styling Get 12+ themes including Metro, Office and Expression for the entire studio. Plus, with built-in ClearStyle technology, you can easily change control colors ...
§ Professional Themes and Simple Styling Get 12+ themes including Metro, Office and Expression for the entire studio. Plus, with built-in ClearStyle technology, you can easily change control ...
§ Professional Themes and Simple Styling Get 12+ themes including Metro, Office and Expression for the entire studio. Plus, with built-in ClearStyle technology, you can easily change control ...