无脑笔记--内容提供器01

一、概述:

内容提供程序有助于应用管理其自身和其他应用所存储数据的访问,并提供与其他应用共享数据的方法。它们会封装数据,并提供用于定义数据安全性的机制。内容提供程序是一种标准接口,可将一个进程中的数据与另一个进程中运行的代码进行连。实现内容提供程序大有好处。最重要的是,通过配置内容提供程序,您可以使其他应用安全地访问和修改您的应用数据。

在这里插入图片描述

二、访问提供程序

对于每一个应用程序来说,如果想要访问内容提供器中共享的数据,就一定要借助ContentResolver类,可以通过Context中的getContentResolver()方法获取到该类的实例。(ContentResolver 对象会与提供程序对象(即实现 ContentProvider 的类实例)进行通信。提供程序对象从客户端接收数据请求、执行请求的操作并返回结果。)ContentResolver中提供了一系列的方法用于对数据进行CRUD操作,其中insert()方法用于添加数据,update()方法用于更新,delete()方法用于删除数据,query()方法用于查询数据。和SQLite中进行CRUD操作的方法类似,只是在参数上面有些不同。

从界面访问ContentProvider的常用模式会通过使用CursorLoader,在后台运行异步查询。界面中的Activity或Fragment会调用查询的CursorLoader,其转而使用ContentResolver来获取ContentProvider。
在这里插入图片描述
ContentResolver中的增删改查方法都是不接收表名参数的,而是使用一个Uri参数代替,这个参数被称为内容URI。内容URI给内容提供器中的数据建立唯一标识符,他一般由两个部分组成:authority和path。authority是用于对不同的应用程序做区分的,一般为了冲突,都会采用程序包名的方式来命名。比如某个程序的的包名是com.example.app,那么这个程序对应的authority就是com.example.app.provider。path则是用于对同一应用程序中的不同的表做区分的,通常会添加到authority后面。比如此时数据库中有两个表table1和table2,这是path就可以命名为/table1和/table2。然后将authority和path进行组合,再在字符串头部加上协议声明,内容URI标准写法如下:

content://com.example.app.provider/table1
content://com.example.app.provider/table2

在得到内容URI字符串后,还需要将它解析成Uri对象才可以作为参数传入,解析代码如下:

Uri uri=Uri.parse("content://com.example.app.provider/table1");
//调用Uri.parse()方法,就可以把URI内容字符串解析成Uri对象了

现在就可以用这个Uri对象来查询table1中的数据了。

// Queries the user dictionary and returns results
cursor = getContentResolver().query(
    UserDictionary.Words.CONTENT_URI,   // The content URI of the words table
    projection,                        // The columns to return for each row
    selectionClause,                   // Selection criteria
    selectionArgs,                     // Selection criteria
    sortOrder);                        // The sort order for the returned rows

在这里插入图片描述
查询完成后返回的仍是一个Cursor对象,这时我们就可以将数据从Cursor对象中逐一读取出来了 。读取的思路是通过移动游标的位置来遍历Cursor中的所有行,然后再取出每一行中相应列的数据,代码如下:

if(cursor!=null)
{
	while(cursor.moveToNext())
	{
	String column1=cursor.getString(cursor.getColumnIndex("colunm1"));
	int column2=cursor.getInt(cursor.getColumnIndex("column2"));
	}
	cursor.close();
}

添加数据,将数据组装到ContentValues中,再调用ContentResolver的insert()方法。将Uri和ContentValues作为参数传入即可:

ContentValues values=new ContentValues();
values.put("column1","text");
values.put("column2",999);
getContentResolver().insert(uri,values);

更新数据:

ContentValues values=new ContentValues();
values.put("column1","update");
getContentResolver().update(uri,values,"column1=? and column2=?",new String[]{"text","999"});
//将column1=text,column2=999的数据中的column1内容修改为“update”

删除数据

getContentResolver().delete(uri,"column2=?",new String[]{"999"});

三、读取系统联系人-实践

ListView布局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ListView
        android:id="@+id/listview_contacts"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>

获取权限+读取系统联系人

public class ContactsTestActivity extends AppCompatActivity  {

    private ListView listViewContacts;
    ArrayAdapter<String> adapter;
    List<String> contactList=new ArrayList<>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_contacts_test);
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS)!= PackageManager.PERMISSION_GRANTED)
        {
            ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.READ_CONTACTS},1);
        }
        else{
            readContacts();
        }
        listViewContacts=(ListView)findViewById(R.id.listview_contacts);
        adapter=new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,contactList);
        listViewContacts.setAdapter(adapter);

    }
	//读取系统联系人
    private  void readContacts()
    {
        Cursor cursor=null;
        try {
            cursor=getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,null,null,null);
            if (cursor!=null)
            {
                while(cursor.moveToNext())
                {
                    //获取联系人姓名
                    String displayName=cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
                    //获取联系人手机号
                    String number=cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));

                    contactList.add(displayName+"\n"+number);
                }
                adapter.notifyDataSetChanged();
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(cursor!=null)
            {
                cursor.close();
            }
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch(requestCode)
        {
            case 1:
                if (grantResults.length>0&&grantResults[0]==PackageManager.PERMISSION_GRANTED)
                {
                    readContacts();
                }
                else
                {
                        if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_CONTACTS)) {
                            Toast.makeText(this,"我们需要获得READ_CONTACTS权限才可以访问通讯录!!!",Toast.LENGTH_SHORT).show();
                            // *异步*向用户显示说明-不要阻止
                            //此线程等待用户的响应!之后用户
                            //看到说明,然后重试以请求许可。
                        } else {
                            // 无需解释;请求许可
                            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS},1);
                        }
                }
                break;
                default:
        }
    }
}

最后,还需要在AndroidManifest.xml中添加权限声明:

  <uses-permission android:name="android.permission.READ_CONTACTS"/>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值