• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

Android Studio开发:使用内容组件Content获取通讯信息和附源码 包括添加手机联系人和发短信

武飞扬头像
showswoller
帮助1

运行有问题或需要源码请点赞关注收藏后评论区留言

一、利用ContentResolver读写联系人

在实际开发中,普通App很少会开放数据接口给其他应用访问。内容组件能够派上用场的情况往往是App想要访问系统应用的通讯数据,比如查看联系人,短信,通话记录等等,以及对这些通讯数据及逆行增删改查。 首先要给AndroidMaifest.xml中添加响应的权限配置 

  1.  
    <!-- 存储卡读写 -->
  2.  
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  3.  
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAG" />
  4.  
    <!-- 联系人/通讯录。包括读联系人、写联系人 -->
  5.  
    <uses-permission android:name="android.permission.READ_CONTACTS" />
  6.  
    <uses-permission android:name="android.permission.WRITE_CONTACTS" />
  7.  
    <!-- 短信。包括发送短信、接收短信、读短信 -->
  8.  
    <uses-permission android:name="android.permission.SEND_SMS" />
  9.  
    <uses-permission android:name="android.permission.RECEIVE_SMS" />
  10.  
    <uses-permission android:name="android.permission.READ_SMS" />
  11.  
    <!-- 通话记录。包括读通话记录、写通话记录 -->
  12.  
    <uses-permission android:name="android.permission.READ_CALL_LOG" />
  13.  
    <uses-permission android:name="android.permission.WRITE_CALL_LOG" />
  14.  
    <!-- 安装应用请求,Android8.0需要 -->
  15.  
    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
学新通

下面是往手机通讯录添加联系人信息的例子 效果如下

分成三个步骤 先查出联系人的基本信息,然后查询联系人号码,再查询联系人邮箱

学新通

代码

 ContactAddActivity类

  1.  
    package com.example.chapter07;
  2.  
     
  3.  
    import android.annotation.SuppressLint;
  4.  
    import android.os.Bundle;
  5.  
    import android.view.View;
  6.  
    import android.view.View.OnClickListener;
  7.  
    import android.widget.EditText;
  8.  
     
  9.  
    import androidx.appcompat.app.AppCompatActivity;
  10.  
     
  11.  
    import com.example.chapter07.bean.Contact;
  12.  
    import com.example.chapter07.util.CommunicationUtil;
  13.  
    import com.example.chapter07.util.ToastUtil;
  14.  
     
  15.  
    @SuppressLint("DefaultLocale")
  16.  
    public class ContactAddActivity extends AppCompatActivity implements View.OnClickListener {
  17.  
    private static final String TAG = "ContactAddActivity";
  18.  
    private EditText et_contact_name;
  19.  
    private EditText et_contact_phone;
  20.  
    private EditText et_contact_email;
  21.  
     
  22.  
    @Override
  23.  
    protected void onCreate(Bundle savedInstanceState) {
  24.  
    super.onCreate(savedInstanceState);
  25.  
    setContentView(R.layout.activity_contact_add);
  26.  
    et_contact_name = findViewById(R.id.et_contact_name);
  27.  
    et_contact_phone = findViewById(R.id.et_contact_phone);
  28.  
    et_contact_email = findViewById(R.id.et_contact_email);
  29.  
    findViewById(R.id.btn_add_contact).setOnClickListener(this);
  30.  
    }
  31.  
     
  32.  
    @Override
  33.  
    public void onClick(View v) {
  34.  
    if (v.getId() == R.id.btn_add_contact) {
  35.  
    Contact contact = new Contact(); // 创建一个联系人对象
  36.  
    contact.name = et_contact_name.getText().toString().trim();
  37.  
    contact.phone = et_contact_phone.getText().toString().trim();
  38.  
    contact.email = et_contact_email.getText().toString().trim();
  39.  
    // 方式一,使用ContentResolver多次写入,每次一个字段
  40.  
    CommunicationUtil.addContacts(getContentResolver(), contact);
  41.  
    // 方式二,使用ContentProviderOperation一次写入,每次多个字段
  42.  
    //CommunicationUtil.addFullContacts(getContentResolver(), contact);
  43.  
    ToastUtil.show(this, "成功添加联系人信息");
  44.  
    }
  45.  
    }
  46.  
     
  47.  
    }
学新通

ContactReadActivity类

  1.  
    package com.example.chapter07;
  2.  
     
  3.  
    import androidx.appcompat.app.AppCompatActivity;
  4.  
     
  5.  
    import android.graphics.Color;
  6.  
    import android.os.Bundle;
  7.  
    import android.widget.LinearLayout;
  8.  
    import android.widget.TextView;
  9.  
     
  10.  
    import com.example.chapter07.bean.Contact;
  11.  
    import com.example.chapter07.util.CommunicationUtil;
  12.  
    import com.example.chapter07.util.ToastUtil;
  13.  
    import com.example.chapter07.util.Utils;
  14.  
     
  15.  
    import java.util.List;
  16.  
     
  17.  
    public class ContactReadActivity extends AppCompatActivity {
  18.  
    private TextView tv_desc;
  19.  
    private LinearLayout ll_list; // 联系人列表的线性布局
  20.  
     
  21.  
    @Override
  22.  
    protected void onCreate(Bundle savedInstanceState) {
  23.  
    super.onCreate(savedInstanceState);
  24.  
    setContentView(R.layout.activity_contact_read);
  25.  
    tv_desc = findViewById(R.id.tv_desc);
  26.  
    ll_list = findViewById(R.id.ll_list);
  27.  
    showContactInfo(); // 显示所有的联系人信息
  28.  
    }
  29.  
     
  30.  
    // 显示所有的联系人信息
  31.  
    private void showContactInfo() {
  32.  
    try {
  33.  
    // 读取所有的联系人
  34.  
    List<Contact> contactList = CommunicationUtil.readAllContacts(getContentResolver());
  35.  
    String contactCount = String.format("当前共找到%d位联系人", contactList.size());
  36.  
    tv_desc.setText(contactCount);
  37.  
    for (Contact contact : contactList){
  38.  
    String contactDesc = String.format("姓名为%s,号码为%s",contact.name, contact.phone);
  39.  
    TextView tv_contact = new TextView(this); // 创建一个文本视图
  40.  
    tv_contact.setText(contactDesc);
  41.  
    tv_contact.setTextColor(Color.BLACK);
  42.  
    tv_contact.setTextSize(17);
  43.  
    int pad = Utils.dip2px(this, 5);
  44.  
    tv_contact.setPadding(pad, pad, pad, pad); // 设置文本视图的内部间距
  45.  
    ll_list.addView(tv_contact); // 把文本视图添加至联系人列表的线性布局
  46.  
    }
  47.  
    } catch (Exception e) {
  48.  
    e.printStackTrace();
  49.  
    ToastUtil.show(this, "请检查是否开启了通讯录权限");
  50.  
    }
  51.  
    }
  52.  
     
  53.  
    }
学新通

activity_contact_addXML

  1.  
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2.  
    android:layout_width="match_parent"
  3.  
    android:layout_height="match_parent"
  4.  
    android:orientation="vertical"
  5.  
    android:padding="5dp" >
  6.  
     
  7.  
    <RelativeLayout
  8.  
    android:layout_width="match_parent"
  9.  
    android:layout_height="40dp" >
  10.  
     
  11.  
    <TextView
  12.  
    android:id="@ id/tv_contact_name"
  13.  
    android:layout_width="wrap_content"
  14.  
    android:layout_height="match_parent"
  15.  
    android:gravity="center"
  16.  
    android:text="联系人姓名:"
  17.  
    android:textColor="@color/black"
  18.  
    android:textSize="17sp" />
  19.  
     
  20.  
    <EditText
  21.  
    android:id="@ id/et_contact_name"
  22.  
    android:layout_width="match_parent"
  23.  
    android:layout_height="match_parent"
  24.  
    android:layout_marginBottom="3dp"
  25.  
    android:layout_marginTop="3dp"
  26.  
    android:layout_toRightOf="@ id/tv_contact_name"
  27.  
    android:background="@drawable/editext_selector"
  28.  
    android:gravity="left|center"
  29.  
    android:hint="请输入联系人姓名"
  30.  
    android:inputType="text"
  31.  
    android:maxLength="12"
  32.  
    android:textColor="@color/black"
  33.  
    android:textSize="17sp" />
  34.  
    </RelativeLayout>
  35.  
     
  36.  
    <RelativeLayout
  37.  
    android:layout_width="match_parent"
  38.  
    android:layout_height="40dp" >
  39.  
     
  40.  
    <TextView
  41.  
    android:id="@ id/tv_contact_phone"
  42.  
    android:layout_width="wrap_content"
  43.  
    android:layout_height="match_parent"
  44.  
    android:gravity="center"
  45.  
    android:text="联系人号码:"
  46.  
    android:textColor="@color/black"
  47.  
    android:textSize="17sp" />
  48.  
     
  49.  
    <EditText
  50.  
    android:id="@ id/et_contact_phone"
  51.  
    android:layout_width="match_parent"
  52.  
    android:layout_height="match_parent"
  53.  
    android:layout_marginBottom="3dp"
  54.  
    android:layout_marginTop="3dp"
  55.  
    android:layout_toRightOf="@ id/tv_contact_phone"
  56.  
    android:background="@drawable/editext_selector"
  57.  
    android:gravity="left|center"
  58.  
    android:hint="请输入联系人手机号码"
  59.  
    android:inputType="number"
  60.  
    android:maxLength="11"
  61.  
    android:textColor="@color/black"
  62.  
    android:textSize="17sp" />
  63.  
    </RelativeLayout>
  64.  
     
  65.  
    <RelativeLayout
  66.  
    android:layout_width="match_parent"
  67.  
    android:layout_height="40dp" >
  68.  
     
  69.  
    <TextView
  70.  
    android:id="@ id/tv_contact_email"
  71.  
    android:layout_width="wrap_content"
  72.  
    android:layout_height="match_parent"
  73.  
    android:gravity="center"
  74.  
    android:text="联系人邮箱:"
  75.  
    android:textColor="@color/black"
  76.  
    android:textSize="17sp" />
  77.  
     
  78.  
    <EditText
  79.  
    android:id="@ id/et_contact_email"
  80.  
    android:layout_width="match_parent"
  81.  
    android:layout_height="match_parent"
  82.  
    android:layout_marginBottom="3dp"
  83.  
    android:layout_marginTop="3dp"
  84.  
    android:layout_toRightOf="@ id/tv_contact_email"
  85.  
    android:background="@drawable/editext_selector"
  86.  
    android:gravity="left|center"
  87.  
    android:hint="请输入联系人邮箱"
  88.  
    android:inputType="textEmailAddress"
  89.  
    android:textColor="@color/black"
  90.  
    android:textSize="17sp" />
  91.  
    </RelativeLayout>
  92.  
     
  93.  
    <Button
  94.  
    android:id="@ id/btn_add_contact"
  95.  
    android:layout_width="match_parent"
  96.  
    android:layout_height="wrap_content"
  97.  
    android:gravity="center"
  98.  
    android:text="添加联系人"
  99.  
    android:textColor="@color/black"
  100.  
    android:textSize="17sp" />
  101.  
     
  102.  
    </LinearLayout>
学新通

activity_contact_readXML

  1.  
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2.  
    android:layout_width="match_parent"
  3.  
    android:layout_height="match_parent"
  4.  
    android:orientation="vertical" >
  5.  
     
  6.  
    <TextView
  7.  
    android:id="@ id/tv_desc"
  8.  
    android:layout_width="match_parent"
  9.  
    android:layout_height="wrap_content"
  10.  
    android:padding="5dp"
  11.  
    android:textColor="@color/black"
  12.  
    android:textSize="17sp" />
  13.  
     
  14.  
    <ScrollView
  15.  
    android:layout_width="match_parent"
  16.  
    android:layout_height="wrap_content">
  17.  
     
  18.  
    <LinearLayout
  19.  
    android:id="@ id/ll_list"
  20.  
    android:layout_width="match_parent"
  21.  
    android:layout_height="wrap_content"
  22.  
    android:orientation="vertical" />
  23.  
     
  24.  
    </ScrollView>
  25.  
     
  26.  
    </LinearLayout>
学新通

二、利用ContentObserver监听短信

ContentRslover获取数据采用的是主动查询方式,有查询才有数据否则美哟。为了省事,这时用到了ContentObserver内容观察器,事先给目标内容注册一个观察器,目标内容的数据一旦发生变化,就马上触发观察器的监听事件,从而执行开发者预先定义的代码

内容观察器的用法与内容提供器类似,下面是交互方法说明

registerContentObserver 内容解析器要注册内容观察器

unregisterContentObserver 注销

notifyChange 通知内容观察器发生了数据变化

 学新通

 java类代码

MonitorSmsActivity

  1.  
    package com.example.chapter07;
  2.  
     
  3.  
    import android.annotation.SuppressLint;
  4.  
    import android.app.AlertDialog;
  5.  
    import android.app.PendingIntent;
  6.  
    import android.content.Context;
  7.  
    import android.content.Intent;
  8.  
    import android.database.ContentObserver;
  9.  
    import android.database.Cursor;
  10.  
    import android.net.Uri;
  11.  
    import android.os.Bundle;
  12.  
    import android.os.Handler;
  13.  
    import android.telephony.SmsManager;
  14.  
    import android.util.Log;
  15.  
    import android.view.View;
  16.  
    import android.widget.TextView;
  17.  
     
  18.  
    import androidx.appcompat.app.AppCompatActivity;
  19.  
     
  20.  
    @SuppressLint("DefaultLocale")
  21.  
    public class MonitorSmsActivity extends AppCompatActivity implements View.OnClickListener {
  22.  
    private static final String TAG = "MonitorSmsActivity";
  23.  
    private static TextView tv_check_flow;
  24.  
    private static String mCheckResult;
  25.  
     
  26.  
    @Override
  27.  
    protected void onCreate(Bundle savedInstanceState) {
  28.  
    super.onCreate(savedInstanceState);
  29.  
    setContentView(R.layout.activity_monitor_sms);
  30.  
    tv_check_flow = findViewById(R.id.tv_check_flow);
  31.  
    tv_check_flow.setOnClickListener(this);
  32.  
    findViewById(R.id.btn_check_flow).setOnClickListener(this);
  33.  
    initSmsObserver();
  34.  
    }
  35.  
     
  36.  
    @Override
  37.  
    public void onClick(View v) {
  38.  
    if (v.getId() == R.id.btn_check_flow) {
  39.  
    //查询数据流量,移动号码的查询方式为发送短信内容“18”给“10086
  40.  
    //电信和联通号码的短信查询方式请咨询当地运营商客服热线
  41.  
    //跳到系统的短信发送页面,由用户手工发短信
  42.  
    //sendSmsManual("10086", "18");
  43.  
    //无需用户操作,自动发送短信
  44.  
    sendSmsAuto("10086", "18");
  45.  
    } else if (v.getId() == R.id.tv_check_flow) {
  46.  
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
  47.  
    builder.setTitle("收到流量校准短信");
  48.  
    builder.setMessage(mCheckResult);
  49.  
    builder.setPositiveButton("确定", null);
  50.  
    builder.create().show();
  51.  
    }
  52.  
    }
  53.  
     
  54.  
    // 跳到系统的短信发送页面,由用户手工编辑与发送短信
  55.  
    public void sendSmsManual(String phoneNumber, String message) {
  56.  
    Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.parse("smsto:" phoneNumber));
  57.  
    intent.putExtra("sms_body", message);
  58.  
    startActivity(intent);
  59.  
    }
  60.  
     
  61.  
    // 短信发送事件
  62.  
    private String SENT_SMS_ACTION = "com.example.storage.SENT_SMS_ACTION";
  63.  
    // 短信接收事件
  64.  
    private String DELIVERED_SMS_ACTION = "com.example.storage.DELIVERED_SMS_ACTION";
  65.  
     
  66.  
    // 无需用户操作,由App自动发送短信
  67.  
    public void sendSmsAuto(String phoneNumber, String message) {
  68.  
    // 以下指定短信发送事件的详细信息
  69.  
    Intent sentIntent = new Intent(SENT_SMS_ACTION);
  70.  
    sentIntent.putExtra("phone", phoneNumber);
  71.  
    sentIntent.putExtra("message", message);
  72.  
    PendingIntent sentPI = PendingIntent.getBroadcast(this, 0,
  73.  
    sentIntent, PendingIntent.FLAG_UPDATE_CURRENT);
  74.  
    // 以下指定短信接收事件的详细信息
  75.  
    Intent deliverIntent = new Intent(DELIVERED_SMS_ACTION);
  76.  
    deliverIntent.putExtra("phone", phoneNumber);
  77.  
    deliverIntent.putExtra("message", message);
  78.  
    PendingIntent deliverPI = PendingIntent.getBroadcast(this, 1,
  79.  
    deliverIntent, PendingIntent.FLAG_UPDATE_CURRENT);
  80.  
    // 获取默认的短信管理器
  81.  
    SmsManager smsManager = SmsManager.getDefault();
  82.  
    // 开始发送短信内容。要确保打开发送短信的完全权限,不是那种还需提示的不完整权限
  83.  
    smsManager.sendTextMessage(phoneNumber, null, message, sentPI, deliverPI);
  84.  
    }
  85.  
     
  86.  
    private Handler mHandler = new Handler(); // 声明一个处理器对象
  87.  
    private SmsGetObserver mObserver; // 声明一个短信获取的观察器对象
  88.  
    private static Uri mSmsUri; // 声明一个系统短信提供器的Uri对象
  89.  
    private static String[] mSmsColumn; // 声明一个短信记录的字段数组
  90.  
     
  91.  
    // 初始化短信观察器
  92.  
    private void initSmsObserver() {
  93.  
    //mSmsUri = Uri.parse("content://sms/inbox");
  94.  
    //Android5.0之后似乎无法单独观察某个信箱,只能监控整个短信
  95.  
    mSmsUri = Uri.parse("content://sms"); // 短信数据的提供器路径
  96.  
    mSmsColumn = new String[]{"address", "body", "date"}; // 短信记录的字段数组
  97.  
    // 创建一个短信观察器对象
  98.  
    mObserver = new SmsGetObserver(this, mHandler);
  99.  
    // 给指定Uri注册内容观察器,一旦发生数据变化,就触发观察器的onChange方法
  100.  
    getContentResolver().registerContentObserver(mSmsUri, true, mObserver);
  101.  
    }
  102.  
     
  103.  
    // 在页面销毁时触发
  104.  
    protected void onDestroy() {
  105.  
    super.onDestroy();
  106.  
    getContentResolver().unregisterContentObserver(mObserver); // 注销内容观察器
  107.  
    }
  108.  
     
  109.  
    // 定义一个短信获取的观察器
  110.  
    private static class SmsGetObserver extends ContentObserver {
  111.  
    private Context mContext; // 声明一个上下文对象
  112.  
    public SmsGetObserver(Context context, Handler handler) {
  113.  
    super(handler);
  114.  
    mContext = context;
  115.  
    }
  116.  
     
  117.  
    // 观察到短信的内容提供器发生变化时触发
  118.  
    public void onChange(boolean selfChange) {
  119.  
    String sender = "", content = "";
  120.  
    // 构建一个查询短信的条件语句,移动号码要查找10086发来的短信
  121.  
    String selection = String.format("address='10086' and date>%d",
  122.  
    System.currentTimeMillis() - 1000 * 60 * 1); // 查找最近一分钟的短信
  123.  
    // 通过内容解析器获取符合条件的结果集游标
  124.  
    Cursor cursor = mContext.getContentResolver().query(
  125.  
    mSmsUri, mSmsColumn, selection, null, " date desc");
  126.  
    // 循环取出游标所指向的所有短信记录
  127.  
    while (cursor.moveToNext()) {
  128.  
    sender = cursor.getString(0); // 短信的发送号码
  129.  
    content = cursor.getString(1); // 短信内容
  130.  
    Log.d(TAG, "sender=" sender ", content=" content);
  131.  
    break;
  132.  
    }
  133.  
    cursor.close(); // 关闭数据库游标
  134.  
    mCheckResult = String.format("发送号码:%s\n短信内容:%s", sender, content);
  135.  
    // 依次解析流量校准短信里面的各项流量数值,并拼接流量校准的结果字符串
  136.  
    String flow = String.format("流量校准结果如下:总流量为:%s;已使用:%s"
  137.  
    ";剩余流量:%s", findFlow(content, "总流量为"),
  138.  
    findFlow(content, "已使用"), findFlow(content, "剩余"));
  139.  
    if (tv_check_flow != null) { // 离开该页面后就不再显示流量信息
  140.  
    tv_check_flow.setText(flow); // 在文本视图显示流量校准结果
  141.  
    }
  142.  
    super.onChange(selfChange);
  143.  
    }
  144.  
    }
  145.  
     
  146.  
    // 解析流量短信里面的流量数值
  147.  
    private static String findFlow(String sms, String begin) {
  148.  
    String flow = findString(sms, begin, "GB");
  149.  
    String temp = flow.replace("GB", "").replace(".", "");
  150.  
    if (!temp.matches("\\d ")) {
  151.  
    flow = findString(sms, begin, "MB");
  152.  
    }
  153.  
    return flow;
  154.  
    }
  155.  
     
  156.  
    // 截取指定头尾之间的字符串
  157.  
    private static String findString(String content, String begin, String end) {
  158.  
    int begin_pos = content.indexOf(begin);
  159.  
    if (begin_pos < 0) {
  160.  
    return "未获取";
  161.  
    }
  162.  
    String sub_sms = content.substring(begin_pos);
  163.  
    int end_pos = sub_sms.indexOf(end);
  164.  
    if (end_pos < 0) {
  165.  
    return "未获取";
  166.  
    }
  167.  
    if (end.equals(",")) {
  168.  
    return sub_sms.substring(begin.length(), end_pos);
  169.  
    } else {
  170.  
    return sub_sms.substring(begin.length(), end_pos end.length());
  171.  
    }
  172.  
    }
  173.  
     
  174.  
    }
学新通

XML文件代码

activity_monitor_smsXML

  1.  
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2.  
    android:layout_width="match_parent"
  3.  
    android:layout_height="match_parent"
  4.  
    android:orientation="vertical" >
  5.  
     
  6.  
    <Button
  7.  
    android:id="@ id/btn_check_flow"
  8.  
    android:layout_width="match_parent"
  9.  
    android:layout_height="wrap_content"
  10.  
    android:gravity="center"
  11.  
    android:text="发送校准短信"
  12.  
    android:textColor="@color/black"
  13.  
    android:textSize="17sp" />
  14.  
     
  15.  
    <TextView
  16.  
    android:id="@ id/tv_check_flow"
  17.  
    android:layout_width="match_parent"
  18.  
    android:layout_height="wrap_content"
  19.  
    android:paddingLeft="5dp"
  20.  
    android:textColor="@color/black"
  21.  
    android:textSize="17sp" />
  22.  
     
  23.  
    </LinearLayout>
学新通

创作不易 觉得有帮助请点赞关注收藏~~~~

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgabjic
系列文章
更多 icon
同类精品
更多 icon
继续加载