日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

android uri db,Android ContentProvider封装数据库和文件读写总结

發布時間:2023/12/2 Android 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android uri db,Android ContentProvider封装数据库和文件读写总结 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文是我各處東拼西湊加上自己實現一個ContentProvider的使用總結,留做后用,主要介紹ContentProvider的集成方法。

一、綜述

ContentProvider是Android四大組件之一,其核心功能是提供應用間的統一的數據訪問方式,當然也可以用于應用內的數據封裝。ContentProvider類似C/S結構,應用A實現ContentProvider向外提供應用內的數據訪問,應用B使用Context.getContentResolver()來間接與應用A的Provider交互。

ContentProvider提供一套類似數據庫的query/delete/insert/update的方法來操作數據,開發者可以以此來屏蔽管理數據的真正方式 (SharePreference/File/SQLite等)。另外,ContentProvider也提供了直接操作文件的方式(覆寫openFile),第三方應用可以通過該方式讀寫當前應用的私有文件(data/data等)。

二、相關知識

2.1 UriMatcher和ContentUris的使用

UriMatcher主要用戶判斷Uri是否符合特定格式,用法如下:

private static final int TYPE_ALL = 1;

private static final int TYPE_SINGLE = 2;

private static UriMatcher mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

static {

mUriMatcher.addURI(AUTHORITY, "person", TYPE_ALL);

mUriMatcher.addURI(AUTHORITY, "person/#", TYPE_SINGLE);//#號表示一個數字

}

以上為其聲明與配置,下面是使用方法:

switch (mUriMatcher.match(uri)) {

case TYPE_ALL:

//uri匹配到第一種類型

case TYPE_SINGLE:

//uri匹配到第二種類型

default:

//uri沒有匹配到這兩種類型

}

這樣我們就可以知道外部傳入的Uri的類型了。

2.2 ContentUris用法

ContentUris用于處理Uri后面的id部分(純數字),常用函數有:

parseId(uri): 解析Uri里的最后的id

withAppendedId(uri, id):在路徑后面加上id部分

三、封裝ContentProvider的步驟

提供Provider的工程簡稱應用A。下面是封裝ContentProvider的步驟:

3.1 在Manifest中聲明ContentProvider:

android:authorities="org.test.auth"

android:exported="true"/>

聲明后,應用安裝到設備上第三方應用就能通過ContentResolver訪問此Provider。

3.2 ContentProvider的代碼

package org.test.auth;

import java.io.File;

import java.io.FileNotFoundException;

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 android.os.ParcelFileDescriptor;

import android.text.TextUtils;

import android.util.Log;

public class MyDataProvider extends ContentProvider {

private static final String AUTHORITY = "org.test.auth";

private static final int TYPE_ALL = 1;

private static final int TYPE_SINGLE = 2;

private static final String TAG = "TEST111_DataProvider";

private MyDBHelper mDbHelper;

private SQLiteDatabase mDatabase;

private static UriMatcher mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

static {

mUriMatcher.addURI(AUTHORITY, "person", TYPE_ALL);

mUriMatcher.addURI(AUTHORITY, "person/#", TYPE_SINGLE);

}

@Override

public int delete(Uri uri, String selection, String[] selectionArgs) {

switch (mUriMatcher.match(uri)) {

case TYPE_ALL:

return mDatabase.delete(MyDBHelper.TABLE_NAME,

selection,

selectionArgs);

case TYPE_SINGLE:

long id = ContentUris.parseId(uri);

String where = MyDBHelper.COLUMN_ID + " = " + id;

if(!TextUtils.isEmpty(selection)) {

where = where + " and " + selection;

}

return mDatabase.delete(MyDBHelper.TABLE_NAME,

where,

selectionArgs);

default:

return -1;

}

}

@Override

public String getType(Uri uri) {

switch (mUriMatcher.match(uri)) {

case TYPE_ALL:

return "vnd.android.cursor.dir/person";

case TYPE_SINGLE:

return "vnd.android.cursor.item/person";

default:

return null;

}

}

@Override

public Uri insert(Uri uri, ContentValues values) {

//由于此時的values中具體是否含有數據是不確定的,所以此時需要在第二個參數中添加person表中的非主鍵的一列

long id = mDatabase.insert(MyDBHelper.TABLE_NAME, MyDBHelper.COLUMN_NAME, values);

return ContentUris.withAppendedId(uri, id);

}

@Override

public boolean onCreate() {

mDbHelper = new MyDBHelper(getContext());

mDatabase = mDbHelper.getWritableDatabase();

return true;

}

@Override

public Cursor query(Uri uri, String[] columns,

String selection, String[] selectionArgs,

String orderBy) {

switch (mUriMatcher.match(uri)) {

case TYPE_ALL:

return mDatabase.query(MyDBHelper.TABLE_NAME, columns, selection, selectionArgs, null, null, orderBy);

case TYPE_SINGLE:

long id = ContentUris.parseId(uri);

String where = MyDBHelper.COLUMN_ID + " = " + id;

if(!TextUtils.isEmpty(selection)) {

where = where + " and " + selection;

}

return mDatabase.query(MyDBHelper.TABLE_NAME, columns, where, selectionArgs, null, null, orderBy);

default:

return null;

}

}

@Override

public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {

switch (mUriMatcher.match(uri)) {

case TYPE_ALL:

return mDatabase.update(MyDBHelper.TABLE_NAME, values,

selection, selectionArgs);

case TYPE_SINGLE:

long id = ContentUris.parseId(uri);

String where = MyDBHelper.COLUMN_ID + " = " + id;

if(!TextUtils.isEmpty(selection)) {

where = where + " and " + selection;

}

return mDatabase.update(MyDBHelper.TABLE_NAME, values,

where, selectionArgs);

default:

return -1;

}

}

@Override

public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {

File root = new File(getContext().getFilesDir() + "/" + uri.getPath());

root.getParentFile().mkdirs();

int imode = 0;

if (mode.contains("w")) {

imode |= ParcelFileDescriptor.MODE_WRITE_ONLY;

if (!root.exists()) {

try {

root.createNewFile();

} catch (Exception ex) {

Log.d(TAG, "error happened", ex);

}

}

}

if (mode.contains("r")) imode |= ParcelFileDescriptor.MODE_READ_ONLY;

if (mode.contains("+")) imode |= ParcelFileDescriptor.MODE_APPEND;

return ParcelFileDescriptor.open(root, imode);

}

}

此示例中使用的數據操作方式是數據庫,onCreate執行ContentProvider啟動時的初始化操作,query/insert/delete/update操作數據,getType返回指定Uri對應的數據類型。“vnd.android.cursor.dir”表示cursor集合,“vnd.android.cursor.item”表示cursor條目。

覆寫openFile方法提供私有文件的對外訪問,在該方法內可以控制是否提供文件讀寫,本例代碼來自網絡,支持讀寫操作。

附上數據庫幫助類代碼:

package org.test.auth;

import android.content.Context;

import android.database.sqlite.SQLiteDatabase;

import android.database.sqlite.SQLiteOpenHelper;

public class MyDBHelper extends SQLiteOpenHelper {

public static final String DB_NAME = "test.db";

public static final String TABLE_NAME = "person";

public static final String COLUMN_ID = "_id";

public static final String COLUMN_AGE = "age";

public static final String COLUMN_NAME = "name";

public static final int DB_VERSION = 1;

public MyDBHelper(Context context) {

super(context, DB_NAME, null, DB_VERSION);

}

@Override

public void onCreate(SQLiteDatabase database) {

String sql = "create table if not exists " + TABLE_NAME + "( " +

COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +

COLUMN_NAME +" varchar(100), " +

COLUMN_AGE + " integer" +

" )" ;

database.execSQL(sql);

}

@Override

public void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion) {

}

}

四、測試代碼

測試代碼在另一個工程中,簡稱應用B。

package com.example.testcontentprovider;

import java.io.BufferedReader;

import java.io.BufferedWriter;

import java.io.FileNotFoundException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.OutputStream;

import java.io.OutputStreamWriter;

import android.app.Activity;

import android.content.ContentResolver;

import android.content.ContentValues;

import android.database.Cursor;

import android.net.Uri;

import android.os.Bundle;

import android.os.ParcelFileDescriptor;

import android.util.Log;

public class MainActivity extends Activity {

private static final String URI = "content://org.test.auth/person";

private static final String TAG = "TEST111_";

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

doTest();

}

private void doTest() {

ContentResolver cr = getContentResolver();

String typeAll = cr.getType(Uri.parse(URI));

Log.d(TAG, "get all type= " + typeAll);

String typeOne = cr.getType(Uri.parse(URI + "/1"));

Log.d(TAG, "get one type= " + typeOne);

insertValue(cr, "張三", 12);

insertValue(cr, "李四", 23);

//查詢所有數據

query(cr, -1);

//查詢單條數據

query(cr, 1);

//更改id=1的數據

updateValue(cr, 1, "王五", 20, null, null);

//查詢所有數據

query(cr, -1);

//更改name=李四的數據

updateValue(cr, 2, "哈哈", 34, "name=?", new String[] {"李四"});

//查詢所有數據

query(cr, -1);

//更改所有數據

updateValue(cr, -1, "小明", 15, null, null);

//查詢所有數據

query(cr, -1);

//刪除id=1數據

int affectedColumnCountOne = cr.delete(Uri.parse(URI + "/1"), null, null);

Log.d(TAG, "delete one affectedColumnCount= " + affectedColumnCountOne);

//查詢所有數據

query(cr, -1);

//刪除所有數據

int affectedColumnCountAll = cr.delete(Uri.parse(URI), null, null);

Log.d(TAG, "delete all affectedColumnCount= " + affectedColumnCountAll);

//查詢所有數據

query(cr, -1);

//測試文件讀寫

try {

OutputStream os = cr.openOutputStream(Uri.parse(URI+"/provider_file.txt"));

BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));

bw.append("think who am I?!");

bw.flush();

bw.close();

InputStream is = cr.openInputStream(Uri.parse(URI+"/provider_file.txt"));

BufferedReader br = new BufferedReader(new InputStreamReader(is));

String result = br.readLine();

br.close();

Log.d(TAG, "read file result : " + result);

} catch (Exception e) {

Log.d(TAG, "file op failed", e);

}

}

private void query(ContentResolver cr, int id) {

String idCause = "";

if(id >= 0) {

idCause = "/" + id;

}

Cursor cursorResultAll = cr.query(Uri.parse(URI + idCause), null, null, null, null);

if(null != cursorResultAll) {

while(cursorResultAll.moveToNext()) {

int result = cursorResultAll.getInt(0);

String name = cursorResultAll.getString(1);

int age = cursorResultAll.getInt(2);

Log.d(TAG, "query()| originid= " + id +"; id = " + result + " name= " + name + " age= " + age);

}

}

}

private void insertValue(ContentResolver cr, String name, int age) {

ContentValues value = new ContentValues();

value.put("name", name);

value.put("age", age);

Uri insertColumn = cr.insert(Uri.parse(URI), value);

Log.d(TAG, "insertValue() insert at column: " + insertColumn);

}

private void updateValue(ContentResolver cr, int id, String name, int age,

String selection, String[] selectionArgs) {

if (id >= 0) {

ContentValues value = new ContentValues();

value.put("name", name);

value.put("age", age);

int affectedColumnCount = cr.update(Uri.parse(URI + "/" + id), value, selection, selectionArgs);

Log.d(TAG, "updateValue() affectedColumnCount: " + affectedColumnCount);

} else {

ContentValues value = new ContentValues();

value.put("name", name);

value.put("age", age);

int affectedColumnCount = cr.update(Uri.parse(URI), value,

selection, selectionArgs);

Log.d(TAG, "updateValue() affectedColumnCount: " + affectedColumnCount);

}

}

}

以上,就是實現一個ContentProvider的方法,后續需要補充ContentProvider的原理部分,據說進程間通信是基于共享內存的,以后有時間需要分析一下。

總結

以上是生活随笔為你收集整理的android uri db,Android ContentProvider封装数据库和文件读写总结的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。