您的位置:首页 > 编程语言 > PHP开发

Content Provider(三) 自定义ContentProvider

2016-01-13 14:52 561 查看


自定义ContentProvider是要继承ContentProvider

1、定义合同类(Contract Class)

这个名字是我自己取的,可能翻译不到位 。这个就是用来提供外部接口的,像我们之前用的UserDictionary.WORD.Words 就是一个合同类

public class BookContract {
public static final String AUTHORITY = "com.ckt.myprovider.bookprovider";

public static final class ITBook implements BaseColumns {
public static final String ID = BaseColumns._ID;
public static final String TITLE = "_title";
public static final String AUTHOR = "_author";

public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/itbook");

public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.ckt.itbook";
public static final String CONTENT_ITME_TYPE = "vnd.android.cursor.item/vnd.ckt.itbook";

public static final String DEFAULT_SORT = TITLE + " asc";
}

}

AUTHORITY: 标准的构成是应用的包名+自定义Provider名子 ,如上面,包名为com.ckt.myprovider,自定义provider名子为bookprovider

ITBook : 这个类对应一个itbook表,实现BaseColumns是为了给这个表中加入一个BaseColumns_ID的列,这个对于ListView等等的来说是必须的,当然你也可以赋值"_id"

ID,TITLE,AUTHOR是表的列名

CONTENT_URI:标准构成为content:// + AUTHORITY + 表名 , 这个我们给表名取名为itbook

CONTENT_TYPE 和 CONTENT_ITEM_TYPE :  基本格式是type/subtype , 因为Android定义的MIME是自定义的符合运营商规定的MIME , 所以对于type

vnd.android.cursor.dir //for multiple rows
vnd.android.cursor.item //for single row


代码中的两行分别对应请求的是多行数据和单行数据

DEFAULT_SORT : 默认的排序 ,这里是按照title来排序 

2、定义继承自ContentProvider的provider

package com.ckt.myprovider.book;

import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;

import java.util.HashMap;
import java.util.StringTokenizer;

import dalvik.annotation.TestTarget;

public class BookProvider extends ContentProvider {

private ContentResolver mContentResolver;
private DBHelper mDBHelper;
private SQLiteDatabase mDatabase;
private static final int ITBOOK_LIST = 0;
private static final int ITBOOK_ITEM = 1;
private static UriMatcher mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
private static HashMap<String, String> mProjectionMap = new HashMap<>();

static {
mUriMatcher.addURI(BookContract.AUTHORITY, "itbook", ITBOOK_LIST);
mUriMatcher.addURI(BookContract.AUTHORITY, "itbook/#", ITBOOK_ITEM);

mProjectionMap.put(BookContract.ITBook.ID, BookContract.ITBook.ID);
mProjectionMap.put(BookContract.ITBook.TITLE, BookContract.ITBook.TITLE);
mProjectionMap.put(BookContract.ITBook.AUTHOR, BookContract.ITBook.AUTHOR);
}

public BookProvider() {
}

@Override
public boolean onCreate() {
Context context = getContext();
mContentResolver = context.getContentResolver();
mDBHelper = new DBHelper(context, DB_NAME, null, 1);
return true;
}

@Override
public String getType(Uri uri) {
switch (mUriMatcher.match(uri)) {
case ITBOOK_ITEM:
return BookContract.ITBook.CONTENT_TYPE;

case ITBOOK_LIST:
return BookContract.ITBook.CONTENT_ITME_TYPE;

default:
throw new UnsupportedOperationException("Not yet implemented");
}

}

@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
mDatabase = mDBHelper.getReadableDatabase();
SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
switch (mUriMatcher.match(uri)) {
case ITBOOK_ITEM:
long id = ContentUris.parseId(uri);
builder.setTables(DB_TABLE);
builder.setProjectionMap(mProjectionMap);
builder.appendWhere(BookContract.ITBook.ID + " = " + id);
break;

case ITBOOK_LIST:
builder.setTables(DB_TABLE);
builder.setProjectionMap(mProjectionMap);
break;

default:
throw new UnsupportedOperationException("Not yet implemented");
}
Cursor cursor = builder.query(mDatabase, projection, selection, selectionArgs, null, null, BookContract.ITBook.DEFAULT_SORT);
//data change ,notify uri
cursor.setNotificationUri(mContentResolver, uri);
return cursor;

}

@Override
public Uri insert(Uri uri, ContentValues values) {
mDatabase = mDBHelper.getReadableDatabase();
Uri mNewUri = null;
long id = 0;
switch (mUriMatcher.match(uri)) {
case ITBOOK_ITEM:
throw new IllegalArgumentException("Error Uri: " + uri);

case ITBOOK_LIST:
id = mDatabase.insert(DB_TABLE, null, values);
break;

default:
throw new UnsupportedOperationException("Not yet implemented");
}

//if successfully
if (id > 0) {
mNewUri = ContentUris.withAppendedId(uri, id);
}
//if error occurs
else {
throw new SQLiteException("Unable to insert");
}
//notify
mContentResolver.notifyChange(uri, null);
return mNewUri;
}

@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
mDatabase = mDBHelper.getWritableDatabase();
int count = 0;
switch (mUriMatcher.match(uri)) {
case ITBOOK_ITEM:
long id = ContentUris.parseId(uri);
selection = BookContract.ITBook.ID + " = " + id + " " + selection;
count = mDatabase.delete(DB_TABLE, selection, selectionArgs);
break;

case ITBOOK_LIST:
count = mDatabase.delete(DB_TABLE, selection, selectionArgs);
break;

default:
throw new UnsupportedOperationException("Not yet implemented");
}
//notify all uri
mContentResolver.notifyChange(uri, null);
//successfully count > 0 , or count =0
return count;
}

@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
mDatabase = mDBHelper.getWritableDatabase();
int count = 0;
switch (mUriMatcher.match(uri)){
case ITBOOK_ITEM:
long id = ContentUris.parseId(uri);
selection = BookContract.ITBook.ID + " = " + id + " " + selection;
count = mDatabase.update(DB_TABLE,values,selection,selectionArgs);
break;

case ITBOOK_LIST:
count = mDatabase.update(DB_TABLE,values,selection,selectionArgs);
break;

default:
throw new UnsupportedOperationException("Not yet implemented");
}
//notify all uris
mContentResolver.notifyChange(uri,null);
//successfully count > 0 . or count = 0
return count;
}

private static String DB_NAME = "book.db";
private static String DB_TABLE = "itbook";
private static final String SQL_CREATE = "create table " +
DB_TABLE +
" ( " +
BookContract.ITBook.ID + " integer primary key, " +
BookContract.ITBook.TITLE + " text not null, " +
BookContract.ITBook.AUTHOR + " text not null)";

private static class DBHelper extends SQLiteOpenHelper {

public DBHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
}

@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(SQL_CREATE);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("drop table if exists " + DB_TABLE);
onCreate(db);
}
}
}


onCreate():  这里面不要执行一些耗时的操作

getType() : 根据URI来决定返回单行的CONTENT_ITEM_TYPE还是多行的CONTENT_TYPE,为了识别URI, 用到了UriMatcher类

private static final int ITBOOK_LIST = 0;
private static final int ITBOOK_ITEM = 1;
private static UriMatcher mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

static {
mUriMatcher.addURI(BookContract.AUTHORITY, "itbook", ITBOOK_LIST);
mUriMatcher.addURI(BookContract.AUTHORITY, "itbook/#", ITBOOK_ITEM);
}


query():官方推荐用SQLiteQueryBuilder来构建查询。 在查询的最后要用cursor.setNotificationUri(mContentResolver, uri) 来通知监听uri的客户端来更新数据 ,如CursorLoader

insert(), update(), insert()最后都需要用mContentResolver.nofityChange(uri, null).

3.在Manifest文件中定义

<provider
android:name=".book.BookProvider"
android:authorities="com.ckt.myprovider.bookprovider"
android:enabled="true"
android:exported="true">
<grant-uri-permission android:path="/itbook"/>
</provider>
name和authorities不用说,enabled为true指的是允许系统去启动这个provider,exported为true是允许其它应用使用这个provider

4.使用自定义的Provider

package com.ckt.myprovider;

import android.annotation.TargetApi;
import android.app.AlertDialog;
import android.app.LoaderManager;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.CursorLoader;
import android.content.DialogInterface;
import android.content.Loader;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;
import android.widget.Toast;

import com.ckt.myprovider.book.BookContract;

import static android.widget.Toast.LENGTH_LONG;

public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor> {

private static final String TAG = "MainActivity";
private EditText mTitleEt, mAuthorEt;
private ContentResolver mContentResolver;
private LayoutInflater inflater;

private ListView mListView;
private SimpleCursorAdapter mAdapter;

private String[] mProjection = {
BookContract.ITBook.ID,
BookContract.ITBook.TITLE,
BookContract.ITBook.AUTHOR};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
init();

}

private void init() {
inflater = LayoutInflater.from(getApplicationContext());
mContentResolver = getContentResolver();
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
doInsert();
}
});

mTitleEt = (EditText) findViewById(R.id.book_title);
mAuthorEt = (EditText) findViewById(R.id.book_author);

mListView = (ListView) findViewById(R.id.listview);
mAdapter = new SimpleCursorAdapter(
getApplicationContext(),
R.layout.simple_item,
null,
new String[]{BookContract.ITBook.TITLE, BookContract.ITBook.AUTHOR},
new int[]{R.id.item_title, R.id.item_author},
0);
mListView.setAdapter(mAdapter);
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
final String author = ((TextView) view.findViewById(R.id.item_author)).getText().toString();
final String title = ((TextView) view.findViewById(R.id.item_title)).getText().toString();
View myView = inflater.inflate(R.layout.dialog, null);
final EditText mDialogAuthor = (EditText) myView.findViewById(R.id.book_author);
mDialogAuthor.setText(author);
final EditText mDialogTitle = (EditText) myView.findViewById(R.id.book_title);
mDialogTitle.setText(title);
builder.setTitle("Book")
.setView(myView)
//delete
.setNegativeButton("Delete", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
int count = mContentResolver.delete(
BookContract.ITBook.CONTENT_URI,
BookContract.ITBook.TITLE + "= ?",
new String[]{title}
);
if (count > 0) {
Toast.makeText(MainActivity.this, "Delete Successfully", LENGTH_LONG).show();
}
}
})
//update
.setPositiveButton("Update", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
ContentValues mUpdateValue = new ContentValues();
mUpdateValue.put(BookContract.ITBook.TITLE, mDialogTitle.getText().toString());
mUpdateValue.put(BookContract.ITBook.AUTHOR, mDialogAuthor.getText().toString());
int count = mContentResolver.update(
BookContract.ITBook.CONTENT_URI,
mUpdateValue,
BookContract.ITBook.TITLE + "=?",
new String[]{title}
);
if (count > 0) {
Log.d(TAG, "Update, count = " + count);
Toast.makeText(MainActivity.this, "Update Successfully", LENGTH_LONG).show();
}
}
})
//nothing
.setNeutralButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {

}
});
builder.create().show();
}
});

getLoaderManager().initLoader(0, null, this);
}

private void doInsert() {
String title = mTitleEt.getText().toString();
String author = mAuthorEt.getText().toString();
ContentValues mNewValues = new ContentValues();
mNewValues.put(BookContract.ITBook.TITLE, title);
mNewValues.put(BookContract.ITBook.AUTHOR, author);
Log.d(TAG, "title = " + title + " ,author = " + author);
if (!TextUtils.isEmpty(title) && !TextUtils.isEmpty(author)) {
Uri mNewUri = mContentResolver.insert(BookContract.ITBook.CONTENT_URI, mNewValues);
if (mNewUri != null) {
String id = mNewUri.getPathSegments().get(1);
long id1 = ContentUris.parseId(mNewUri);
Log.d(TAG, "Insert , id = " + id + " ,id1 = " + String.valueOf(id1));
mTitleEt.setText(null);
mAuthorEt.setText(null);
}
}
}

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
CursorLoader cursorLoader = new CursorLoader(
getApplicationContext(), BookContract.ITBook.CONTENT_URI,
mProjection,
null,
null,
BookContract.ITBook.DEFAULT_SORT
);
return cursorLoader;
}

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
mAdapter.swapCursor(data);
}

@Override
public void onLoaderReset(Loader<Cursor> loader) {
mAdapter.swapCursor(null);
}
}


说明一点问题:

在加载数据到ListView的Adapter中的时候 ,用的是Loader中的CursorLoader,因为如果数据量较大查询是非常耗时的,一般我们开辟新的线程,而且要监听数据的改变来做相应的改变

使用CursorLoader好处
(1)适用任何Activity和Fragment
(2)提供异步加载
(3)对数据源监测,数据改变了及时更新
(4)配置(如屏幕方向)改变时候 ,重新连接最后 一个Loader的游标 ,不用重新查询。

5. 外部应用访问ContentProvider权限定义

如果我们自己写个ContentProvider却又在自己的应用中用这个玩意 ,未免大材小用,直接用数据库就行,那么如何在外部的应用中访问呢。

首先,如果我们的自定义provider不定义读写权限的话,默认,外部应用是无法访问自己的provider的,这个大家可以自己试试。

那么问题来了,怎么定定义权限呢

在我们的provider应用的manifest文件中

<permission android:name="ckt.permission.READ_ITBOOK" />
<permission android:name="ckt.permission.WRITE_ITBOOK" />
这样我们就定义了向系统申请的权限
现在我来使用

<provider
android:name=".book.BookProvider"
android:authorities="com.ckt.myprovider.bookprovider"
android:writePermission="ckt.permission.WRITE_ITBOOK"
android:enabled="true"
android:exported="true"
android:readPermission="ckt.permission.READ_ITBOOK">
</provider>
writePermission和readPermission就是我们用的读写权限,这样一来,只要外部应用能申请了权限就可以用content uri来操作content provider了

6、外部应用访问自定义的provider

首先是拥有完全的权限

<uses-permission android:name="ckt.permission.READ_ITBOOK" />
<uses-permission android:name="ckt.permission.WRITE_ITBOOK" />

package com.ckt.readprovider;

import android.app.LoaderManager;
import android.content.CursorLoader;
import android.content.Loader;
import android.database.Cursor;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v4.widget.SimpleCursorAdapter;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.ListView;

public class MainActivity extends AppCompatActivity {
private ListView mListView;
private SimpleCursorAdapter mAdapter;
private String[] from = {BookContract.ITBook.TITLE, BookContract.ITBook.AUTHOR};
private int[] to = {R.id.item_title, R.id.item_author};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
mListView = (ListView) findViewById(R.id.listview);
mAdapter = new SimpleCursorAdapter(MainActivity.this, R.layout.simple_item, null, from, to, 0);
mListView.setAdapter(mAdapter);
getLoaderManager().initLoader(0, null, new LoaderManager.LoaderCallbacks<Cursor>() {
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
String[] projection = {BookContract.ITBook.ID, BookContract.ITBook.TITLE, BookContract.ITBook.AUTHOR};
CursorLoader cursorLoader = new CursorLoader(MainActivity.this,
BookContract.ITBook.CONTENT_URI,
projection,
null,
null,
BookContract.ITBook.DEFAULT_SORT
);
return cursorLoader;
}

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
mAdapter.swapCursor(data);
}

@Override
public void onLoaderReset(Loader<Cursor> loader) {
mAdapter.swapCursor(null);
}
});
}

}
这里也是用ListView和CursorLoader,基本没什么好说的。

有时候,我们不想把太多的数据暴露出去,我们只想提供某些数据给其它应用查询,那么怎么办呢,我们可以限制访问权限 ,只允许外部 应用访问特定的uri来查询数据

<provider
android:name=".book.BookProvider"
android:authorities="com.ckt.myprovider.bookprovider"
android:grantUriPermissions="true"
android:enabled="true"
android:exported="true">
<grant-uri-permission android:path="/itbook"/>
</provider>

我们这里不设置了读写权限 ,用grantUriPermission来定义可以授予uri临时的权限,而且我还定义了<grant-uri-permission>来决定哪个uri是我们才给授权 ,当然我写的例子中只有一个表格,如果我们还加了一个表authorInfo,这个作者信息,我们并不想公布,这样我们可以达到限制效果

而对于请求数据的应用,如果它们并不知道这个权限 ,也就没办法去申请这个权限了,只能通过有完全权限的应用来申请临时的uri权限,虽然申请到了这个uri权限 ,但是我们只能操作这个uri对应的数据 

先来看看效果



图上的效果是 , 我们这个应用没有在manifest文件中申请权限(可能我们并不知道有这个权限 ), 但是我们知道 readprovider这个应用有这个权限可以读取,我们可以向这个应用发送一个intent, 来得到一个临时的uri权限 ,进而操作这个uri来获取数据 ,但是这个readprovider只给了我们读的权限 ,所以我们又不能用这个uri来直接的update , delete, insert,这个时候 ,我们要启动这个readprovider一个界面 ,让用户自己操作这个界面 ,这样用户能看到,也保证了数据
的安全。

申请权限的应用tempermissionClient

package com.ckt.tempermissionclient;

import android.app.LoaderManager;
import android.content.ComponentName;
import android.content.CursorLoader;
import android.content.Intent;
import android.content.Loader;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v4.widget.SimpleCursorAdapter;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;

public class MainActivity extends AppCompatActivity {
private ListView mListView;
private SimpleCursorAdapter mAdapter;
private Button mBtGetTemPer, mBtUpdate;
private String[] from = {BookContract.ITBook.TITLE, BookContract.ITBook.AUTHOR};
private int[] to = {R.id.item_title, R.id.item_author};
private EditText mEtTitle,mEtAuthor;
private static Uri uri;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

mListView = (ListView) findViewById(R.id.listview);
mAdapter = new SimpleCursorAdapter(MainActivity.this, R.layout.simple_item, null, from, to, 0);
mListView.setAdapter(mAdapter);
mBtGetTemPer = (Button) findViewById(R.id.tem);
mBtGetTemPer.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction("ckt.action.gettempermission");
startActivityForResult(intent, 888);
}
});

mBtUpdate = (Button) findViewById(R.id.update);
mBtUpdate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
Bundle bundle = new Bundle();
bundle.putString("title",mEtTitle.getText().toString());
bundle.putString("author", mEtAuthor.getText().toString());
intent.putExtras(bundle);
intent.setAction("ckt.action.updatebook");
startActivityForResult(intent,886);
}
});

mEtTitle = (EditText) findViewById(R.id.book_title);
mEtAuthor = (EditText) findViewById(R.id.book_author);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == 666) {
Log.d("david", "requestcode == " + requestCode);
uri = data.getData();
getLoaderManager().initLoader(0, null, new LoaderManager.LoaderCallbacks<Cursor>() {
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
String[] projection = {BookContract.ITBook.ID, BookContract.ITBook.TITLE, BookContract.ITBook.AUTHOR};
CursorLoader cursorLoader = new CursorLoader(MainActivity.this, uri, projection, null, null, BookContract.ITBook.DEFAULT_SORT);
return cursorLoader;
}

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
mAdapter.swapCursor(data);
}

@Override
public void onLoaderReset(Loader<Cursor> loader) {
mAdapter.swapCursor(null);
}
});
}
}

@Override
protected void onStop() {
super.onStop();
getApplicationContext().revokeUriPermission(uri,Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
}


如上面gif图中描述的一样,这个不解释这代码了,我们看readprovider中的响应的activity
package com.ckt.readprovider;

import android.content.ContentValues;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class Main2Activity extends AppCompatActivity {
private String action;
private Button mBtUpdate;
private TextView mTvTitle,mTvAuthor;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
mTvTitle = (TextView) findViewById(R.id.read_title);
mTvAuthor = (TextView) findViewById(R.id.read_author);
Intent intent = getIntent();
action = intent.getAction();
if (("ckt.action.gettempermission").equals(action)) {
grantPermission();
} else if (("ckt.action.updatebook").equals(action)) {
Bundle bundle = getIntent().getExtras();
String title = bundle.getString("title");
String author = bundle.getString("author");
mTvTitle.setText(title);
mTvAuthor.setText(author);
}

mBtUpdate = (Button) findViewById(R.id.update);

mBtUpdate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (("ckt.action.updatebook").equals(action)) {
Log.d("david", "insert ~");
Bundle bundle = getIntent().getExtras();
String title = bundle.getString("title");
String author = bundle.getString("author");
if (!TextUtils.isEmpty(title) && !TextUtils.isEmpty(author)) {
ContentValues contentValues = new ContentValues();
contentValues.put(BookContract.ITBook.TITLE, title);
contentValues.put(BookContract.ITBook.AUTHOR, author);
Log.d("david", "title = " + title + " ,author = " + author);
Uri uri = getContentResolver().insert(BookContract.ITBook.CONTENT_URI, contentValues);
if(uri != null){
Log.d("david","insert successfully");
finish();
}
}
}
}
});
}

private void grantPermission() {
Uri uri = BookContract.ITBook.CONTENT_URI;
Intent intent = new Intent();
intent.setData(uri);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
grantUriPermission("com.ckt.tempermissionclient", uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
setResult(666, intent);
finish();
}

}


这个我们看下这个 grantPermission 里面有intent.setFlags 和 grantUriPermisson ,都是授予权限,那么有什么区别
intent.setFlags: 这个权限在请求权限的一方的任务栈消失之前,一直存在 ,也就是说重启或者用back button一把返回,会让这个任务栈消失,自然也就没有权限了,大家可以一起按返回的按钮,再进入应用就没有权限了

而这个grangUriPermission 就有点屌了, 它一定要手动去调用 Context.revokeUriPermission,才会释放uri权限 

好了,基本上自定义content provider的东西到这里都应用涉及到了,我搜了baidu和google搜了很多文章,我这个算是比较齐全的,不过我们google中搜索文章的时候 ,有人提了一个问题,这个问题是:我如何把内部存储中的文件提供给外部应用呢,于是我在我前往篇文章中就对ContentProvider的子类FileProvider做了介绍,如果有兴趣大家可以去看下。  

我写的文章可能会很粗糙,但是要点都到位了,如果有什么不不到位 的地方 ,大家可以指出来,互相交流互相学习~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息