在上一篇学习安卓开发[3] - 使用RecyclerView显示列表中了解了在进行列表展示时RecyclerView的使用,本次记录的是在应用中如何通过隐式Intent调用其它应用的功能,比如发短信、打电话、拍照等
- 隐式Intent
- 短信
- 判断是否存在相关APP
- 相机
- FileProvider
- Bitmap
- 功能声明
隐式Intent
Intent对象用来向操作系统说明需要处理的任务。使用显式Intent时,要指定操作系统需要启动的activity,但使用隐式intent,只需告知操作系统想要进行的操作,系统就会启动能完成该操作的activity,如果有多个符合条件的activity,会提供用户一个应用列表供选择
Android是如何通过隐式intent找到并启动合适应用的呢?原因在于配置文件中的itent过滤器设置,比如我们也想开发一款短信应用,那么可以在AndroidMainfest的activity声明中这样设置:
<activity android:name=".CrimeListActivity">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
隐式Intent的组成部分有
1)要执行的操作,通常以Intent类中的常量来表示,比如访问URL可以使用Intent.ACTION_VIEW,发送邮件使用Intent.ACTION_SEND
2)待访问数据的位置,这可能是设备以外的资源,如某个网页的URL,某个文件的URI
3)操作涉及的数据类型,如text/html, audio/mpeg3等
4)可选类别,用来描述对activity的使用方式
短信
那么要启动短信的隐式intent的方法为:
mReportButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent i = new Intent(Intent.ACTION_SEND);
i.setType("text/plain");
i.putExtra(Intent.EXTRA_TEXT, getCrimeReport());
i.putExtra(Intent.EXTRA_SUBJECT,
getString(R.string.crime_report_suspect));
i = Intent.createChooser(i, getString(R.string.send_report));
startActivity(i);
}
});
首先指定发送消息的操作名为ACTION_SEND,然后消息内容为文本,所以设置数据类型为text/plain,要发送的文本通过Extra的形式提供
判断是否存在相关APP
使用隐式intent时,如果系统没有安装对应的软件,应用就会奔溃,所以有必要在使用隐式intent时,检查一下能够找到对应的软件,如果没找到,就避免再去发生相关的隐式intent
final Intent pickContact = new Intent(Intent.ACTION_SEND);
PackageManager packageManager = getActivity().getPackageManager();
if (packageManager.resolveActivity(pickContact, PackageManager.MATCH_DEFAULT_ONLY) == null) {
mReportButton.setEnabled(false);
}
通过PackageManager可以搜索需要的activity的信息,flag标志MATCH_DEFAULT_ONLY限定只搜索带CATEGORY_DEFAULT的activity,如果没有找到,就禁用发短信按钮。
相机
如果所开发的APP有拍照功能,就可以使用系统相机了。拍摄的照片要保存在设备文件系统,但这就涉及到私有存储空间的问题。出于安全考虑,无法使用公共外部存储转存,那么如果想共享文件给其他应用,或者接收其他应用的文件(如相机拍摄的照片),可以使用ContentProvider把要共享的文件临时暴露出来。对于接受相机拍摄的照片这样的场景,系统提供的现成的FileProvider类。
FileProvider
要使用FileProvider类,需要在AndroidMainfest中添加声明。
首先添加files.xml文件
<paths>
<files-path
name="crime_photos"
path="."/>
</paths>
这个描述性文件把私有存储空间的根路径映射为crime_photos,这个名字仅供FileProvider自己使用。
然后添加FileProvider声明:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.example.zhixin.crimeintent.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/files" />
</provider>
通过这段声明,提供了一个文件保存地,相机拍摄的照片就可以放在这里了。exported="false"表示除了应用自己和给予授权的应用,其它的不允许使用这个FileProvider,grantUriPermissions="true"表示允许其他应用向指定文职的URI写入文件。
接下来就可以实现拍照功能了
mPhotoButton = (ImageButton) v.findViewById(R.id.crime_camera);
final Intent captureImage = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
boolean canTakePhoto = mPhotoFile != null &&
captureImage.resolveActiv