Android

Java安卓学习总结(十九)

第十五章 隐式intent

有关格式化字符串

之前用过复数字符串,是根据所给参数而确定使用的字符串内容。而格式化字符串的参数就是直接填补了字符串内的格式字符。

定义方法如下:

<string name="crime_report">%1$s!
The crime was discovered on %2$s. %3$s, and %4$s</string>

其中形如%1$s等是占位符。

有关隐式intent

最根本的区别是构造的方法不同。显式intent的两个参数分别是当前Activity和需要创建的Activity类,如

Intent intent=new Intent(getActivity(),CrimePagerActivity.class)

而隐式intent的参数有很多,依次是要执行的操作、待访问数据的位置、操作涉及的数据类型、可选类别。这些参数只有第一个是必需的,但是加上不同的参数可以解决不同的问题。

如只写一个参数的,发送一段文本信息,操作是ACTION_SEND,其不需要访问数据。可以设置自己发送的消息的数据类型。

Intent i=new Intent(Intent.ACTION_SEND);
i.setType("text/plain");

再如写前两个参数的,获取联系人信息,操作是Intent.ACTION_PICK,访问的数据的位置是ContactsContract.Contacts.CONTENT_URI。

final Intent pickContact=new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);

有关activity选择器

有时候使用隐式intent时可能会看不见候选activity列表,原因有两个:一是已经选择了默认的响应应用,二是只有一个activity可以响应该隐式intent。

利用Intent.createChooser()可以创建每次都显示的选择器。

Intent i= ShareCompat.IntentBuilder.from(getActivity()).setType("text/plain").getIntent();
i.putExtra(Intent.EXTRA_TEXT,getCrimeReport());
i.putExtra(Intent.EXTRA_SUBJECT,getString(R.string.crime_report_subject));
i=Intent.createChooser(i,getString(R.string.send_report));
startActivity(i);

有关ContentProvider类

ContentProvider是Android深度定制了一个用于处理联系人信息的API,其将联系人数据库的信息封装起来供其他应用使用。利用ContentResolver来访问ContentProvider的内容。

Cursor c=getActivity().getContentResolver().query(contactUri,queryField,null,null,null);

因为是定制的,所以query的五个参数略有不同,第一个是访问的位置(和表名相关),第二个是要查询的列(投影),第三个是where语句,第四个是where语句的参数(如果有),且全都放在一个string数组里面,第五个是排序方式orderby。

返回的是一个游标,从游标中读取数据的操作照常。

有关应用权限

获取联系人姓名是在ContactsContract.Contacts.CONTENT_URI中查找的,可能是因为里面的信息不多,且很安全,所以联系人应用就可以暂时将权限赋给我们使用。具体实现是联系人应用返回时给intent添加了一个

Intent.FLAG_GRANT_READ_URI_PERMISSION

让应用可以暂时读取联系人数据一次。

有关检查可响应任务的activity

通过操作系统中的PackageManager类进行自检,在onCreateView中进行检查。

PackageManager packageManager=getActivity().getPackageManager();
if (packageManager.resolveActivity(pickContact,PackageManager.MATCH_DEFAULT_ONLY)==null)
{
mSuspectButton.setEnabled(false);
}

还可以添加一个没什么用的操作给intent,来验证是否有作用。

pickContact.addCategory(Intent.CATEGORY_HOME);

有关挑战练习 ShareCompat

ShareCompat.IntentBuilder也是一个Builder,也可以通过流接口来定义。

Intent i= ShareCompat.IntentBuilder.from(getActivity()).setType("text/plain").getIntent();

有关挑战练习 又一个隐式Intent

首先是要先查到电话号码,还是使用getContentResolver(),只不过这一次查询的位置是ContactsContract.CommonDataKinds.Phone.CONTENT_URI。

这一次要权限了,不加权限回崩溃!

java.lang.SecurityException: Permission Denial: opening provider com.android.providers.contacts.ContactsProvider2 from ProcessRecord{22ec7a83 26970:com.example.a73421.criminalintentchallenge/u0a63} (pid=26970, uid=10063) requires android.permission.READ_CONTACTS or android.permission.WRITE_CONTACTS

在AndroidManifest.xml中加入android.permission.READ_CONTACTS这个permission,参考资料,代码如下:

<uses-permission android:name="android.permission.READ_CONTACTS" />

获取电话号码:

String suspectName=mCrime.getSuspect();
String[] queryField=new String[]{ContactsContract.CommonDataKinds.Phone.NUMBER};
Cursor cursor= getActivity().getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
queryField,
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + "=?",
new String[]{suspectName},
null);
if (cursor.getCount()==0)
{
return;
}
cursor.moveToFirst();
int indexPhone=cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
String suspectNumber=cursor.getString(indexPhone);

之后是用所得电话号码构造URI:

Uri number=Uri.parse("tel:"+suspectNumber);

启动activity:

Intent pickPhone=new Intent(Intent.ACTION_DIAL,number);
startActivity(pickPhone);

2 thoughts on “Java安卓学习总结(十九)

  1. 第一个挑战练习忘记加信息内容了,使用:
    Intent i = ShareCompat.IntentBuilder.from(getActivity()).setType(“text/plain”).setText(getCrimeReport()).getIntent();

发表评论