Android Studio开发:使用内容组件Content获取通讯信息和附源码 包括添加手机联系人和发短信
运行有问题或需要源码请点赞关注收藏后评论区留言
一、利用ContentResolver读写联系人
在实际开发中,普通App很少会开放数据接口给其他应用访问。内容组件能够派上用场的情况往往是App想要访问系统应用的通讯数据,比如查看联系人,短信,通话记录等等,以及对这些通讯数据及逆行增删改查。 首先要给AndroidMaifest.xml中添加响应的权限配置
-
<!-- 存储卡读写 -->
-
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAG" />
-
<!-- 联系人/通讯录。包括读联系人、写联系人 -->
-
<uses-permission android:name="android.permission.READ_CONTACTS" />
-
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
-
<!-- 短信。包括发送短信、接收短信、读短信 -->
-
<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" />
-
<!-- 安装应用请求,Android8.0需要 -->
-
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
下面是往手机通讯录添加联系人信息的例子 效果如下
分成三个步骤 先查出联系人的基本信息,然后查询联系人号码,再查询联系人邮箱
代码
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;
-
-
-
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;
-
-
-
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);
-
}
-
-
-
public void onClick(View v) {
-
if (v.getId() == R.id.btn_add_contact) {
-
Contact contact = new Contact(); // 创建一个联系人对象
-
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多次写入,每次一个字段
-
CommunicationUtil.addContacts(getContentResolver(), contact);
-
// 方式二,使用ContentProviderOperation一次写入,每次多个字段
-
//CommunicationUtil.addFullContacts(getContentResolver(), contact);
-
ToastUtil.show(this, "成功添加联系人信息");
-
}
-
}
-
-
}
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; // 联系人列表的线性布局
-
-
@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(); // 显示所有的联系人信息
-
}
-
-
// 显示所有的联系人信息
-
private void showContactInfo() {
-
try {
-
// 读取所有的联系人
-
List<Contact> contactList = CommunicationUtil.readAllContacts(getContentResolver());
-
String contactCount = String.format("当前共找到%d位联系人", contactList.size());
-
tv_desc.setText(contactCount);
-
for (Contact contact : contactList){
-
String contactDesc = String.format("姓名为%s,号码为%s",contact.name, contact.phone);
-
TextView tv_contact = new TextView(this); // 创建一个文本视图
-
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); // 设置文本视图的内部间距
-
ll_list.addView(tv_contact); // 把文本视图添加至联系人列表的线性布局
-
}
-
} catch (Exception e) {
-
e.printStackTrace();
-
ToastUtil.show(this, "请检查是否开启了通讯录权限");
-
}
-
}
-
-
}
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="联系人姓名:"
-
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="请输入联系人姓名"
-
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="联系人号码:"
-
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="请输入联系人手机号码"
-
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="联系人邮箱:"
-
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="请输入联系人邮箱"
-
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="添加联系人"
-
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监听短信
ContentRslover获取数据采用的是主动查询方式,有查询才有数据否则美哟。为了省事,这时用到了ContentObserver内容观察器,事先给目标内容注册一个观察器,目标内容的数据一旦发生变化,就马上触发观察器的监听事件,从而执行开发者预先定义的代码
内容观察器的用法与内容提供器类似,下面是交互方法说明
registerContentObserver 内容解析器要注册内容观察器
unregisterContentObserver 注销
notifyChange 通知内容观察器发生了数据变化
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) {
-
//查询数据流量,移动号码的查询方式为发送短信内容“18”给“10086”
-
//电信和联通号码的短信查询方式请咨询当地运营商客服热线
-
//跳到系统的短信发送页面,由用户手工发短信
-
//sendSmsManual("10086", "18");
-
//无需用户操作,自动发送短信
-
sendSmsAuto("10086", "18");
-
} else if (v.getId() == R.id.tv_check_flow) {
-
AlertDialog.Builder builder = new AlertDialog.Builder(this);
-
builder.setTitle("收到流量校准短信");
-
builder.setMessage(mCheckResult);
-
builder.setPositiveButton("确定", null);
-
builder.create().show();
-
}
-
}
-
-
// 跳到系统的短信发送页面,由用户手工编辑与发送短信
-
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);
-
}
-
-
// 短信发送事件
-
private String SENT_SMS_ACTION = "com.example.storage.SENT_SMS_ACTION";
-
// 短信接收事件
-
private String DELIVERED_SMS_ACTION = "com.example.storage.DELIVERED_SMS_ACTION";
-
-
// 无需用户操作,由App自动发送短信
-
public void sendSmsAuto(String phoneNumber, String message) {
-
// 以下指定短信发送事件的详细信息
-
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);
-
// 以下指定短信接收事件的详细信息
-
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);
-
// 获取默认的短信管理器
-
SmsManager smsManager = SmsManager.getDefault();
-
// 开始发送短信内容。要确保打开发送短信的完全权限,不是那种还需提示的不完整权限
-
smsManager.sendTextMessage(phoneNumber, null, message, sentPI, deliverPI);
-
}
-
-
private Handler mHandler = new Handler(); // 声明一个处理器对象
-
private SmsGetObserver mObserver; // 声明一个短信获取的观察器对象
-
private static Uri mSmsUri; // 声明一个系统短信提供器的Uri对象
-
private static String[] mSmsColumn; // 声明一个短信记录的字段数组
-
-
// 初始化短信观察器
-
private void initSmsObserver() {
-
//mSmsUri = Uri.parse("content://sms/inbox");
-
//Android5.0之后似乎无法单独观察某个信箱,只能监控整个短信
-
mSmsUri = Uri.parse("content://sms"); // 短信数据的提供器路径
-
mSmsColumn = new String[]{"address", "body", "date"}; // 短信记录的字段数组
-
// 创建一个短信观察器对象
-
mObserver = new SmsGetObserver(this, mHandler);
-
// 给指定Uri注册内容观察器,一旦发生数据变化,就触发观察器的onChange方法
-
getContentResolver().registerContentObserver(mSmsUri, true, mObserver);
-
}
-
-
// 在页面销毁时触发
-
protected void onDestroy() {
-
super.onDestroy();
-
getContentResolver().unregisterContentObserver(mObserver); // 注销内容观察器
-
}
-
-
// 定义一个短信获取的观察器
-
private static class SmsGetObserver extends ContentObserver {
-
private Context mContext; // 声明一个上下文对象
-
public SmsGetObserver(Context context, Handler handler) {
-
super(handler);
-
mContext = context;
-
}
-
-
// 观察到短信的内容提供器发生变化时触发
-
public void onChange(boolean selfChange) {
-
String sender = "", content = "";
-
// 构建一个查询短信的条件语句,移动号码要查找10086发来的短信
-
String selection = String.format("address='10086' and date>%d",
-
System.currentTimeMillis() - 1000 * 60 * 1); // 查找最近一分钟的短信
-
// 通过内容解析器获取符合条件的结果集游标
-
Cursor cursor = mContext.getContentResolver().query(
-
mSmsUri, mSmsColumn, selection, null, " date desc");
-
// 循环取出游标所指向的所有短信记录
-
while (cursor.moveToNext()) {
-
sender = cursor.getString(0); // 短信的发送号码
-
content = cursor.getString(1); // 短信内容
-
Log.d(TAG, "sender=" sender ", content=" content);
-
break;
-
}
-
cursor.close(); // 关闭数据库游标
-
mCheckResult = String.format("发送号码:%s\n短信内容:%s", sender, content);
-
// 依次解析流量校准短信里面的各项流量数值,并拼接流量校准的结果字符串
-
String flow = String.format("流量校准结果如下:总流量为:%s;已使用:%s"
-
";剩余流量:%s", findFlow(content, "总流量为"),
-
findFlow(content, "已使用"), findFlow(content, "剩余"));
-
if (tv_check_flow != null) { // 离开该页面后就不再显示流量信息
-
tv_check_flow.setText(flow); // 在文本视图显示流量校准结果
-
}
-
super.onChange(selfChange);
-
}
-
}
-
-
// 解析流量短信里面的流量数值
-
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="发送校准短信"
-
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>
创作不易 觉得有帮助请点赞关注收藏~~~~
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgabjic
系列文章
更多
同类精品
更多
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
photoshop蒙版画笔没反应怎么办
PHP中文网 06-24