Android学习笔记第二篇--分享数据
来源:互联网 发布:energia驱动mac 编辑:程序博客网 时间:2024/05/19 19:40
第二篇、Android分享操作
- 第二篇Android分享操作
- 分享简单数据
- 向其他app发送检单数据
- 注意
- 接收外App传的数据
- ActionBar 分享功能
- 向其他app发送检单数据
- 分享文件
- 建立文件分享
- 分享文件
- 请求分享文件
- 获取文件信息
- NFC分享文件
- 发送文件
- 接收文件
- 分享简单数据
- 第二篇Android分享操作
1. 分享简单数据
向其他app发送检单数据
- Intent发送数据必须有actions,其他对应action的activity响应事件。通过Intent实现分享功能,而ActionBar可使用
ShareActionProvider
来快速实现分享功能。如下是使用Intent.createChooser实现分享功能的demo:
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,"Share to My friends");
如上,可以显示出多个选择框,列出可响应的分享社交App
分享二进制文件,需要指定特定的MIME类型,在EXTRA_STREAM里面放置数据的URI,如下分享一个图片的代码示例:
Intent shareIntent = new Intent();shareIntent.setAction(Intent.ACTION_SEND);shareIntent.putExtra(Intent.EXTRA_STREAM, uriToImage);//重要,指定URIshareIntent.setType("image/jpeg");//指定MIME类型startActivity(Intent.createChooser(shareIntent,"Share a picture");
注意:
- 可以使用
*/*
指定MIME类型,但是仅有能够处理一般数据类型的Activity才能匹配到。因为普通的Activity不能详尽所有MIME类型。 - 响应的Activity需要有访问URI的权限。两种方案,一是ContentProvider(per-URI permissions);二是MediaStore(亦可存储非媒体文件,Android3.0以后。)
- 可以使用
多块内容,Multiple。同时分享不同的内容,可使用
ACTION_SEND_MULTIPLE
及数据URIs。而MIME需根据内容类型调整,可使用*符号。如image/jpeg
、image/*
、*/*
。如下:ArrayList<Uri> imageUris = new ArrayList<Uri>();imageUris.add(imageUri1); // Add your image URIs hereimageUris.add(imageUri2);//接收Activity需要有权限哦Intent shareIntent = new Intent();shareIntent.setAction(Intent.ACTION_SEND_MULTIPLE);//复合类型的MIME,ActionshareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, imageUris);//传递数组shareIntent.setType("image/*");//复合MIMEstartActivity(Intent.createChooser(shareIntent, "Share images to.."));
- Intent发送数据必须有actions,其他对应action的activity响应事件。通过Intent实现分享功能,而ActionBar可使用
接收外App传的数据
Activity 在manifest文件 配置,通过Intent Filters来过滤需要处理的数据Action,如下Activity接收单张图片、文本、多张图片时,不同的intent-filer配置:
<activity android:name=".ui.MyActivity" ><!-- 注释,单类型图片的Action过滤,其Action名称不同--> <intent-filter> <action android:name="android.intent.action.SEND" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="image/*" /> </intent-filter><!-- 注释,文本类型的Action过滤--> <intent-filter> <action android:name="android.intent.action.SEND" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="text/plain" /> </intent-filter><!-- 注释,多种类型图片的Action过滤--> <intent-filter> <action android:name="android.intent.action.SEND_MULTIPLE" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="image/*" /> </intent-filter></activity>
处理接收数据,通过getIntent()来获取extra数据,需要知道传递来的具体类型,结构,做相应处理。有时需要访问权限。若是数据量太大,应考虑避免UI线程的阻塞。
ActionBar 分享功能
Android4.0引入ActionProvider,其子类ShareActionProvider用于分享数据。ActionBar步骤:
在Menu的xml中定义
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" /> <!--如上则声明该item需要share action provider来匹配内容 --> ...</menu>
需要提供intent给ShareActionProvider,示例如下:
private ShareActionProvider mShareActionProvider;...@Overridepublic boolean onCreateOptionsMenu(Menu menu) { //菜单布局文件 getMenuInflater().inflate(R.menu.share_menu, menu); //加载配有ShareActionProvider属性的item MenuItem item = menu.findItem(R.id.menu_item_share); // 实例化ShareActionProvider mShareActionProvider = (ShareActionProvider) item.getActionProvider(); // 返回true表示显示菜单项 return true;}//回调更新intent,用于分享private void setShareIntent(Intent shareIntent) { if (mShareActionProvider != null) { mShareActionProvider.setShareIntent(shareIntent); }}
2. 分享文件
分享文件最为安全的方式是使用content URI,Android中FileProvider有getUriForFile()创建文件content URI。少量数据可以用intent传递。
建立文件分享
要安全地提供文件分享,需要配置Content URI。
- 指定FileProvider,在manifest中定义一个provider的entry,声明Authority等。如下示例:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapp"> <application ...> <!-- authorities、meta-data的配置 --> <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" /> <!-- meta-data指定文件共享目录,在res/xml下 --> </provider> ... </application></manifest>
共享文件的目录,res/xml中配置,filepaths.xml,如下示例:
<paths> <!-- 每一个共享目录都是一个item,这里表示共享了files/ 目录下的子目录,files-path这个标签适用于共享应用内部储存,files/下的目录。name=“myimages” 做为content uri中的路径标记--><files-path path="images/" name="myimages"/></paths>
<paths>
有多个子标签,各自代表不同共享目录,<files-path>
表示内部files/下目录,<external-path>
外部存储目录,<cache-path>
缓存目录。参考FileProvider。注意xml里写的目录,无法在代码中追加和修改- Content URI包含
<provider>
指定Authority(“com.example.myapp.fileprovider”); - 路径“myimages/”;
- 文件名称。
例如获取上述files/images/下的aa.jpg文件,File Provider提供的URI:
content://com.example.myapp.fileprovider/myimages/aa.jpg
- Content URI包含
分享文件
- 上面创建了共享提供者,此处需要共享请求者。
File requestFile = new File(mImageFilename[position]); 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); }
需要注意的是,能获取content uri的文件,都是在manifest文件中,provider下meta-data配置了
<paths>
标签内的文件,否则会抛IllegalArgumentException设置文件授权:
if(fileUri != null){//Grant temporary read permission to the content URI,授权具有临时性,一次性。mResultIntent.addFlags(Intent.FLAG_GRANT_URI_PERMISSION);}
Caution:调用setFlags()授权文件是唯一的安全方法,应避免Context.grantUriPermission(),它需要Context.revokeUriPermission()才能撤销授权。
请求分享文件
一般文件共享分为共享者与请求者,或者服务器与客户端。服务器需要配置共享清单,客户端需要请求共享,并指定请求类型。
发送文件请求,客户端startActivityForResult(),通过intent的Action,附带data,MIME去请求服务器的共享数据。服务器来显示对应的共享清单。
java
mRequestFileIntent = new Intent(Intent.ACTION_PICK);//Action
mRequestFileIntent.setType("image/jpg");//MIME类型
...
在onActivityResult()中处理服务器返回的URI,注:刚开始只是处理URI,而无任何实际的文件操作和访问,不会影响服务器文件安全。
“`java
@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对象类操作文件。
FileDescriptor fd = mInputPFD.getFileDescriptor();
…
}
“`
获取文件信息
上一步获取了服务器提供的content uri和file descriptor对象,但并不能操作文件,还需要指导文件信息,如大小、类型。
获取文件MIME,通过ContentResolver.getType()获取uri对应的文件类型。
java
Uri returnUri = returnIntent.getData();
String mimeType = getContentResolver().getType(returnUri);
获取文件大小,FileProvider的query()方法返回Cuisor对象,包含对应uri的文件名称大小信息。DISPLAY_NAME,SIZE。
“`java
Uri returnUri = returnIntent.getData();
Cursor returnCursor =
getContentResolver().query(returnUri, null, null, null, null);
/*- Get the column indexes of the data in the Cursor,
- move to the first row in the Cursor, get the data,
- and display it.
*/
int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
returnCursor.moveToFirst();
“`
3. NFC分享文件
Android Beam文件传输可在设备间传输大文件,API调用方便。
发送文件
使用NFC发送文件,需要设备支持NFC且app生命NFC和外部存储权限。使用URI给Android Beam来传出文件。需要满足以下要求:
Android版本api>=16。
传送的文件必须在外部存储上。
文件必须全局可读,可以用File.setReadable(true,false)来设置。
必须提供文件的File URI。Android Beam无法处理FileProvider.getUriForFile生成的URI。
<uses-permission android:name="android.permission.NFC" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORANGE" />
其中外部存储权限在4.2.2之前不是必须声明的。
<uses-feature android:name="android.hardware.nfc" android:required="true" /><!-- 如此设置,声明该应用必须要硬件nfc支持才可以运行。若是required为false,则需要检测设备是否支持Android Beam-->
- 测试Android Beam,PackageManager.hasSystemFeature()和参数FEATURE_NFC来测是nfc。Build.VERSION.SDK_INT系统版本号。
boolean hasNFC= PackageManager.hasSystemFeature(PackageManager.FEATURE_NFC);//判断NFC可用与否。Build.VERSION.SDK_INT<Build.VERSION_CODE.JELLY_BEAN_MR1//版本低。//可用的话,实例化NfcAdapterNfcAdapter adapter = NfcAdatper.getDefaultAdapter(this);
- 通过回调函数获取数据
private Uri[] mFileUris = new Uri[10];//提供给AndroidBeam的URIsprivate class FileUriCallback implements NfcAdapter.CreateBeamUrisCallback{public FileUriCallback(){}@overridepublic Uri[] createBeamUris(NfcEvent event){ return mFileUris;}}
通过setBeamPushUrisCallback()将回调提供给Android Beam文件传输。
mFileUriCallback = new FileUriCallback();mNfcAdapter.setBeamPushUrisCallback(mFileUriCallback,this);
- 指定要发送的文件,给文件File URI,然后加入URIs数组。记住需要有文件的读取权限。
接收文件
Android Beam文件传输时,是将文件copy到某特殊目录,然后由Media Scanner扫描文件,在MediaStore Provider中为媒体文件添加条目记录。
响应传输来的请求,并显示数据。
Android Beam传输数据到接收设备后,会发送Intent通知,包含ACTION_VIEW,MIME,URI。用户确认通知后,intent被发至系统,寻求其他响应。
Activity在manifest配置
<intent-filter>
加入<action android:name="android.intent.action.VIEW"/>
、<category android:name="android.intent.category.CATEGORY_DEFAULT"
、<data android:nimeType="mime-type"
分别标识不同的Action,category和数据type。Action_view的action也不一定就是Android beam发送的。*
<activity android:name="com.example.android.nfctransfer.ViewActivity" android:label="Android Beam Viewer"> <intent-filter> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT"/> ... </intent-filter></activity>
读取文件需要权限
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
上面所说,ACTION_VIEW不一定就是AndroidBeam发送的intent,所以需要检查Scheme和Authority。调用Uri.getScheme。
mIntent = getIntent();//判断Action,机器Scheme和AuthorityUri beamUri = mIntent.getData();beamUri.getScheme();//判断是否是“file”,或者“content”
File URI中获取目录
public String handleFileUri(Uri beamUri) { // Get the path part of the URI String fileName = beamUri.getPath(); // Create a File object for this filename File copiedFile = new File(fileName); // Get a string containing the file's parent directory return copiedFile.getParent(); }
Content URI中获取目录,MediaS tore会含有文件的uri信息。Uri.getAuthority()获取authority,返回值MediaStore.AUTHORITY或者其他。
为其他类型时候,不一定可以获取目录;
文章为阅读Android官方培训教程而摘记,仅供小白个人学习笔记
- Android学习笔记第二篇--分享数据
- Android学习笔记(十九)分享简单数据
- Android学习笔记(十九)分享简单数据
- Android学习笔记: 第二天
- 第二篇学习笔记
- 分享mysql数据学习笔记(转)
- Android微信分享学习笔记
- Android学习的第二周笔记
- Geekband002第二周笔记分享
- Hibernate 学习笔记第二篇
- erlang学习笔记第二篇
- Dom4j学习笔记--第二篇
- latex学习笔记第二篇
- 第二十八篇: 学习笔记
- Android Voip 第二篇笔记
- Android数据存储学习笔记
- 汇编语言学习笔记 第二节:数据传送指令
- python网络数据采集学习笔记:第二章
- 自定义behavior
- android用socket与PC用C#的socket通讯使PC关机
- container_of分析
- Stack Overflow 2016最新架构探秘
- Linux Shell编程-字符截取和处理命令
- Android学习笔记第二篇--分享数据
- 开源框架
- 域名得到泛域名
- 北京的小伙伴,本周五阿里聚安全约你来玩
- 开源框架
- 使用go tool pprof分析内存泄漏、CPU消耗
- div设置height的必要性
- 关于"Slidepage传值问题"的解决方法
- 一道笔试题