Android Studio初学者实例:ContentProvider读取手机通讯录

news2024/12/26 8:02:17

该实验是通过ContentProvider读取手机通讯录

知识点包含了RecyclerView控件、UriMatcher、ContentResolver

先看效果,显示手机通讯录

 首先是界面的布局代码

activity_main59.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity59">
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#42BCF3"
        android:gravity="center"
        android:text="通讯录"
        android:textColor="#FFFFFF"
        android:textSize="30dp" />

    <androidx.recyclerview.widget.RecyclerView

        android:id="@+id/rv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#E4E0E0"
        />
</LinearLayout>

其次是RecyclerView的item布局代码,其中使用了CardView是为了方便快捷的弄个圆角储来

main59_item.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:padding="40dp"
    app:cardCornerRadius="40px"
    android:layout_marginTop="20dp"
    android:background="@color/white">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/txlogo"/>
    <LinearLayout
        android:layout_marginLeft="10dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:id="@+id/name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="姓名"
            android:textSize="20dp"
            android:textStyle="bold" />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="号码"
            android:layout_marginTop="10dp"
            android:id="@+id/number"
            android:textSize="20dp"/>
    </LinearLayout>
    </LinearLayout>

</androidx.cardview.widget.CardView>

一个联系人的实体类

Communication
public class Communication {
    private  String name;
    private String number;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public Communication(String name, String number) {
        this.name = name;
        this.number = number;
    }
}
RecyclerView的适配器:
Main59Adapter
import android.content.Context;
import android.database.Cursor;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;

import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.List;

public class Main59Adapter extends RecyclerView.Adapter<Main59Adapter.MyViewHolder> {

    private  RecyclerView mRv;
    private Context context;
    private List<Communication> dataSource;


    public Main59Adapter(Context context,RecyclerView recyclerView){
        this.context=context;
        this.dataSource=new ArrayList<>();
        this.mRv=recyclerView;
    }
    public void setDataSource(List<Communication> dataSource) {
        this.dataSource = dataSource;
        notifyDataSetChanged();
    }


    class  MyViewHolder extends RecyclerView.ViewHolder{

        TextView name,number;
        public MyViewHolder(@NonNull @NotNull View itemView) {
            super(itemView);
            name=itemView.findViewById(R.id.name);
            number=itemView.findViewById(R.id.number);
        }
    }

    @NonNull
    @NotNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull @NotNull ViewGroup parent, int viewType) {
        return new Main59Adapter.MyViewHolder(LayoutInflater.from(context).inflate(R.layout.main59_item,parent,false));
    }

    @Override
    public void onBindViewHolder(@NonNull @NotNull MyViewHolder holder, int position) {
        holder.name.setText(dataSource.get(position).getName());
        holder.number.setText(dataSource.get(position).getNumber());

    }

    @Override
    public int getItemCount() {
        return dataSource.size();
    }
}

逻辑代码

MainActivity59

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.view.View;
import android.view.ViewGroup;

import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.List;

public class MainActivity59 extends AppCompatActivity {
/*
* ContentProvider
* 我们想在自己的应用中访问别的应用,或者说一些ContentProvider暴露给我们的一些数据, 比如手机联系人,短信等!我们想对这些数据进行读取或者修改,这就需要用到ContentProvider了
* 我们自己的应用,想把自己的一些数据暴露出来,给其他的应用进行读取或操作,我们也可以用 到ContentProvider,另外我们可以选择要暴露的数据,就避免了我们隐私数据的的泄露
* 并不仅仅可以查数据,根据权限 还能增删改数据
* */
    RecyclerView recyclerView;
    Cursor cursor;
    List<Communication>communications=new ArrayList<>();
    private  Main59Adapter mAdapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main59);
        //动态申请权限
        getContacts();
        recyclerView=findViewById(R.id.rv);
        LinearLayoutManager linearLayoutManager=new LinearLayoutManager(this);
        recyclerView.setLayoutManager(linearLayoutManager);
        mAdapter=new Main59Adapter(this,recyclerView);

        recyclerView.setAdapter(mAdapter);
        mAdapter.setDataSource(communications);

    }


//获取手机联系人
    private void getContacts(){
        //①查询raw_contacts表获得联系人的id
        ContentResolver resolver = getContentResolver();
        Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
        //查询联系人数据
        cursor = resolver.query(uri, null, null, null, null);
        cursor.moveToFirst();
       do
        {
            //获取联系人姓名,手机号码
            String cName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
            String cNum = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
            communications.add(new Communication(cName,cNum));
        }while (cursor.moveToNext());
        cursor.close();
    }



}

另外请注意在AndroidManifest.xml

添加权限:

    <uses-permission android:name="android.permission.READ_CONTACTS" /> <!-- 手机联系人 -->

可以翻看资料进行静态或动态申请,也可以直接进行手机系统将手机通讯录权限给APP

这里给出一个例子:

点击按钮没有权限申请权限,有权限跳转通讯录界面,注意:这只是个例子需要你修改,

一般报错如下是这个原因:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.mk.zhengtailai.PersonalBankManager/com.mk.zhengtailai.PersonalBankManager. TXLActivity}: java.lang.SecurityException: Permission Denial: opening provider com.android.providers.contacts. ContactsProvider2 from ProcessRecord{85e7d40 8538:com.mk.zhengtailai. PersonalBankManager/u0a124} (pid=8538, uid=10124) requires android.permission. READ_CONTACTS or android.permission.WRITE_CONTACTS

 view.findViewById(R.id.button5).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(ContextCompat.checkSelfPermission(getContext(), Manifest.permission.READ_CONTACTS)
                        != PackageManager.PERMISSION_GRANTED){
                    ActivityCompat.requestPermissions(getActivity(),new String[]{Manifest.permission.READ_CONTACTS},1);
                }else {
                    Intent intent=new Intent(getContext(),TXLActivity.class);
                    startActivity(intent);
                }
            }
        });

今天又写了一遍发现,手机没有通讯录的话会报错:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.mk.zhengtailai.PersonalBankManager/com.mk.zhengtailai.PersonalBankManager. TXLActivity}: android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0

所以我就随便加个try处理一下:

 try {
         Intent intent=new Intent(getContext(),TXLActivity.class);
         startActivity(intent);
      }catch (Exception e){
          Toast.makeText(getContext(), "通讯录无联系人", Toast.LENGTH_SHORT).show();
       }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1891070.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[译]Reactjs性能篇

英文有限&#xff0c;技术一般&#xff0c;海涵海涵&#xff0c;由于不是翻译出身&#xff0c;所以存在大量的瞎胡乱翻译的情况&#xff0c;信不过我的&#xff0c;请看原文&#xff5e;&#xff5e; 原文地址&#xff1a;https://facebook.github.io/react/docs/advanced-per…

不同操作系统下的换行符

1. 关键字2. 换行符的比较3. ASCII码4. 修改换行符 4.1. VSCode 5. 参考文档 1. 关键字 CR LF CRLF 换行符 2. 换行符的比较 英文全称英文缩写中文含义转义字符ASCII码值操作系统Carriage ReturnCR回车\r13MacIntosh&#xff08;早期的Mac&#xff09;LinefeedLF换行/新行\…

Qt Q_ASSERT详解

Q_ASSERT详解 引言一、基本用法二、深入了解三、参考链接 引言 Q_ASSERT是 Qt 框架中的一个宏&#xff0c;用于在调试时检查某个条件是否为真。它是程序调试中的一个重要工具&#xff0c;有助于开发者在开发过程中及时发现并修复潜在的错误。 一、基本用法 只在使用 Qt 的 D…

暑期大数据人工智能学习-企业项目试岗实训开营

暑期企业项目-试岗实训活动全面开启啦 跟张良均老师学大数据人工智能 不仅可以提供实习证明&#xff0c;有需要话也可以提供实习鉴定报告 √54个热门案例拆解 √40项目实战课程 √27个项目可选 √4个项目方向

数据提取的奥秘

在数字化时代&#xff0c;数据提取作为连接原始数据与知识发现的桥梁&#xff0c;其重要性不言而喻。它不仅是数据分析和数据治理的基石&#xff0c;更是企业决策和业务优化的关键。以下是数据提取奥秘的详细解析&#xff1a; 一、数据提取的定义与意义 定义&#xff1a;数据…

怎样保存python文件

按下“CtrlS”键即可快速保存Python文件。 或者点击“File”&#xff0c;在下拉菜单中选择“Save”。 打开后我们就会看到这样的一个页面窗口了。 我们还能在这里进行路径的保存位置的查找。 然后在这里选择文件类型&#xff0c;并输入文件名。 接下来我们点击保存就可以完成操…

PyCharm远程开发配置(2024以下版本)

目录 PyCharm远程开发配置 1、清理远程环境 1.1 点击Setting 1.2 进入Interpreter 1.3 删除远程环境 1.4 删除SSH 2、连接远程环境 2.1 点击Close Project 2.2 点击New Project 2.3 项目路径设置 2.4 SSH配置 2.5 选择python3解释器在远程环境的位置 2.6 配置远程…

AI Agent当牛做马,办公自动化带来超级生产力|对话Laplace

成立仅9个月的AI初创公司拉普拉斯智能&#xff08;Laplace AI&#xff09;&#xff0c;已经用原生智能生产力操作平台帮助企业用户实现智能体落地了&#xff01; 平台名为拉普拉斯智能实验室&#xff08;Laplace AI Lab&#xff09;&#xff0c;入口统一&#xff0c;用自然语言…

2024-2025年本田维修电路图线路图接线图资料更新

此次更新了2024-2025年本田车系电路图资料&#xff0c;覆盖市面上99%车型&#xff0c;包括维修手册、电路图、新车特征、车身钣金维修数据、全车拆装、扭力、发动机大修、发动机正时、保养、电路图、针脚定义、模块传感器、保险丝盒图解对照表位置等等&#xff01; 汽修帮手汽…

小迪安全v2023 javaWeb项目

小迪安全v2023 javaWeb项目 大体上跟随小迪安全的课程&#xff0c;本意是记录自己的学习历程&#xff0c;不能说是完全原创吧&#xff0c;大家可以关注一下小迪安全&#xff0c;他讲的挺好的。 若有冒犯&#xff0c;麻烦私信移除。 已获得迪の认可&#xff0c;哈哈 文章目录…

【Spring Boot】关系映射开发(一):一对一映射

关系映射开发&#xff08;一&#xff09;&#xff1a;一对一映射 1.认识实体间关系映射1.1 映射方向1.2 ORM 映射类型 2.实现 “一对一” 映射2.1 编写实体2.1.1 新建 Student 实体2.1.2 新建 Card 实体 2.2 编写 Repository 层2.2.1 编写 Student 实体的 Repository2.2.2 编写…

轮换IP是什么?——深入了解轮换IP的特点

大家在日常上网时&#xff0c;可能听说过“轮换IP”这个词。那么&#xff0c;轮换IP到底是什么&#xff1f;它有哪些特点&#xff1f;今天&#xff0c;我们就来揭开轮换IP的神秘面纱。 什么是轮换IP&#xff1f; 简单来说&#xff0c;轮换IP是指定期更换上网时使用的IP地址。…

C++字体库开发二

Font: 字体大小&#xff0c;方向&#xff0c;变换 FontContext: 多语言&#xff0c;更新&#xff0c;基础字体&#xff0c;表情 FontDescription: 字重&#xff0c;子样式&#xff0c;名称&#xff0c;底色 FontDir: 字体目标 FontFace: Regular,Bold特殊字重 FontFamily: 字体…

嵌入式c语言3——自定义数据类型

结构体struct&#xff0c;共用体union 结构体中定义变量&#xff0c;首尾地址相连 对于union&#xff0c;其包含变量对起始地址相同 由于其起始地址相同&#xff0c;则改变其中某一变量值时有可能使得另一个变量值发生改变 enum 枚举&#xff0c;可以用来定义一堆整形常量构成…

itk::ShapedNeighborhoodIterator类C2516问题

错误问题&#xff1a; 1>C:\itk\src-5.3.0\Modules\Core\Common\include\itkShapedNeighborhoodIterator.h(183,1): error C2516: itk::ShapedNeighborhoodIterator<TImage,TBoundaryCondition>::ConstIterator: is not a legal base class 1>C:\itk\src-5.3.0\Mo…

解决Visual Studio 一直弹出管理员身份运行问题(win10/11解决办法)

不知道大家是否有遇到这个问题 解决办法也很简单 找到启动文件 如果是快捷方式就继续打开文件位置 找到这个程序启动项 右键 选择 兼容性疑难解答&#xff08;win11 则需要 按住 shift 右键&#xff09; win10 解决办法 这样操作完后就可以了 win11解决办法按以下选择就行

Android触摸事件分发关键点【笔记摘要】

触摸事件分发&#xff1a;就是一个为了解决触摸事件冲突而设置的机制 1.事件类型 ACTION_DOWN -> ACTION_UP / ACTION_CANCEL ACTION_DOWN -> ACTION_MOVE -> ACTION_MOVE -> ACTION_MOVE -> ACTION_UP / ACTION_CANCEL 这个取消事件ACTION_CANCEL它是一种特殊…

Go语言工程管理

本文内容为Go工程创建和配置开发及简单程序示例。 目录 工程管理 GOPATH 配置GOPATH GOROOT 新建系统变量 配置go工程 添加go path 简单的程序实现 程序代码 开始运行 运行结果 内容解析 总结 工程管理 GOPATH go语言的项目&#xff0c;需要有特定的目录结构进行…

Osg中的智能指针和观察指针

目录 1 设计 内容 1 设计 osg中能够使用智能指针的对象都继承自引用计数类Referenced&#xff0c;观察指针(observer_ptr)与智能指针之间通过ObserverSet相互关联&#xff0c;其中obserserver_ptr直接依赖ObeserverSet。 Referenced不直接依赖ObserverSet类&#xff0c;但可…

springboot java.lang.ClassNotFoundException: dm.jdbc.driver.DmDriver 应该如何解决

遇到的问题&#xff1a;项目中引用了外部的达梦jar包 在idea中正常使用 也能找到dm.jdbc.driver.DmDriver 驱动 但是当通过jenkins 构建部署到服务器上 总是报 ClassNotFoundException: dm.jdbc.driver.DmDriver 找不到驱动 应用到的驱动代码如下格式 排查步骤 1.首先看你的项…