[Android Studio]使用ContentProvider对手机联系人进行读写操作+RecyclerView+ActionBar

使用ContentProvider对收集联系人进行读写操作+RecyclerView+ActionBar


基于前期WeChat项目,在 Fragment中实现

  1. RecyclerView以展开和收缩的效果显示手机联系人信息(姓名、手机号、邮箱地址) 。
  2. WeChat标题处右上角添加按钮,点击按钮弹出对话框,实现添加手机联系人,并在指定Fragment中显示(刷新得以显示)。
  3. 点击Fragment界面的ActionBar弹出对话框,实现添加手机联系人,并在当前Fragment中显示。

我选择的是在findFragment中实现相关功能。
在这里插入图片描述

RecyclerView展开和收缩

主要参考https://www.jianshu.com/p/c4cfe38a91ed,需要注意的是数据的切片处理和adapter onBindViewHolder对其动态效果的实现。

获取读写手机联系人的权限

AndroidManifest.xml 加上权限说明

    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.WRITE_CONTACTS" />

findFragment.java 申请授权

		int hasWriteContactsPermisson = ContextCompat.checkSelfPermission(view.getContext(), Manifest.permission.READ_CONTACTS);
        if(hasWriteContactsPermisson != PackageManager.PERMISSION_GRANTED) {
            requestPermissions(new String[]{Manifest.permission.WRITE_CONTACTS}, 1);
        }

标题右上角的点击事件

MainActivity.java

		btnTopAdd = (ImageButton) findViewById(R.id.btnTopAdd);
        btnTopAdd.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(final View v) {
                // 加载result.xml界面布局代表的视图
                final View resultDialog = getLayoutInflater().inflate(R.layout.top_btn_add, null);  // 设置成final,否则String name = ((EditText) resultDialog.findViewById(R.id.name)).getText().toString();报EditText空指针错误
                // 使用对话框来显示查询结果
                AlertDialog show = new AlertDialog.Builder(MainActivity.this)
                        .setView(resultDialog)
                        .setTitle("Add your contact")
                        .setPositiveButton("确认", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                // 获取程序界面中的三个文本框的内容
                                String name = ((EditText) resultDialog.findViewById(R.id.name)).getText().toString();
                                String phone = ((EditText) resultDialog.findViewById(R.id.phone)).getText().toString();
                                String email = ((EditText) resultDialog.findViewById(R.id.email)).getText().toString();
                                // 创建一个空的ContentValues
                                ContentValues values = new ContentValues();
                                // 向RawContacts.CONTENT_URI执行一个空值插入
                                // 目的是获取系统返回的rawContactId
                                Uri rawContactUri = getContentResolver().insert(ContactsContract.RawContacts.CONTENT_URI, values);
                                long rawContactId = ContentUris.parseId(rawContactUri);
                                values.clear();
                                values.put(ContactsContract.RawContacts.Data.RAW_CONTACT_ID, rawContactId);
                                // 设置内容类型
                                values.put(ContactsContract.RawContacts.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);
                                // 设置联系人名字
                                values.put(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, name);
                                // 向联系人URI添加联系人名字
                                getContentResolver().insert(ContactsContract.Data.CONTENT_URI, values);
                                values.clear();
                                values.put(ContactsContract.RawContacts.Data.RAW_CONTACT_ID, rawContactId);
                                values.put(ContactsContract.RawContacts.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
                                // 设置联系人的电话号码
                                values.put(ContactsContract.CommonDataKinds.Phone.NUMBER, phone);
                                // 设置电话类型
                                values.put(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE);
                                // 向联系人电话号码URI添加电话号码
                                getContentResolver().insert(ContactsContract.Data.CONTENT_URI, values);
                                values.clear();
                                values.put(ContactsContract.RawContacts.Data.RAW_CONTACT_ID, rawContactId);
                                values.put(ContactsContract.RawContacts.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE);
                                // 设置联系人的E-mail地址
                                values.put(ContactsContract.CommonDataKinds.Email.DATA, email);
                                // 设置该电子邮件的类型
                                values.put(ContactsContract.CommonDataKinds.Email.TYPE, ContactsContract.CommonDataKinds.Email.TYPE_WORK);
                                // 向联系人E-mail URI添加E-mail数据
                                getContentResolver().insert(ContactsContract.Data.CONTENT_URI, values);
                                Toast.makeText(v.getContext(), "下拉刷新[朋友],查看新增联系人", Toast.LENGTH_SHORT).show();
                            }
                        })
                        .setNegativeButton("取消", null).show();

            }
        });

注:

  1. 在点击按钮弹出对话框AlertDialog后,在 setPositiveButton() 中用
new DialogInterface.OnClickListener()

来给对话框的确认按钮创建点击事件监听,其中的 context 为当前对话框的resultDailog 的环境。

  1. Uri 代表要操作的数据,ContentResolver通过ContentProvider提供的Uri接口获得封装的数据。如果是在Activity条件下,直接写getContentResolver()…;在非Activity条件下,如Fragment,需写作getActivity().getContentResolver()…。

*** 未能用及时刷新的方法让RecyclerView在点击对话框的确认按钮之后马上显示item(只怪自己太菜… …)

在此采用下拉刷新的方法对RecyclerView刷新,用到swiperefreshlayout

  1. 在build.gradle(Module:app)的dependencies 加上如下代码:
	implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.46' 
    implementation group: 'androidx.recyclerview', name: 'recyclerview', version: '1.1.0-alpha01'
  1. 在build.gradle(Project:…)的allprojects->repositories 加上如下代码:
 maven { url "https://jitpack.io"}

tab_find.xml

    <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
        android:id="@+id/swipeRefreshLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/rcv_expandcollapse"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:overScrollMode="never"
            android:layout_margin="8dp"
            android:scrollbars="none"/>

    </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

findFragment.java


	private SwipeRefreshLayout swipeRefreshLayout;
		//...
		swipeRefreshLayout = view.findViewById(R.id.swipeRefreshLayout);
        swipeRefreshLayout.setOnRefreshListener(this);      // 下拉刷新

        onRefresh();

	
    @Override
    public void onRefresh() {
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < mList.size(); ){// 先清空mList数据和RecyclerView的Item
                    mList.remove(0);
                    adapter.removeItem(0);
                }
                viewShow();	//在RecyclerView中显示所有手机联系人及其相关信息
                swipeRefreshLayout.setRefreshing(false);
            }
        }, 500);
    }

ExpandCollapseAdapter.java 加上removeItem(),参考此blog

	public void removeItem(int position) {
        mList.remove(position);
        notifyItemRemoved(position);
        notifyItemRangeChanged(position,getItemCount());   
    }

ActionBar点击事件

findFragment.java

FloatingActionButton fab = view.findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(final View view) {
                final View resultDialog = getActivity().getLayoutInflater().inflate(R.layout.top_btn_add, null);  // 设置成final,否则String name = ((EditText) resultDialog.findViewById(R.id.name)).getText().toString();报EditText空指针错误
                // 使用对话框来显示查询结果
                AlertDialog show = new AlertDialog.Builder(view.getContext())
                        .setView(resultDialog)
                        .setTitle("Add your contact")
                        .setPositiveButton("确认", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                // 获取程序界面中的三个文本框的内容
                                String name = ((EditText) resultDialog.findViewById(R.id.name)).getText().toString();
                                String phone = ((EditText) resultDialog.findViewById(R.id.phone)).getText().toString();
                                String email = ((EditText) resultDialog.findViewById(R.id.email)).getText().toString();
                                // 创建一个空的ContentValues
                                ContentValues values = new ContentValues();
                                // 向RawContacts.CONTENT_URI执行一个空值插入
                                // 目的是获取系统返回的rawContactId
                                Uri rawContactUri = getActivity().getContentResolver().insert(ContactsContract.RawContacts.CONTENT_URI, values);
                                long rawContactId = ContentUris.parseId(rawContactUri);
                                values.clear();
                                values.put(ContactsContract.RawContacts.Data.RAW_CONTACT_ID, rawContactId);
                                // 设置内容类型
                                values.put(ContactsContract.RawContacts.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);
                                // 设置联系人名字
                                values.put(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, name);
                                // 向联系人URI添加联系人名字
                                getActivity().getContentResolver().insert(ContactsContract.Data.CONTENT_URI, values);
                                values.clear();
                                values.put(ContactsContract.RawContacts.Data.RAW_CONTACT_ID, rawContactId);
                                values.put(ContactsContract.RawContacts.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
                                // 设置联系人的电话号码
                                values.put(ContactsContract.CommonDataKinds.Phone.NUMBER, phone);
                                // 设置电话类型
                                values.put(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE);
                                // 向联系人电话号码URI添加电话号码
                                getActivity().getContentResolver().insert(ContactsContract.Data.CONTENT_URI, values);
                                values.clear();
                                values.put(ContactsContract.RawContacts.Data.RAW_CONTACT_ID, rawContactId);
                                values.put(ContactsContract.RawContacts.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE);
                                // 设置联系人的E-mail地址
                                values.put(ContactsContract.CommonDataKinds.Email.DATA, email);
                                // 设置该电子邮件的类型
                                values.put(ContactsContract.CommonDataKinds.Email.TYPE, ContactsContract.CommonDataKinds.Email.TYPE_WORK);
                                // 向联系人E-mail URI添加E-mail数据
                                getActivity().getContentResolver().insert(ContactsContract.Data.CONTENT_URI, values);

                                Toast.makeText(view.getContext(), "联系人添加成功", Toast.LENGTH_SHORT).show();
                                PersonData personData = new PersonData();
                                personData.setName(name);
                                personData.setPhoneNumber(phone);
                                personData.setEmailAddress(email);
                                mDataList.add(personData);
                                mList.add("");
                                adapter.notifyDataSetChanged();
                            }
                        })
                        .setNegativeButton("取消", null).show();
            }
        });

和WeChat标题的右上角按钮差不多,相对来说较容易实现RecyclerView的及时刷新,每点一次对话框的确认按钮,就会有新的item加入到RecyclerVIew的下面。因为定义的adapter在此Fragment中可以直接调用,但在MainActivity中就比较复杂,目前没有找到解决办法。

adapter.notifyDataSetChanged();

注:
mList也要进行add操作,为了增加mList的size。否则先点悬浮按钮添加联系人,后下拉刷新,会发现有item在数量和形式上不合乎逻辑。在OnRefresh()的run()中可见其原因(先清除,后添加)。


源码已上传至github

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是在Android Studio中实现ContentProvider的步骤: 1. 创建一个新的Java类,命名为`DBHelper`,并继承自`SQLiteOpenHelper`类。在`DBHelper`类中,重写`onCreate()`和`onUpgrade()`方法,用于创建和升级数据库。 ```java public class DBHelper extends SQLiteOpenHelper { private static final String DATABASE_NAME = "mydatabase.db"; private static final int DATABASE_VERSION = 1; public DBHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { // 创建数据库表 db.execSQL("CREATE TABLE mytable (_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT)"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // 升级数据库表 db.execSQL("DROP TABLE IF EXISTS mytable"); onCreate(db); } } ``` 2. 创建一个新的Java类,命名为`MyContentProvider`,并继承自`ContentProvider`类。在`MyContentProvider`类中,重写`onCreate()`、`query()`、`insert()`、`update()`和`delete()`方法,用于实现对数据的CRUD操作。 ```java public class MyContentProvider extends ContentProvider { private DBHelper dbHelper; @Override public boolean onCreate() { dbHelper = new DBHelper(getContext()); return true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteDatabase db = dbHelper.getReadableDatabase(); Cursor cursor = db.query("mytable", projection, selection, selectionArgs, null, null, sortOrder); cursor.setNotificationUri(getContext().getContentResolver(), uri); return cursor; } @Override public Uri insert(Uri uri, ContentValues values) { SQLiteDatabase db = dbHelper.getWritableDatabase(); long id = db.insert("mytable", null, values); getContext().getContentResolver().notifyChange(uri, null); return ContentUris.withAppendedId(uri, id); } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { SQLiteDatabase db = dbHelper.getWritableDatabase(); int count = db.update("mytable", values, selection, selectionArgs); getContext().getContentResolver().notifyChange(uri, null); return count; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { SQLiteDatabase db = dbHelper.getWritableDatabase(); int count = db.delete("mytable", selection, selectionArgs); getContext().getContentResolver().notifyChange(uri, null); return count; } @Override public String getType(Uri uri) { return null; } } ``` 3. 在`AndroidManifest.xml`文件中注册`MyContentProvider`。 ```xml <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapp"> <application> <!-- ... --> <provider android:name=".MyContentProvider" android:authorities="com.example.myapp.provider" android:exported="true" /> </application> </manifest> ``` 4. 在需要访问`ContentProvider`的地方,使用`ContentResolver`类进行数据的访问。 ```java ContentResolver resolver = getContentResolver(); Cursor cursor = resolver.query(Uri.parse("content://com.example.myapp.provider/mytable"), null, null, null, null); // 处理查询结果 ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值