運(yùn)行有問題或需要源碼請(qǐng)點(diǎn)贊關(guān)注收藏后評(píng)論區(qū)留言
一、利用ContentResolver讀寫聯(lián)系人
在實(shí)際開發(fā)中,普通App很少會(huì)開放數(shù)據(jù)接口給其他應(yīng)用訪問。內(nèi)容組件能夠派上用場(chǎng)的情況往往是App想要訪問系統(tǒng)應(yīng)用的通訊數(shù)據(jù),比如查看聯(lián)系人,短信,通話記錄等等,以及對(duì)這些通訊數(shù)據(jù)及逆行增刪改查。 首先要給AndroidMaifest.xml中添加響應(yīng)的權(quán)限配置?
<!-- 存儲(chǔ)卡讀寫 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAG" />
<!-- 聯(lián)系人/通訊錄。包括讀聯(lián)系人、寫聯(lián)系人 -->
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<!-- 短信。包括發(fā)送短信、接收短信、讀短信 -->
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<!-- 通話記錄。包括讀通話記錄、寫通話記錄 -->
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.WRITE_CALL_LOG" />
<!-- 安裝應(yīng)用請(qǐng)求,Android8.0需要 -->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
下面是往手機(jī)通訊錄添加聯(lián)系人信息的例子 效果如下
分成三個(gè)步驟 先查出聯(lián)系人的基本信息,然后查詢聯(lián)系人號(hào)碼,再查詢聯(lián)系人郵箱
代碼
?ContactAddActivity類
package com.example.chapter07;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.EditText;
import androidx.appcompat.app.AppCompatActivity;
import com.example.chapter07.bean.Contact;
import com.example.chapter07.util.CommunicationUtil;
import com.example.chapter07.util.ToastUtil;
@SuppressLint("DefaultLocale")
public class ContactAddActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "ContactAddActivity";
private EditText et_contact_name;
private EditText et_contact_phone;
private EditText et_contact_email;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_contact_add);
et_contact_name = findViewById(R.id.et_contact_name);
et_contact_phone = findViewById(R.id.et_contact_phone);
et_contact_email = findViewById(R.id.et_contact_email);
findViewById(R.id.btn_add_contact).setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.btn_add_contact) {
Contact contact = new Contact(); // 創(chuàng)建一個(gè)聯(lián)系人對(duì)象
contact.name = et_contact_name.getText().toString().trim();
contact.phone = et_contact_phone.getText().toString().trim();
contact.email = et_contact_email.getText().toString().trim();
// 方式一,使用ContentResolver多次寫入,每次一個(gè)字段
CommunicationUtil.addContacts(getContentResolver(), contact);
// 方式二,使用ContentProviderOperation一次寫入,每次多個(gè)字段
//CommunicationUtil.addFullContacts(getContentResolver(), contact);
ToastUtil.show(this, "成功添加聯(lián)系人信息");
}
}
}
ContactReadActivity類
package com.example.chapter07;
import androidx.appcompat.app.AppCompatActivity;
import android.graphics.Color;
import android.os.Bundle;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.example.chapter07.bean.Contact;
import com.example.chapter07.util.CommunicationUtil;
import com.example.chapter07.util.ToastUtil;
import com.example.chapter07.util.Utils;
import java.util.List;
public class ContactReadActivity extends AppCompatActivity {
private TextView tv_desc;
private LinearLayout ll_list; // 聯(lián)系人列表的線性布局
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_contact_read);
tv_desc = findViewById(R.id.tv_desc);
ll_list = findViewById(R.id.ll_list);
showContactInfo(); // 顯示所有的聯(lián)系人信息
}
// 顯示所有的聯(lián)系人信息
private void showContactInfo() {
try {
// 讀取所有的聯(lián)系人
List<Contact> contactList = CommunicationUtil.readAllContacts(getContentResolver());
String contactCount = String.format("當(dāng)前共找到%d位聯(lián)系人", contactList.size());
tv_desc.setText(contactCount);
for (Contact contact : contactList){
String contactDesc = String.format("姓名為%s,號(hào)碼為%s",contact.name, contact.phone);
TextView tv_contact = new TextView(this); // 創(chuàng)建一個(gè)文本視圖
tv_contact.setText(contactDesc);
tv_contact.setTextColor(Color.BLACK);
tv_contact.setTextSize(17);
int pad = Utils.dip2px(this, 5);
tv_contact.setPadding(pad, pad, pad, pad); // 設(shè)置文本視圖的內(nèi)部間距
ll_list.addView(tv_contact); // 把文本視圖添加至聯(lián)系人列表的線性布局
}
} catch (Exception e) {
e.printStackTrace();
ToastUtil.show(this, "請(qǐng)檢查是否開啟了通訊錄權(quán)限");
}
}
}
activity_contact_addXML
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="5dp" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="40dp" >
<TextView
android:id="@+id/tv_contact_name"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:text="聯(lián)系人姓名:"
android:textColor="@color/black"
android:textSize="17sp" />
<EditText
android:id="@+id/et_contact_name"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="3dp"
android:layout_marginTop="3dp"
android:layout_toRightOf="@+id/tv_contact_name"
android:background="@drawable/editext_selector"
android:gravity="left|center"
android:hint="請(qǐng)輸入聯(lián)系人姓名"
android:inputType="text"
android:maxLength="12"
android:textColor="@color/black"
android:textSize="17sp" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="40dp" >
<TextView
android:id="@+id/tv_contact_phone"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:text="聯(lián)系人號(hào)碼:"
android:textColor="@color/black"
android:textSize="17sp" />
<EditText
android:id="@+id/et_contact_phone"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="3dp"
android:layout_marginTop="3dp"
android:layout_toRightOf="@+id/tv_contact_phone"
android:background="@drawable/editext_selector"
android:gravity="left|center"
android:hint="請(qǐng)輸入聯(lián)系人手機(jī)號(hào)碼"
android:inputType="number"
android:maxLength="11"
android:textColor="@color/black"
android:textSize="17sp" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="40dp" >
<TextView
android:id="@+id/tv_contact_email"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:text="聯(lián)系人郵箱:"
android:textColor="@color/black"
android:textSize="17sp" />
<EditText
android:id="@+id/et_contact_email"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="3dp"
android:layout_marginTop="3dp"
android:layout_toRightOf="@+id/tv_contact_email"
android:background="@drawable/editext_selector"
android:gravity="left|center"
android:hint="請(qǐng)輸入聯(lián)系人郵箱"
android:inputType="textEmailAddress"
android:textColor="@color/black"
android:textSize="17sp" />
</RelativeLayout>
<Button
android:id="@+id/btn_add_contact"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="添加聯(lián)系人"
android:textColor="@color/black"
android:textSize="17sp" />
</LinearLayout>
activity_contact_readXML
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/tv_desc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5dp"
android:textColor="@color/black"
android:textSize="17sp" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/ll_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
</ScrollView>
</LinearLayout>
二、利用ContentObserver監(jiān)聽短信
ContentRslover獲取數(shù)據(jù)采用的是主動(dòng)查詢方式,有查詢才有數(shù)據(jù)否則美喲。為了省事,這時(shí)用到了ContentObserver內(nèi)容觀察器,事先給目標(biāo)內(nèi)容注冊(cè)一個(gè)觀察器,目標(biāo)內(nèi)容的數(shù)據(jù)一旦發(fā)生變化,就馬上觸發(fā)觀察器的監(jiān)聽事件,從而執(zhí)行開發(fā)者預(yù)先定義的代碼
內(nèi)容觀察器的用法與內(nèi)容提供器類似,下面是交互方法說明
registerContentObserver 內(nèi)容解析器要注冊(cè)內(nèi)容觀察器
unregisterContentObserver 注銷
notifyChange 通知內(nèi)容觀察器發(fā)生了數(shù)據(jù)變化
?文章來源:http://www.zghlxwxcb.cn/news/detail-491209.html
?java類代碼
MonitorSmsActivity
package com.example.chapter07;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.telephony.SmsManager;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
@SuppressLint("DefaultLocale")
public class MonitorSmsActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "MonitorSmsActivity";
private static TextView tv_check_flow;
private static String mCheckResult;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_monitor_sms);
tv_check_flow = findViewById(R.id.tv_check_flow);
tv_check_flow.setOnClickListener(this);
findViewById(R.id.btn_check_flow).setOnClickListener(this);
initSmsObserver();
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.btn_check_flow) {
//查詢數(shù)據(jù)流量,移動(dòng)號(hào)碼的查詢方式為發(fā)送短信內(nèi)容“18”給“10086”
//電信和聯(lián)通號(hào)碼的短信查詢方式請(qǐng)咨詢當(dāng)?shù)剡\(yùn)營商客服熱線
//跳到系統(tǒng)的短信發(fā)送頁面,由用戶手工發(fā)短信
//sendSmsManual("10086", "18");
//無需用戶操作,自動(dòng)發(fā)送短信
sendSmsAuto("10086", "18");
} else if (v.getId() == R.id.tv_check_flow) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("收到流量校準(zhǔn)短信");
builder.setMessage(mCheckResult);
builder.setPositiveButton("確定", null);
builder.create().show();
}
}
// 跳到系統(tǒng)的短信發(fā)送頁面,由用戶手工編輯與發(fā)送短信
public void sendSmsManual(String phoneNumber, String message) {
Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.parse("smsto:" + phoneNumber));
intent.putExtra("sms_body", message);
startActivity(intent);
}
// 短信發(fā)送事件
private String SENT_SMS_ACTION = "com.example.storage.SENT_SMS_ACTION";
// 短信接收事件
private String DELIVERED_SMS_ACTION = "com.example.storage.DELIVERED_SMS_ACTION";
// 無需用戶操作,由App自動(dòng)發(fā)送短信
public void sendSmsAuto(String phoneNumber, String message) {
// 以下指定短信發(fā)送事件的詳細(xì)信息
Intent sentIntent = new Intent(SENT_SMS_ACTION);
sentIntent.putExtra("phone", phoneNumber);
sentIntent.putExtra("message", message);
PendingIntent sentPI = PendingIntent.getBroadcast(this, 0,
sentIntent, PendingIntent.FLAG_UPDATE_CURRENT);
// 以下指定短信接收事件的詳細(xì)信息
Intent deliverIntent = new Intent(DELIVERED_SMS_ACTION);
deliverIntent.putExtra("phone", phoneNumber);
deliverIntent.putExtra("message", message);
PendingIntent deliverPI = PendingIntent.getBroadcast(this, 1,
deliverIntent, PendingIntent.FLAG_UPDATE_CURRENT);
// 獲取默認(rèn)的短信管理器
SmsManager smsManager = SmsManager.getDefault();
// 開始發(fā)送短信內(nèi)容。要確保打開發(fā)送短信的完全權(quán)限,不是那種還需提示的不完整權(quán)限
smsManager.sendTextMessage(phoneNumber, null, message, sentPI, deliverPI);
}
private Handler mHandler = new Handler(); // 聲明一個(gè)處理器對(duì)象
private SmsGetObserver mObserver; // 聲明一個(gè)短信獲取的觀察器對(duì)象
private static Uri mSmsUri; // 聲明一個(gè)系統(tǒng)短信提供器的Uri對(duì)象
private static String[] mSmsColumn; // 聲明一個(gè)短信記錄的字段數(shù)組
// 初始化短信觀察器
private void initSmsObserver() {
//mSmsUri = Uri.parse("content://sms/inbox");
//Android5.0之后似乎無法單獨(dú)觀察某個(gè)信箱,只能監(jiān)控整個(gè)短信
mSmsUri = Uri.parse("content://sms"); // 短信數(shù)據(jù)的提供器路徑
mSmsColumn = new String[]{"address", "body", "date"}; // 短信記錄的字段數(shù)組
// 創(chuàng)建一個(gè)短信觀察器對(duì)象
mObserver = new SmsGetObserver(this, mHandler);
// 給指定Uri注冊(cè)內(nèi)容觀察器,一旦發(fā)生數(shù)據(jù)變化,就觸發(fā)觀察器的onChange方法
getContentResolver().registerContentObserver(mSmsUri, true, mObserver);
}
// 在頁面銷毀時(shí)觸發(fā)
protected void onDestroy() {
super.onDestroy();
getContentResolver().unregisterContentObserver(mObserver); // 注銷內(nèi)容觀察器
}
// 定義一個(gè)短信獲取的觀察器
private static class SmsGetObserver extends ContentObserver {
private Context mContext; // 聲明一個(gè)上下文對(duì)象
public SmsGetObserver(Context context, Handler handler) {
super(handler);
mContext = context;
}
// 觀察到短信的內(nèi)容提供器發(fā)生變化時(shí)觸發(fā)
public void onChange(boolean selfChange) {
String sender = "", content = "";
// 構(gòu)建一個(gè)查詢短信的條件語句,移動(dòng)號(hào)碼要查找10086發(fā)來的短信
String selection = String.format("address='10086' and date>%d",
System.currentTimeMillis() - 1000 * 60 * 1); // 查找最近一分鐘的短信
// 通過內(nèi)容解析器獲取符合條件的結(jié)果集游標(biāo)
Cursor cursor = mContext.getContentResolver().query(
mSmsUri, mSmsColumn, selection, null, " date desc");
// 循環(huán)取出游標(biāo)所指向的所有短信記錄
while (cursor.moveToNext()) {
sender = cursor.getString(0); // 短信的發(fā)送號(hào)碼
content = cursor.getString(1); // 短信內(nèi)容
Log.d(TAG, "sender="+sender+", content="+content);
break;
}
cursor.close(); // 關(guān)閉數(shù)據(jù)庫游標(biāo)
mCheckResult = String.format("發(fā)送號(hào)碼:%s\n短信內(nèi)容:%s", sender, content);
// 依次解析流量校準(zhǔn)短信里面的各項(xiàng)流量數(shù)值,并拼接流量校準(zhǔn)的結(jié)果字符串
String flow = String.format("流量校準(zhǔn)結(jié)果如下:總流量為:%s;已使用:%s" +
";剩余流量:%s", findFlow(content, "總流量為"),
findFlow(content, "已使用"), findFlow(content, "剩余"));
if (tv_check_flow != null) { // 離開該頁面后就不再顯示流量信息
tv_check_flow.setText(flow); // 在文本視圖顯示流量校準(zhǔn)結(jié)果
}
super.onChange(selfChange);
}
}
// 解析流量短信里面的流量數(shù)值
private static String findFlow(String sms, String begin) {
String flow = findString(sms, begin, "GB");
String temp = flow.replace("GB", "").replace(".", "");
if (!temp.matches("\\d+")) {
flow = findString(sms, begin, "MB");
}
return flow;
}
// 截取指定頭尾之間的字符串
private static String findString(String content, String begin, String end) {
int begin_pos = content.indexOf(begin);
if (begin_pos < 0) {
return "未獲取";
}
String sub_sms = content.substring(begin_pos);
int end_pos = sub_sms.indexOf(end);
if (end_pos < 0) {
return "未獲取";
}
if (end.equals(",")) {
return sub_sms.substring(begin.length(), end_pos);
} else {
return sub_sms.substring(begin.length(), end_pos + end.length());
}
}
}
XML文件代碼
activity_monitor_smsXML
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="@+id/btn_check_flow"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="發(fā)送校準(zhǔn)短信"
android:textColor="@color/black"
android:textSize="17sp" />
<TextView
android:id="@+id/tv_check_flow"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="5dp"
android:textColor="@color/black"
android:textSize="17sp" />
</LinearLayout>
創(chuàng)作不易 覺得有幫助請(qǐng)點(diǎn)贊關(guān)注收藏~~~~文章來源地址http://www.zghlxwxcb.cn/news/detail-491209.html
到了這里,關(guān)于Android Studio開發(fā)之使用內(nèi)容組件Content獲取通訊信息講解及實(shí)戰(zhàn)(附源碼 包括添加手機(jī)聯(lián)系人和發(fā)短信)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!