Content Provider与SQLite结合使用

本文详细介绍了在Android中如何使用Content Provider来实现数据共享,特别是与SQLite数据库结合使用。通过示例展示了如何创建自定义Content Provider,设置权限,以及如何使用CursorLoader进行查询、筛选和排序。此外,还解释了如何在AndroidManifest.xml中注册Content Provider,并通过自定义的Content Provider操作SQLite数据库。
摘要由CSDN通过智能技术生成

前言

  虽然推荐使用数据库保存结构化的复杂数据,但是数据共享是一个挑战,因为数据库只允许创建它的应用访问。

在Android中共享数据

  在Android中,推荐使用content provider方法在不同包之间共享数据。content provider可以被视为一个数据仓库。它如何存储数据与应用如何使用它无关。然而,应用如何使用一致的编程接口在它的里面的数据非常重要。content provider的行为与数据库非常相似——你可以查询它、编辑它的内容、添加或者删除内容。然而,与数据库不同的是,一个content provider可以使用不同的方式存储它的数据。数据可以被存储在数据库中、在文件中、甚至在网络上。
  Android提供了许多非常有用的content provider,包括以下几种:

类型 说明
Browser 存储浏览器数据,比如浏览器的书签、浏览器访问历史等。
CallLog 存储通话数据,比如未接电话、通话详情等。
Contacts 存储通讯录详情。
MediaStore 存储多媒体文件,比如音频、视频和图片。
Settings 存储设备的设置和偏好设置。

  除了许多内置的content provider以外,可以创建自定义的content provider。
  要查询一个content provider,需要以统一的资源标识符(Uniform Resource Identifier,URI)的形式制定查询字符串,以及一个可选的特定行说明符。以下是查询URI的形式:

<standard_prefix>://<authority>/<data_path>/<id>

  URI的各种组成部分如下:

组成 说明
content provider content provider的标准前缀是content://
authority 指定content provider的名称。例如内置Contacts的content provider的名称为contacts。对于第三方content provider来说,它可以是完整的合法名称,例如com.wrox.provider。
data_path 指定请求的数据种类。例如,如果你要从Contacts的content provider中获取所有的通讯录,那么data_path应该是people,URI将类似与:content://contacts/people
id 指定请求特定的记录。例如,如果你要获取Contacts的content provider中第2条通讯录,URI将类似类似于:content://contact/people/2
查询字符串 描述
content://media/internal/images 返回设备上保存在内部存储中的图片列表。
content://media/external/images 返回设备上保存在外部存储(例如SD卡)中的图片列表。
content://call_log/calls 返回登记在通话记录中的通话记录。
content://browser/bookmarks 返回存储在浏览器中的书签列表。

使用content provider

  理解content provider的最佳方法是在实践中使用它。

Main2Activity

public class Main2Activity extends ListActivity {
   
    final private int REQUEST_READ_CONTACTS = 123;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);

        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.READ_CONTACTS)
                != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.READ_CONTACTS},
                    REQUEST_READ_CONTACTS);
        } else {
            listContacts();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode
            , @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode) {
            case REQUEST_READ_CONTACTS:
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    listContacts();
                } else {
                    Toast.makeText(Main2Activity.this
                            , "Permission Denied", Toast.LENGTH_SHORT).show();
                }
                break;
            default:
                super.onRequestPermissionsResult(requestCode
                        , permissions, grantResults);
        }
    }

    protected void listContacts() {
        Uri allContacts = Uri.parse("content://contacts/people");
        CursorLoader cursorLoader = new CursorLoader(
                this,
                allContacts,
                null,
                null,
                null,
                null);
        Cursor cursor = cursorLoader.loadInBackground();
        String[] columns = new String[]{
                ContactsContract.Contacts.DISPLAY_NAME,
                ContactsContract.Contacts._ID};
        int[] views = new int[]{R.id.contactName, R.id.contactID};
        SimpleCursorAdapter adapter;
        adapter = new SimpleCursorAdapter(
                this, R.layout.activity_main2, cursor, columns, views,
                CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
        this.setListAdapter(adapter);
    }
}

  本示例获取了存储在Contacts应用中的通讯录并且将其显示在ListView中。
  首先指定访问Contacts应用的URI:

Uri allContacts = Uri.parse("content://contacts/people");

  其次,检查应用是否由访问Contacts的权限:

if (ContextCompat.checkSelfPermission(this,
    Manifest.permission.READ_CONTACTS)
    != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(this,
        new String[]{Manifest.permission.READ_CONTACTS},
        REQUEST_READ_CONTACTS);
} else {
    listContacts();
}

  如果没有访问权限,就会发出一条权限请求(使Android弹出一个权限请求对话框)。如果应用由相应的访问权限,ListContacts()方法会被调用。
  getContentResolver()方法返回一个ContentResolver对象,它会使用适当content provider解析内容URI。
  CursorLoader类(Android API level 11及以上版本可用)在后再线程中执行cursor查询操作,因此不会阻塞应用UI。

CursorLoader cursorLoader = new CursorLoader(
    this,
    allContacts,
    null,
    null,
    null,
    null);
Cursor cursor = cursorLoader.loadInBackground();

  SimpleCursorAdapter对象将一个Cursor数据映射到XML文件(activity_main2.xml)中定义的TextView(或者ImageView)。它将数据(对应于代码中的columns变量)映射到视图(对应于代码中的view变量)中:

String[] columns = new String[]{
    ContactsContract.Contacts.DISPLAY_NAME,
    ContactsContract.Contacts._ID
};
int[] views = new int[]{
    R.id.contactName, R.id.contactID
};
SimpleCursorAdapter adapter = new SimpleCursorAdapter(
    this, R.layout.activity_main2, cursor, columns, views,
    CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
this.setListAdapter(adapter);

  类似于managedQuery()方法,SimpleCursorAdapter类的一个构造函数已经被弃用。对于运行Honeycomb及后续版本的设备,需要使用新的SimpleCursorAdapter类的构造函数,与旧版本相比,该构造函数多一个参数:

 SimpleCursorAdapter adapter = new SimpleCursorAdapter(
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值