添加嫌疑人信息至模型层
为Crime添加成员变量
Crime.java
public class Crime {
//...
private String mSuspect;
private String mPhone;
//...
}
添加数据库字段
CrimeDbSchema.java
public class CrimeDbSchema {
//数据表
public static final class CrimeTable {
//表名
public static final String NAME = "crimes";
//表的字段
public static final class Cols {
//...
public static final String SUSPECT = "suspect";
public static final String PHONE = "phone";
}
}
}
CrimeBaseHelper.java
@Override
public void onCreate(SQLiteDatabase db) {
//执行创建数据表的SQL语句
db.execSQL("create table " + CrimeTable.NAME +
"(" +
" _id integer primary key autoincrement, " +
CrimeTable.Cols.UUID + ", " +
CrimeTable.Cols.TITLE + ", " +
CrimeTable.Cols.DATE + ", " +
CrimeTable.Cols.SOLVED + ", " +
CrimeTable.Cols.SUSPECT + ", " +
CrimeTable.Cols.PHONE +
")"
);
}
CrimeLab.java
//根据crime创建ContentValues并返回
private static ContentValues getContentValues(Crime crime) {
ContentValues values = new ContentValues();
//...
values.put(CrimeTable.Cols.SUSPECT, crime.getSuspect());
values.put(CrimeTable.Cols.PHONE, crime.getPhone());
return values;
}
添加读取信息语句
CrimeCursorWrapper.java
public Crime getCrime() {
//...
String suspect = getString(getColumnIndex(CrimeTable.Cols.SUSPECT));
String phone = getString(getColumnIndex(CrimeTable.Cols.PHONE));
Crime crime = new Crime(UUID.fromString(uuidString));
//...
crime.setSuspect(suspect);
crime.setPhone(phone);
return crime;
}
使用格式化字符串
添加字符串资源
strings.xml
<resources>
...
<string name="crime_report">
[%1$s] 创建于 %2$s (%3$s),%4$s。
</string>
<string name="crime_report_solved">已经被解决了</string>
<string name="crime_report_unsolved">还没有被解决</string>
<string name="crime_report_no_suspect">没有嫌疑人</string>
<string name="crime_report_suspect">嫌疑人是「%s」</string>
<string name="crime_report_subject">陋习记录报告</string>
<string name="send_report">发送报告到:</string>
</resources>
新增getCrimeReport()方法
CrimeFragment.java
private String getCrimeReport() {
String solvedString = null;
if (mCrime.isSolved()) solvedString = getString(R.string.crime_report_solved);
else solvedString = getString(R.string.crime_report_unsolved);
String dateFormat = "MM月dd日 EEE kk:mm";
String dateString = DateFormat.format(dateFormat, mCrime.getDate()).toString();
String suspect = mCrime.getSuspect();
if (suspect == null) suspect = getString(R.string.crime_report_no_suspect);
else suspect = getString(R.string.crime_report_suspect, suspect);
String report = getString(R.string.crime_report, mCrime.getTitle(), dateString, solvedString, suspect);
Log.d(TAG, "陋习报告:" + report);
return report;
}
使用隐式intent
- 使用显式intent,我们需要指定要操作系统启动哪个activity。
- 使用隐式intent,只需告诉操作系统我们想要做什么,操作系统就会去启动能够胜任工作任务的activity。如果找到多个符合的activity,用户会看到一个可选应用列表。
隐式intent的组成
-
要执行的操作
- 访问某个URL,使用Intent.ACTION_VIEW
- 发送邮件,使用Intent.ACTION_SEND
-
要访问数据的位置
- 某个网页的URL
- 指向某个文件的URI
- 指向ContentProvider中某条记录的某个content URI
-
操作涉及的数据类型
- text/html
- audio/mpeg3
-
可选类别(何时、何地或者如何使用某个activity)
发送消息
CrimeFragment.onCreateView(LayoutInflater, ViewGroup, Bundle)
mReportButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG, "发送陋习报告...");
//隐式intent要执行的操作[发送邮件]
Intent intent = new Intent(Intent.ACTION_SEND);
//隐式intent操作的数据类型[不指向任何数据、不包含任何类别]
intent.setType("text/plain");
//附加消息内容
intent.putExtra(Intent.EXTRA_TEXT, getCrimeReport());
//附加消息主题
intent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.crime_report_subject));
//创建每次都显示activity选择器
intent = Intent.createChooser(intent, getString(R.string.send_report));
startActivity(intent);
}
});
获取联系人信息
发送隐式intent
CrimeFragment.onCreateView(LayoutInflater, ViewGroup, Bundle)
//隐式intent要执行的操作为[显示联系人],要访问的数据位置为[ContactsContract.Contacts.CONTENT_URI]
final Intent pickContact = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
mSuspectButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG, "选择嫌疑人...");
startActivityForResult(pickContact, REQUEST_CONTACT);
}
});
获取联系人姓名
CrimeFragment.onActivityResult(int, int, Intent)
if (requestCode == REQUEST_CONTACT) {
//数据定位符,指向用户所选联系人
Uri contactUri = data.getData();
//要查询的字段
String[] queryFields = new String[] { ContactsContract.Contacts.DISPLAY_NAME, ContactsContract.Contacts._ID };
//返回查询结果(只有一条)
Cursor cursor = getActivity().getContentResolver().query(contactUri, queryFields, null, null, null);
String suspectId = null;
try {
if (cursor.getCount() == 0) return;
cursor.moveToFirst();
String suspect = cursor.getString(0);
suspectId = cursor.getString(1);
mCrime.setSuspect(suspect);
mSuspectButton.setText("已选择嫌疑人「" + suspect + "」");
Log.d(TAG, "已选择嫌疑人「" + suspect + "」");
}
finally {
cursor.close();
}
}
检查可响应任务的activity
如果设备没有联系人应用,就禁用选择嫌疑人按钮:
//检查是否存在联系人应用,没有就禁用按钮
//PackageManager.MATCH_DEFAULT_ONLY表示只搜索带CATEGORY_DEFAULT标志的activity
Intent pickContact = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
PackageManager packageManager = getActivity().getPackageManager();
if (packageManager.resolveActivity(pickContact, PackageManager.MATCH_DEFAULT_ONLY) == null) mSuspectButton.setEnabled(false);
为测试上述代码,添加类别给intent,使任何联系人应用都不和此intent匹配:
pickContact.addCategory(Intent.CATEGORY_HOME);
实现拨打联系人电话
添加权限使用声明
AndroidManifest.xml
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.criminalintent">
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<application
...
</application>
</manifest>
申请权限
CrimeFragment.onCreateView(LayoutInflater, ViewGroup, Bundle)
private static final int REQUEST_PERMISSION_CONTACT = 3;
if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(getActivity(), new String[] { Manifest.permission.READ_CONTACTS }, REQUEST_PERMISSION_CONTACT);
}
可在托管activity中重写授权回调方法
CrimePagerActivity.java
private static final int REQUEST_PERMISSION_CONTACT = 3;
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode) {
case REQUEST_PERMISSION_CONTACT:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
Toast.makeText(this, "已获取读取联系人权限。", Toast.LENGTH_SHORT).show();
else
Toast.makeText(this, "获取权限失败。", Toast.LENGTH_SHORT).show();
return;
default:
}
}
获取联系人电话
为获取联系人电话,首先查询联系人的ContactsContract.Contacts._ID,在根据此ID查询ContactsContract.CommonDataKinds.Phone表,得到指定ID联系人的电话ContactsContract.CommonDataKinds.Phone.NUMBER。
CrimeFragment.onActivityResult(int, int, Intent)
if (requestCode == REQUEST_CONTACT) {
//数据定位符,指向用户所选联系人
Uri contactUri = data.getData();
//要查询的字段
String[] queryFields = new String[] { ContactsContract.Contacts.DISPLAY_NAME, ContactsContract.Contacts._ID };
//返回查询结果(只有一条)
Cursor cursor = getActivity().getContentResolver().query(contactUri, queryFields, null, null, null);
String suspectId = null;
try {
if (cursor.getCount() == 0) return;
cursor.moveToFirst();
String suspect = cursor.getString(0);
suspectId = cursor.getString(1);
mCrime.setSuspect(suspect);
mSuspectButton.setText("已选择嫌疑人「" + suspect + "」");
Log.d(TAG, "已选择嫌疑人「" + suspect + "」");
}
finally {
cursor.close();
}
queryFields = new String[] { ContactsContract.CommonDataKinds.Phone.NUMBER };
String whereClause = ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?";
String[] whereArgs = new String[] { suspectId };
cursor = getActivity().getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, queryFields, whereClause, whereArgs, null);
try {
if (cursor.getCount() == 0) return;
cursor.moveToFirst();
String phone = cursor.getString(0);
mCrime.setPhone(phone);
mDialSuspectButton.setText("拨打嫌疑人电话「" + phone + "」");
mDialSuspectButton.setEnabled(true);
Log.d(TAG, "嫌疑人电话「" + phone + "」");
}
finally {
cursor.close();
}
}
拨打电话
创建隐式intent,实现拨打电话操作:
CrimeFragment.onCreateView(LayoutInflater, ViewGroup, Bundle)
mDialSuspectButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG, "拨打嫌疑人电话「" + mCrime.getPhone() + "」...");
Intent intent = new Intent(Intent.ACTION_DIAL);
Uri number = Uri.parse("tel:" + mCrime.getPhone());
intent.setData(number);
startActivity(intent);
}
});