Android Studio初学者实例:ContentProvider读取手机通讯录
该实验是通过ContentProvider读取手机通讯录
知识点包含了RecyclerView控件、UriMatcher、ContentResolver
先看效果,显示手机通讯录
首先是界面的布局代码
activity_main59.xml
其次是RecyclerView的item布局代码,其中使用了CardView是为了方便快捷的弄个圆角储来
main59_item.xml
一个联系人的实体类
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 { private RecyclerView mRv; private Context context; private List dataSource; public Main59Adapter(Context context,RecyclerView recyclerView){ this.context=context; this.dataSource=new ArrayList(); this.mRv=recyclerView; } public void setDataSource(List 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; Listcommunications=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
添加权限:
可以翻看资料进行静态或动态申请,也可以直接进行手机系统将手机通讯录权限给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(); }