内容提供者-自定义内容提供者
我们在学习广播的时候,我们首先是学习监听系统发出的广播,然后再去自定广播。而学习内容提供者的话,我们先学习自定义内容提供者,搞清楚了里面的来龙去脉,再去使用系统的内容提供者。
如何编写内容提供者呢?
- 编写一个类,继承ContentProvider
package com.sunofbeaches.contentproviderdemo.provider;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
public class UserProvider extends ContentProvider {
@Override
public boolean onCreate() {
return false;
}
@Nullable
@Override
public Cursor query(@NonNull Uri uri,@Nullable String[] projection,@Nullable String selection,
@Nullable String[] selectionArgs,@Nullable String sortOrder) {
return null;
}
@Nullable
@Override
public String getType(@NonNull Uri uri) {
return null;
}
@Nullable
@Override
public Uri insert(@NonNull Uri uri,@Nullable ContentValues values) {
return null;
}
@Override
public int delete(@NonNull Uri uri,@Nullable String selection,@Nullable String[] selectionArgs) {
return 0;
}
@Override
public int update(@NonNull Uri uri,@Nullable ContentValues values,@Nullable String selection,
@Nullable String[] selectionArgs) {
return 0;
}
}
- 注册内容提供者
四大组件都要进行注册的,就是告诉系统你有这么一个组件。四大组件都是由系统去创建的,而不是你自己创建的。
在application节点里:
<provider
android:name=".provider.UserProvider"
android:authorities="com.sunofbeaches.provider">
</provider>
name就是指向我们的Provider类 authorithies就是认证内容,一般呢我们用包名即可,系统源码也是这样的。具体它有什么用,我们后面会讲到。 可以多个,用分号隔开即可,eg:
<provider
android:name=".provider.UserProvider"
android:authorities="user;com.sunofbeaches.provider">
</provider>
但是,直接写user,是不是重复率高呀,所以一般用包名就好。
- 编写内容提供者里的匹配器
//定义一个uri的匹配器,UriMatcher.NO_MATCH,不匹配时的返回值
private static UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
static {
//com.sunofbeaches.provider,跟我们注册的地方一致即可,这样子才可以找到这里来嘛
//path:路径,一般来说指的是表名,这里我们只有一张表,可以null,后面我们去学习查询联系人的时候,就有多张表了。
//code:返回码,规则匹配上的结果码
sUriMatcher.addURI("com.sunofbeaches.provider",null,USER_ALL);
}
添加在provider里
- 实现内容提供者里的方法
这里的话我们先简单实现一下查询的方法,其他方法我们会在视频里
package com.sunofbeaches.contentproviderdemo.provider;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.sunofbeaches.contentproviderdemo.db.UserDatabaseHelper;
public class UserProvider extends ContentProvider {
private static final int USER_ALL = 1;
//定义一个uri的匹配器,UriMatcher.NO_MATCH,不匹配时的返回值
private static UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
private UserDatabaseHelper mUserDatabaseHelper;
static {
//com.sunofbeaches.provider,跟我们注册的地方一致即可,这样子才可以找到这里来嘛
//path:路径,一般来说指的是表名,这里我们只有一张表,可以null,后面我们去学习查询联系人的时候,就有多张表了。
//code:返回码,规则匹配上的结果码
sUriMatcher.addURI("com.sunofbeaches.provider",null,USER_ALL);
}
@Override
public boolean onCreate() {
mUserDatabaseHelper = new UserDatabaseHelper(getContext());
//true if the provider was successfully loaded, false otherwise
return true;
}
@Nullable
@Override
public Cursor query(@NonNull Uri uri,@Nullable String[] projection,@Nullable String selection,
@Nullable String[] selectionArgs,@Nullable String sortOrder) {
//匹配规则
int result = sUriMatcher.match(uri);
if(result == USER_ALL) {
//匹配成功
SQLiteDatabase db = mUserDatabaseHelper.getReadableDatabase();
Cursor cursor = db.query(UserDatabaseHelper.TABLE_NAME_USER,projection,selection,selectionArgs,null,null,sortOrder);
return cursor;
} else {
throw new IllegalArgumentException("参数非法.");
}
}
@Nullable
@Override
public String getType(@NonNull Uri uri) {
return null;
}
@Nullable
@Override
public Uri insert(@NonNull Uri uri,@Nullable ContentValues values) {
return null;
}
@Override
public int delete(@NonNull Uri uri,@Nullable String selection,@Nullable String[] selectionArgs) {
return 0;
}
@Override
public int update(@NonNull Uri uri,@Nullable ContentValues values,@Nullable String selection,
@Nullable String[] selectionArgs) {
return 0;
}
}
其他应用通过此内容提供者获取数据
创建一个新的android项目,这个简单咯!
我们主界面有一个按钮,点击按钮以后,就去获取前面我们写的内容提供者应用里的用户数据。
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:onClick="getUserData"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="获取远程用户数据信息"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
布局就有个按钮,然后一个点击事件
点击事件完后:
package com.sunofbeaches.providertestdemo;
import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void getUserData(View view) {
ContentResolver contentResolver = getContentResolver();
Uri uri = Uri.parse("content://com.sunofbeaches.provider");
Cursor cursor = contentResolver.query(uri,null,null,null,null);
String[] columnNames = cursor.getColumnNames();
for(String columnName : columnNames) {
Log.d(TAG,"field --- > " + columnName);
}
while(cursor.moveToNext()) {
Log.d(TAG,"-------------------------------------");
for(String columnName : columnNames) {
String value = cursor.getString(cursor.getColumnIndex(columnName));
Log.d(TAG,columnName + " === " + value);
}
Log.d(TAG,"-------------------------------------");
}
cursor.close();
}
}
ContentResolver contentResolver = getContentResolver();
ContentResolver 这个类里呢,有很多的方法,比如说,query,insert,deleted,update.
Uri uri = Uri.parse("content://com.sunofbeaches.provider");
这个URI,content是协议,约束,内容提供者的scheme就是这个。格式就这么定了。
com.sunofbeaches.provider 这个则是我们在注册内容提供者时写的
android:authorities="com.sunofbeaches.provider"
其实后面,还可以有内容 比如说,
Uri uri = Uri.parse("content://com.sunofbeaches.provider/user");
user是path,一般指我们的表,但是我们的例子里只有1个user表,所以不要也没关系。知道这个里的关系,就好。怎么定义,哪里使用。
其实还可以有其他内容,比如说:
Uri uri = Uri.parse("content://com.sunofbeaches.provider/user/8");
这里的8呢,一般指的是记录的ID,在数据库里有很多张表,每张表里有很多条记录。
好啦,把我们的程序跑起来,点击按钮以后结果如下:
好了,视频我们会详细一点给大家讲,然后接下来我们学习一下去获取系统自带的内容提供者里的内容。