当前位置: 首页 > article >正文

在Android Studio中如何实现contentprovider实验+SQLite数据库(保姆级教程)

目录

一.本章要学习的内容

二.代码部分

(一)创建项目

 (二)项目结构

(三)MainActivity

(四)ContentActivity

(五)PersonDBOpenHelper

(六)PersonProvider

(七)SQLActivity

(八)activity_main.xml

(九)contentlayout.xml

(十)sqllayout.xml

(十一)strings.xml

(十二)AndroidManifest.xml

三.运行部分

(一)打开Device Manager

(二)选择上次创建的虚拟机

(三)运行

(四)运行结果

四.ContentProvider

前言

(一)ContentProvider基础介绍

1.1 简介

1.2 作用

1.3 实现原理

(二)具体使用

2.1 统一资源标识符(URI)

2.2 MIME数据类型

2.2.1 MIME类型组成

2.2.2 常见的MIME类型 

2.2.3 ContentProvider根据 URI 返回MIME类型 

2.2.4 类型分类

 2.3 ContentProvider三剑客

2.4 辅助工具类

(三)总结


一.本章要学习的内容

  1. 掌握如何在Android 开发中使用 SQLite 数据库

  2. 熟悉设计数据库表结构的方法与步骤

  3. 理解contentprovider的使用方法及流程,理解ContentProvider、Resolver、Uri、Urimatcher等的原理。

1、实现contentprovider和contentresolver通过uri的调用;

 2、实现contentprovider对数据库sqlite的功能:增、删、改、查;

 3、数据库的表结构自行设计;

1、配置SQLite 数据库的运行环境

2、熟悉contentprovider对数据库sqlite增、删、改、查的具体操作和流程

3、充分理解SQLite数据库的使用原理和方式

二.代码部分

(一)创建项目

 (二)项目结构

(三)MainActivity

package com.example.demo6;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

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

    public void toOne(View view) {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS)!= PackageManager.PERMISSION_GRANTED)
        {
            ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.READ_CONTACTS},1);
            Toast.makeText(this,"未允许读取通讯录权限!",Toast.LENGTH_SHORT).show();
        }
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS)== PackageManager.PERMISSION_GRANTED)
        {
            Intent intent = new Intent(MainActivity.this,ContentActivity.class);
            startActivity(intent);
        }
    }

    public void toTwo(View view) {
        Intent intent = new Intent(MainActivity.this,SQLActivity.class);
        startActivity(intent);
    }
}

(四)ContentActivity

package com.example.demo6;

import android.Manifest;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.widget.TextView;

import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

public class ContentActivity extends Activity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.contentlayout);
        TextView textView = (TextView) findViewById(R.id.callName);
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS)!= PackageManager.PERMISSION_GRANTED)
        {
            ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.READ_CONTACTS},1);
            textView.setText("未允许读取通讯录权限!");
        }
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS)== PackageManager.PERMISSION_GRANTED)
        {
            textView.setText(getQueryData());
        }
    }

    public String getAllPhoneNumbers(String lookUp_Key){
        StringBuilder allPhoneNo = new StringBuilder();
        String[] proj2 = {ContactsContract.CommonDataKinds.Phone.NUMBER};
        String selection = ContactsContract.Data.LOOKUP_KEY+"=?";
        String[] selectionArgs = {lookUp_Key};
        ContentResolver resolver = getContentResolver();
        Cursor cursor = resolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,proj2,selection,selectionArgs,null);
        while(cursor.moveToNext()){
            allPhoneNo.append(cursor.getString(0)).append(" ");
        }
        return allPhoneNo.toString();
    }

    private CharSequence getQueryData() {

        StringBuilder stringBuilder = new StringBuilder();
        ContentResolver resolver = getContentResolver();
        Cursor cursor = resolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                null,null,null,null);

        String name = ContactsContract.Contacts.DISPLAY_NAME;
        String key = ContactsContract.Contacts.LOOKUP_KEY;
        int displayNameIndex = cursor.getColumnIndex(name);
        int KeyIndex = cursor.getColumnIndex(key);
        for (cursor.moveToFirst();!cursor.isAfterLast();cursor.moveToNext()) {
            String displayName = cursor.getString(displayNameIndex);
            String Key = cursor.getString(KeyIndex);
            String displayPhone = getAllPhoneNumbers(Key);
            stringBuilder.append(displayName).append(" ").append(displayPhone).append("\n");
        }
        cursor.close();
        return stringBuilder.toString();
    }


}

(五)PersonDBOpenHelper

package com.example.demo6;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class PersonDBOpenHelper extends SQLiteOpenHelper {

    public PersonDBOpenHelper(Context context) {
        super(context,"info.db",null,1);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("create table info(_id integer primary key autoincrement,name varchar(50),phone varchar(20),UNIQUE(phone))");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }
}

(六)PersonProvider

package com.example.demo6;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

public class PersonProvider extends ContentProvider {

    private static UriMatcher mUriMatcher = new UriMatcher(-1);

    private static final int SUCCESS = 1;

    private PersonDBOpenHelper helper;

    static {
        mUriMatcher.addURI("com.example.test05_contentprovider.PersonProvider","info",SUCCESS);
    }

    @Override
    public boolean onCreate() {
        helper = new PersonDBOpenHelper(getContext());
        return false;
    }

    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
        int code = mUriMatcher.match(uri);
        if (code == SUCCESS) {
            SQLiteDatabase db = helper.getReadableDatabase();
            long rowId = db.insert("info",null,values);
            if (rowId>0) {
                Uri insertedUri = ContentUris.withAppendedId(uri,rowId);

                getContext().getContentResolver().notifyChange(insertedUri,null);
                return insertedUri;
            }
            db.close();
            return uri;
        }else {
            try {
                throw new IllegalAccessException("插入失败,路径不正确!");
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] strings, @Nullable String s, @Nullable String[] strings1, @Nullable String s1) {
        int code = mUriMatcher.match(uri);
        if (code == SUCCESS) {
            SQLiteDatabase db = helper.getReadableDatabase();
            return db.query("info",strings,s,strings1,null,null,s1);
        }else {
            try {
                throw new IllegalAccessException("查询失败,路径不正确!");
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {
        return null;
    }

    @Override
    public int update(@NonNull Uri uri, @Nullable ContentValues contentValues, @Nullable String s, @Nullable String[] strings) {

        int code = mUriMatcher.match(uri);
        if (code == SUCCESS) {
            SQLiteDatabase db = helper.getReadableDatabase();
            int count = db.update("info",contentValues,s,strings);
            if (count>0) {
                getContext().getContentResolver().notifyChange(uri,null);
            }
            db.close();
            return count;
        }else {
            try {
                throw new IllegalAccessException("更新失败,路径不正确!");
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return 0;
    }

    @Override
    public int delete(@NonNull Uri uri, @Nullable String s, @Nullable String[] strings) {
        int code = mUriMatcher.match(uri);
        if (code == SUCCESS) {
            SQLiteDatabase db = helper.getReadableDatabase();
            int count = db.delete("info",s,strings);
            if (count>0) {
                getContext().getContentResolver().notifyChange(uri,null);
            }
            db.close();
            return count;
        }else {
            try {
                throw new IllegalAccessException("删除失败,路径不正确!");
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return code;
    }
}

(七)SQLActivity

package com.example.demo6;

import android.Manifest;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class SQLActivity extends Activity {
    private final Uri uri = Uri.parse("content://com.example.test05_contentprovider.PersonProvider/info");
    private ContentValues values;
    private ContentResolver resolver;
    private EditText et_id;
    private EditText et_name;
    private EditText et_phone;
    private EditText et_queryAll;

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

        et_id = (EditText) findViewById(R.id.editText1);
        et_name = (EditText) findViewById(R.id.editText2);
        et_phone = (EditText) findViewById(R.id.editText3);
        et_queryAll = (EditText) findViewById(R.id.eT);
    }

    public String getAllPhoneNumbers(String lookUp_Key){
        StringBuilder allPhoneNo = new StringBuilder();
        String[] proj2 = {ContactsContract.CommonDataKinds.Phone.NUMBER};
        String selection = ContactsContract.Data.LOOKUP_KEY+"=?";
        String[] selectionArgs = {lookUp_Key};
        ContentResolver resolver = getContentResolver();
        Cursor cursor = resolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,proj2,selection,selectionArgs,null);
        while(cursor.moveToNext()){
            allPhoneNo.append(cursor.getString(0)).append(" ");
        }
        return allPhoneNo.toString();
    }

    public void btnCreate(View view) {

        PersonDBOpenHelper helper = new PersonDBOpenHelper(this);
        SQLiteDatabase db = helper.getWritableDatabase();
        resolver = getContentResolver();
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS)!= PackageManager.PERMISSION_GRANTED)
        {
            ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.READ_CONTACTS},1);
            Toast.makeText(this,"未允许读取通讯录权限!",Toast.LENGTH_SHORT).show();
        }
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS)== PackageManager.PERMISSION_GRANTED)
        {
            Cursor cursor = resolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                    null,null,null,null);
            String name = ContactsContract.Contacts.DISPLAY_NAME;
            String key = ContactsContract.Contacts.LOOKUP_KEY;
            int displayNameIndex = cursor.getColumnIndex(name);
            int KeyIndex = cursor.getColumnIndex(key);
            for (cursor.moveToFirst();!cursor.isAfterLast();cursor.moveToNext()) {
                String displayName = cursor.getString(displayNameIndex);
                String Key = cursor.getString(KeyIndex);
                String displayPhone = getAllPhoneNumbers(Key);
                values = new ContentValues();
                values.put("name",displayName);
                values.put("phone",displayPhone);
                db.insert("info",null,values);
            }
            cursor.close();
            db.close();
            btnQueryAll(view);
            Toast.makeText(this,"插入成功!",Toast.LENGTH_SHORT).show();

        }
    }

    public void btnAdd(View view) {
        resolver = getContentResolver();
        values = new ContentValues();
        if (et_name.length() != 0 && et_phone.length() != 0){
            values.put("name",et_name.getText().toString());
            values.put("phone",et_phone.getText().toString());
            Uri newUri = resolver.insert(uri,values);
            Toast.makeText(this,"增加成功",Toast.LENGTH_SHORT).show();
            btnQueryAll(view);
        } else {
            et_name.setHint("请在此输入需增加的姓名");
            et_phone.setHint("请在此输入需增加的号码");
        }
    }

    public void btnQuery(View view) {
        resolver = getContentResolver();
        if (et_name.length() != 0){
            Cursor cursor = resolver.query(uri,new String[]{"_id","name","phone"},"name=?",new String[]{et_name.getText().toString()},null);
            if (cursor.getCount() != 0){
                cursor.moveToFirst();
                et_id.setText(cursor.getString(0));
                et_name.setText(cursor.getString(1));
                et_phone.setText(cursor.getString(2));
                cursor.close();
            }
            else {
                Toast.makeText(this,"未查询到结果!",Toast.LENGTH_SHORT).show();
            }
        }
        else {
            et_name.setHint("请在此输入需查询的姓名");
            et_phone.setHint("号码");
        }
    }

    public void btnQueryAll(View view) {
        resolver = getContentResolver();

        List<Map<String,String>> data = new ArrayList<Map<String,String>>();
        Cursor cursor = resolver.query(uri,new String[]{"_id","name","phone"},null,null,null);
        while (cursor.moveToNext()){
            Map<String,String> map = new HashMap<String,String>();
            map.put("_id",cursor.getString(0));
            map.put("name",cursor.getString(1));
            map.put("phone",cursor.getString(2));
            data.add(map);
        }
        cursor.close();
        et_queryAll.setText(new String(data.toString()));
    }

    public void btnUpdate(View view) {
        resolver = getContentResolver();
        values = new ContentValues();
        if (et_name.length() != 0 && et_phone.length() != 0){
            values.put("phone",et_phone.getText().toString());
            int updateCount = resolver.update(uri,values,"name=?",new String[]{et_name.getText().toString()});
            Toast.makeText(this,"成功更新了" + updateCount + "条记录",Toast.LENGTH_SHORT).show();
            btnQueryAll(view);
        } else {
            et_name.setHint("请在此输入需修改的姓名");
            et_phone.setHint("请在此输入修改后的号码");
        }
    }

    public void btnDelete(View view) {
        resolver = getContentResolver();
        if (et_name.length() != 0){
            int deleteCount = resolver.delete(uri,"name=?",new String[]{et_name.getText().toString()});
            Toast.makeText(this,"成功删除了" + deleteCount + "条记录",Toast.LENGTH_SHORT).show();
            btnQueryAll(view);
        } else {
            et_name.setHint("请在此输入需删除的姓名");
            et_phone.setHint("号码");
        }
    }
}

(八)activity_main.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:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/toOne"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/toOne"
        android:onClick="toOne" />

    <Button
        android:id="@+id/toTwo"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/toTwo"
        android:onClick="toTwo" />

</LinearLayout>

(九)contentlayout.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:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ContentActivity">

    <TextView
        android:id="@+id/hint"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/hint"
        android:textSize="30sp" />

    <TextView
        android:id="@+id/callName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="20sp" />

</LinearLayout>

(十)sqllayout.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:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".SQLActivity">

    <EditText
        android:id="@+id/editText1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:hint="@string/id" />

    <EditText
        android:id="@+id/editText2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:hint="@string/name" />

    <EditText
        android:id="@+id/editText3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:hint="@string/phone" />

    <Button
        android:id="@+id/add"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/add"
        android:onClick="btnAdd" />

    <Button
        android:id="@+id/delete"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/delete"
        android:onClick="btnDelete" />

    <Button
        android:id="@+id/update"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/update"
        android:onClick="btnUpdate" />

    <Button
        android:id="@+id/query"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/query"
        android:onClick="btnQuery" />

    <Button
        android:id="@+id/addContent"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/addContent"
        android:onClick="btnCreate" />

    <Button
        android:id="@+id/queryAll"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/queryAll"
        android:onClick="btnQueryAll" />

    <EditText
        android:id="@+id/eT"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:layout_marginTop="15dp"
        android:layout_weight="1"
        android:gravity="start|top"
        android:inputType="textMultiLine" />

</LinearLayout>

(十一)strings.xml

<resources>
    <string name="app_name">test05_contentprovider</string>
    <string name="id">id</string>
    <string name="name">姓名</string>
    <string name="phone">号码</string>
    <string name="add">增加</string>
    <string name="delete">删除</string>
    <string name="update">修改</string>
    <string name="query">查询</string>
    <string name="addContent">插入通讯录数据</string>
    <string name="queryAll">查看所有数据</string>
    <string name="toOne">访问通讯录</string>
    <string name="toTwo">数据库</string>
    <string name="hint">读取到的联系人姓名 号码:</string>
</resources>

(十二)AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.demo6">

    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Demo6">
        <activity
            android:name="com.example.demo6.MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name="com.example.demo6.ContentActivity" />
        <activity android:name="com.example.demo6.SQLActivity" />

        <provider
            android:authorities="com.example.test05_contentprovider.PersonProvider"
            android:name="com.example.demo6.PersonProvider"
            android:exported="false" />
    </application>

</manifest>

三.运行部分

(一)打开Device Manager

(二)选择上次创建的虚拟机

(三)运行

(四)运行结果

四.ContentProvider

前言

ContentProvider是Android四大组件之一,另外三个是Activity、Service和Broadcast。它可以被其他应用程序调用,从而实现数据的共享和交互。

(一)ContentProvider基础介绍


1.1 简介

 ContentProvider是Android系统中的一个组件,用于在不同的应用程序之间共享数据。它提供了一种统一的接口,使得应用程序可以访问和修改其他应用程序中的数据,同时还可以对数据进行安全性和权限控制。

1.2 作用

实现进程间的数据交互 & 共享,即跨进程通信。
ContentProvider通常用于提供数据访问的接口,例如访问联系人信息、媒体文件、日历事件等。它可以将数据存储在SQLite数据库中,也可以通过其他方式进行数据存储。

1.ContentProvider=中间者角色(搬运工) 真正存储和操作数据的数据源还是原来存储数据的方式(数据库、文件、xml或网络)
2.数据源可以是:数据库(如Sqlite)、文件、XML、网络等等

1.3 实现原理

ContentProvider是通过Binder机制来实现跨进程通信的,它通过Binder对象来与其他应用程序或组件进行通信。当其他应用程序或组件通过ContentResolver请求数据时,ContentResolver会将请求转发给ContentProvider,而ContentProvider会通过Binder机制将数据返回给请求方。
Binder是什么呢? 浅浅的先了解一下
Binder是Android系统中用于实现跨进程通信的机制,它提供了一种轻量级的IPC(进程间通信)方式,可以实现进程间数据的传输和通信。ContentProvider利用Binder机制来实现数据共享和访问,保证了数据的安全性和权限控制。

(二)具体使用


2.1 统一资源标识符(URI)

ContentProvider使用 URI(统一资源标识符)来标识数据,每个数据都有一个唯一的URI来访问。当其他应用程序通过ContentResolver发起数据请求时,ContentProvider会根据请求的URI来匹配相应的数据,并返回给请求方。
定义:Uniform Resource Identifier,即统一资源标识符
作用:唯一标识 ContentProvider 其中的数据
外界进程通过 URI 找到对应的ContentProvider 其中的数据,再进行数据操作
URI分类:
URI分为 系统预置 & 自定义,分别对应系统内置的数据(如通讯录、日程表等等)和自定义数据库
系统预置URI可以在源码中找到,比如:

管理联系人的Uri:
ContactsContract.Contacts.CONTENT_URI 
管理联系人的电话的Uri:
ContactsContract.CommonDataKinds.Phone.CONTENT_URI 
管理联系人的Email的Uri:
ContactsContract.CommonDataKinds.Email.CONTENT_URI 
发送箱中的短信URI:
Content://sms/outbox
收信箱中的短信URI:
Content://sms/sent
草稿中的短信URI:
Content://sms/draft

自定义URI:
例如:
URl= content:// com.henry.provider/User/1

content: 主题名
com.henry.provider:授权信息
User:表名
1:记录

主题(Schema):ContentProvider的URI前缀(Android 规定)
授权信息(Authority):ContentProvider的唯一标识符·
表名(Path):ContentProvider指向数据库中的某个表名·
记录(ID):表中的某个记录(若无指定,则返回全部记录

具体使用

 设置URI
Uri uri = Uri.parse("content://com.henry.provider/User/1") 
上述URI指向的资源是:名为 `com.henry.provider`的`ContentProvider` 中表名 为`User` 中的 `id`为1的数据

特别注意:URI模式存在匹配通配符* & #
*:匹配任意长度的任何有效字符的字符串
以下的URI 表示 匹配provider的任何内容
content://com.example.app.provider/ *
#:匹配任意长度的数字字符的字符串
以下的URI 表示 匹配provider中的table表的所有行
content://com.example.app.provider/table/#

2.2 MIME数据类型

ContentProvider中的MIME类型用于标识数据的类型和格式,帮助客户端应用程序正确解析和处理数据。开发者在使用ContentProvider时需要注意正确指定数据的MIME类型,以确保数据能够被正确处理。

作用:指定某个扩展名的文件用某种应用程序来打开
如指定.html文件采用text应用程序打开、指定.pdf文件采用flash应用程序打开

2.2.1 MIME类型组成

每种MIME类型 由2部分组成 = 类型 + 子类型
MIME类型是 一个 包含2部分的字符串

text / html
// 类型 = text、子类型 = html
text/css
text/xml
application/pdf

2.2.2 常见的MIME类型 

在Android开发中,常见的MIME类型包括但不限于以下几种:

text/plain:纯文本数据
text/html:HTML格式数据
image/jpeg:JPEG格式图像数据
image/png:PNG格式图像数据
audio/mpeg:MP3格式音频数据
video/mp4:MP4格式视频数据
application/json:JSON格式数据
application/xml:XML格式数据

2.2.3 ContentProvider根据 URI 返回MIME类型 

ContentProvider.geType(uri) ;

2.2.4 类型分类

两种常见的MIME类型形式是单条记录和多条记录(集合)

单条记录形式(vnd.android.cursor.item/自定义):
用于表示返回的数据是单个记录(一行数据)。
MIME类型的格式为"vnd.android.cursor.item/自定义",其中"自定义"部分是开发者自定义的标识符,通常用于指示数据表的类型。
示例:vnd.android.cursor.item/vnd.example.contacts,表示返回的数据是单个联系人记录。
多条记录(集合)形式(vnd.android.cursor.dir/自定义):
用于表示返回的数据是多个记录(多行数据,集合)。
MIME类型的格式为"vnd.android.cursor.dir/自定义",其中"自定义"部分是开发者自定义的标识符,通常用于指示数据表的类型。
示例:vnd.android.cursor.dir/vnd.example.contacts,表示返回的数据是多个联系人记录的集合。

 2.3 ContentProvider三剑客

ContentProvider内容提供者
对外提供数据,其他应用可以通过ContentProvider对你应用中的数据进行添删改查
ContentResolver内容解析者
按一定规则访问内容提供者的数据
ContentObserver内容监听器
监听指定Uri引起的变化,当ContentObserver所观察的Uri发生变化时,便会触发

2.4 辅助工具类

Android 提供了3个用于辅助ContentProvide的工具类:

ContentUris
UriMatcher
ContentObserver

(三)总结

数据共享:ContentProvider提供了一种标准的接口,允许不同应用程序之间共享数据。通过ContentProvider,应用程序可以将自己的数据暴露给其他应用程序,实现数据的共享和交互。
访问控制:ContentProvider可以对数据进行访问控制,通过URI的权限控制和ContentProvider的权限设置,可以限制哪些应用程序可以访问数据,从而保护数据的安全性。
数据封装:ContentProvider可以将数据封装起来,隐藏数据的具体存储方式和结构,只提供统一的接口供其他应用程序访问。这样可以提高数据的安全性和保护数据的完整性。
数据变化通知:ContentProvider支持数据变化通知机制,可以通过ContentResolver注册ContentObserver监听数据的变化,当数据发生变化时,会及时通知监听者,实现数据的实时更新和同步。
访问简单和高效:
对比于其他对外共享数据的方式,数据访问方式会因数据存储的方式而不同:
采用 文件方式 对外共享数据,需要进行文件操作读写数据;
采用 Sharedpreferences 共享数据,需要使用sharedpreferences API读写数据
这使得访问数据变得复杂且难度大。
而采用ContentProvider方式,其 解耦了 底层数据的存储方式,使得无论底层数据存储采用何种方式,外界对数据的访问方式都是统一的,这使得访问简单 & 高效
如一开始数据存储方式 采用 SQLite 数据库,后来把数据库换成 MongoDB,也不会对上层数据ContentProvider使用代码产生影响

 


http://www.kler.cn/a/506428.html

相关文章:

  • redhat安装docker 24.0.7
  • 微软开源AI Agent AutoGen 详解
  • 《鸿蒙Next平台:决策树面对噪声数据的鲁棒性逆袭》
  • Flink链接Kafka
  • LabVIEW光流算法的应用
  • Python文件操作中编码解码问题
  • 人工智能任务19-基于BERT、ELMO模型对诈骗信息文本进行识别与应用
  • 【Java】—— 基于Websocket实现页面聊天效果
  • 数据结构学习记录-数据结构概念
  • mysql 快速转为 sqlalchemy 模型 文件
  • 2.5G交换机 TL-SE2420 简单开箱评测,16个2.5G电口+4个10G光口(SFP+)
  • 《Compact Convolutional Transformers:开启计算机视觉新篇》
  • 2025最新版Sublime Text 4安装使用指南
  • WordPress 中将站点从绑定的域名迁移到使用 IP 地址
  • MySQL8.0新特性
  • 于灵动的变量变幻间:函数与计算逻辑的浪漫交织(上)
  • Hive迁移,小表(10G以下的),分区快速修复批量脚本
  • 硬件学习笔记--31 IEC62053-21相关内容介绍
  • 基于代理的RAG实现-Agentic RAG
  • Kafka消息轨迹方案设计与实现
  • 新型智慧园区解决方案:AI赋能场景,核心架构全解析
  • 一个超级简单的清晰的LSTM模型的例子
  • (双系统)Ubuntu+Windows解决grub引导问题和启动黑屏问题
  • 记录一次RPC服务有损上线的分析过程
  • 2025年01月14日Github流行趋势
  • Elasticsearch容器启动报错:AccessDeniedException[/usr/share/elasticsearch/data/nodes];