文章目录
Uri
介绍
统一资源标识符(URI)是一种用于标识资源的字符串。它可以是一个网址、文件路径、或其他形式的资源定位符。在Android中,URI通常用于访问内容提供者(Content Provider)提供的数据。
举例:
-
获取设备上存储的所有图片
javacontent://media/internal/images
-
获取设备上所有联系人信息
javacontent://contacts/people/
-
获取ID为45的单个联系人信息
javacontent://contacts/people/45
在Java中,可以通过Uri.parse
方法将字符串URI转换为Uri对象。
java
Uri uri = Uri.parse("content://contacts/people/45");
组成
- Scheme :
- 采用前缀
content://
,表示这是一个内容提供者的Uri
。 - 例如:
content://
- 采用前缀
- Authority :
- 通常采用应用程序的包名,这样可以确保其唯一性。
- 例如:
com.example.provider
- Path :
- 指定数据或资源的路径,可以包含具体的表名、资源名以及其他标识符。
- 例如:
/student/1
ContentResolver
ContentResolver
是 Android 框架提供的一个类,用于与内容提供者(Content Provider)交互,提供了一系列增删改查的方法对数据进行操作,这些方法以Uri
的形式对外提供数据
用法
ContentResolver
为应用程序提供了统一的接口来访问不同的ContentProvider
获取对象
使用getContentResolver()
方法获取ContentResolver
对象:
java
ContentResolver contentResolver = getContentResolver();
增删改查
-
增
javaUri insert(Uri uri, ContentValues values);
插入新数据,并返回新插入数据的URI。
ContentValues
对象,包含了要插入的数据键值对
-
删
javaint delete(Uri uri, String selection, String[] selectionArgs);
删除匹配条件的数据,并返回删除的行数。
selection
: SQLWHERE
子句的筛选条件(不包括WHERE
关键字)。用来确定哪些行会被删除。selectionArgs
: 选择条件的参数数组。用于替代selection
中占位符(?
)
-
改
javaint update(Uri uri, ContentValues values, String selection, String[] selectionArgs);
更新匹配条件的数据,并返回更新的行数。
-
查
javaCursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder);
查询数据,并返回一个
Cursor
对象。projection
: 指定你要返回的列。如果你想返回所有列,可以传入null
。sortOrder
: 指定排序的方式。
读取联系人
获取通讯录的数据
使用 ContentResolver
来访问系统通讯录中的数据
获取权限
在AndroidMainfest获取权限
java
<uses-permission android:name="android.permission.READ_CONTACTS" />
配置ListView
在MainActivity中配置ListView
java
public class MainActivity extends AppCompatActivity {
// ArrayAdapter用于在ListView中显示联系人列表
ArrayAdapter<String> adapter;
// 存储联系人名称和电话号码的列表
List<String> contactsList = new ArrayList<>();
// 获取ListView
private ListView listView;
// 设置布局,请求权限,初始化ListView和Adapter。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = findViewById(R.id.contacts_view);
adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, contactsList);
listView.setAdapter(adapter);
// 检查是否已经获得了读取联系人的权限
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
// 如果没有,请求该权限
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS}, 1);
} else {
// 如果已经获得,直接读取联系人
readContacts();
}
}
// 没有权限弹出对话框:如果权限被授予,读取联系人;否则显示提示信息
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
// 检查是否是READ_CONTACTS权限的请求结果
if (requestCode == 1) {
// 检查权限是否被授予
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// 如果被授予,读取联系人
readContacts();
} else {
// 如果未被授予,显示提示信息
Toast.makeText(this, "联系人权限获取失败", Toast.LENGTH_SHORT).show();
}
}
}
// 查询并读取设备上的联系人列表。将查询结果添加到contactsList中,并更新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()) {
// 获取联系人名称和电话号码的列索引
int nameIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME);
int numberIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
// 检查列索引是否有效
if (nameIndex != -1 && numberIndex != -1) {
// 获取联系人名称和电话号码
String displayName = cursor.getString(nameIndex);
String number = cursor.getString(numberIndex);
// 将名称和号码组合后添加到列表
contactsList.add(displayName + "\n" + number);
}
}
// 更新Adapter以显示新的联系人列表
adapter.notifyDataSetChanged();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭Cursor,释放资源
if (cursor != null) {
cursor.close();
}
}
}
}
ContentProvider
内容提供者(Content Provider)是 Android 四大组件之一(Activity、Service、Broadcast Receiver、Content Provider)。它用于在不同的应用之间共享数据,尤其是在进程间通信(IPC)中起着关键作用。内容提供者通过一层中介来控制数据访问,从而确保隐私数据的安全性。
内容提供者本身并不直接存储数据,它只是定义了数据的访问接口。数据的实际存储方式包括文件存储,SharedPreferences 存储,SQLite 数据库存储
方法
创建一个自定义的 ContentProvider
类继承ContentProvider
涉及实现一些关键的方法
onCreate()
方法:用于初始化ContentProvider
通常会执行一些初始化操作,比如设置数据库的连接等getType()
方法:返回给定Uri
的 MIME 类型,以便系统知道如何处理数据insert()
方法:用于向ContentProvider
中插入数据update()
方法:用于更新ContentProvider
中的数据delete()
方法:用于删除ContentProvider
中的数据query()
方法:用于查询ContentProvider
中的数据
步骤
1、注册
创建一个ContentProvider
类,as会自动在AndroidManifest.xml
中注册
xml
<provider
android:name=".MyContentProvider"
android:authorities="com.example.sqlitedatabasepractice_731"
android:enabled="true"
android:exported="true"></provider>
2、继承
继承了ContentProvider,得到了6个要重写的方法
onCreate
java
private SQLiteDatabase db;
// 初始化
public boolean onCreate() {
// 这里是根据自定义的UserDBHelper类的自定义构造方法创建一个UserDBHelper类的对象
// 然后调用其方法获取SQLiteDatabase类的对象
UserDBHelper dbHelper = new UserDBHelper(getContext());
db = dbHelper.getWritableDatabase();
return true;
}
UriMatcher
用于根据 URI 来匹配请求,帮助
ContentProvider
解析 URI,并确定应该执行的操作或返回的数据
java
// UriMatcher用于URI的匹配
private static UriMatcher uriMatcher;
// 静态代码块,初始化 UriMatcher 实例和添加匹配规则
static {
// 为UriMatcher添加匹配规则
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
// 添加匹配规则,匹配所有以 BASE_PATH 结尾的 URI
uriMatcher.addURI(AUTHORITY, BASE_PATH, USER_DIR);
// 添加匹配规则,匹配以 BASE_PATH 结尾,后跟一个 ID 的 URI
uriMatcher.addURI(AUTHORITY, BASE_PATH + "/#", USER_ITEM);
}
insert
java
public Uri insert(Uri uri, ContentValues values) {
// 插入一条新记录
long id = db.insert(UserDBHelper.TABLE_NAME, null, values);
// 构造新记录的URI并用来返回
Uri insertedUri = Uri.withAppendedPath(CONTENT_URI, String.valueOf(id));
return insertedUri;
}
delete
java
public int delete(Uri uri, String selection, String[] selectionArgs) {
int match = uriMatcher.match(uri);
int count = 0;
switch (match) {
case USER_DIR:
// 删除满足条件的所有记录
count = db.delete(UserDBHelper.TABLE_NAME, selection, selectionArgs);
break;
case USER_ITEM:
// 删除指定ID的记录
String id = uri.getLastPathSegment();
count = db.delete(UserDBHelper.TABLE_NAME, "id = ?", new String[]{id});
break;
}
return count;
}
update
java
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
int count = 0;
switch (uriMatcher.match(uri)) {
case USER_DIR:
// 更新满足条件的所有记录
count = db.update(UserDBHelper.TABLE_NAME, values, selection, selectionArgs);
break;
case USER_ITEM:
// 更新指定ID的记录
String id = uri.getLastPathSegment();
count = db.update(UserDBHelper.TABLE_NAME, values, "id = ?", new String[]{id});
break;
}
return count;
}
query
java
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
Cursor cursor = null;
switch (uriMatcher.match(uri)) {
case USER_ITEM:
// 查询指定ID的记录
String id = uri.getLastPathSegment();
cursor = db.query(UserDBHelper.TABLE_NAME, projection, "id = ?", new String[]{id}, null, null, sortOrder);
break;
case USER_DIR:
// 查询所有记录
cursor = db.query(UserDBHelper.TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder);
break;
}
return cursor;
}
getType
java
public String getType(Uri uri) {
// MINE类型说明
// 字符串取值,让ANDROID系统知道处理的是整体数据还是单条数据
// 特点:1.以vnd开头
// 2.如果Uri以路径形式结尾,后面接android.cursor.dir/,返回的是整个数据表的MIME类型
// 如果Uri以ID形式结尾,后面接android.cursor.item/,返回的是单个数据项的MIME类型
// 3.最后接的内容是: vnd.<authority>.<path>
switch (uriMatcher.match(uri)) {
case USER_DIR:
// 返回整个数据表的MIME类型
return "vnd.android.cursor.dir/vnd." + AUTHORITY + "." + BASE_PATH;
case USER_ITEM:
// 返回单个数据项的MIME类型
return "vnd.android.cursor.item/vnd." + AUTHORITY + "." + BASE_PATH;
default:
return null;
}
}
ContentProvider与ContentResolver
++
ContentResolver
间接调用ContentProvider
++++
ContentProvider
操作自己的DataBase数据库++
ContentResolver
间接调用 ContentProvider
:
ContentResolver
是用于访问和管理数据的工具,它将操作请求(如insert()
,update()
,delete()
,query()
)发送到对应的ContentProvider
。ContentResolver
通过URI
定位到具体的ContentProvider
,并调用其方法来执行实际的数据操作。
ContentProvider
操作自己的数据库:
ContentProvider
实现了对数据的 CRUD 操作,它会直接与应用程序的数据库进行交互,执行插入、更新、删除和查询等操作。ContentProvider
在这些操作中使用数据库访问对象(如SQLiteDatabase
),并根据URI
和其他参数来确定需要操作的数据。
比如:
delete()
方法处理删除请求,通过ContentResolver
转发到具体的ContentProvider
实现,执行删除操作并返回删除的记录数。当你在自定义的
ContentProvider
中实现delete()
方法时,它需要接收来自其他应用程序通过ContentResolver
传递的删除请求。你需要根据传递的 ++URI 和选择条件删除数据库中的记录++ ,并返回++删除的记录数++
ContentProvider` 实现了对数据的 CRUD 操作,它会直接与应用程序的数据库进行交互,执行插入、更新、删除和查询等操作。
ContentProvider
在这些操作中使用数据库访问对象(如SQLiteDatabase
),并根据URI
和其他参数来确定需要操作的数据。
比如:
delete()
方法处理删除请求,通过ContentResolver
转发到具体的ContentProvider
实现,执行删除操作并返回删除的记录数。当你在自定义的
ContentProvider
中实现delete()
方法时,它需要接收来自其他应用程序通过ContentResolver
传递的删除请求。你需要根据传递的 ++URI 和选择条件删除数据库中的记录++ ,并返回++删除的记录数++
感谢您的阅读
如有错误烦请指正