009 Android之ContentProvider
文章目錄
- Android文件權限簡述
- ContentProvider 內容提供者
- ContentResolver
- URI
- 什么是URI
- URI示例
- URI和URL
- ContentProvider實例
- ContentProvider實例1
- ContentProvider實例2
Android文件權限簡述
關于Android中關于文件權限的具體解釋
drwxrwx-x第一位:-表示文件,d表示文件夾,l表示連接
二三四:所有者權限,即程序本身訪問文件或目錄的權限
五六七:所在群組的權限
八九十:其他用戶權限
r表示讀權限,w表示寫權限,x表示可執行權限,-表示沒有權限,用數字表示法:r=4,w=2,x=1,-=0
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-LAkutBXO-1623813168455)(009 Android之ContentProvider.assets/1623330084594.png)]
ContentProvider 內容提供者
ContentProvider 內容提供者是安卓中的四大組件之一,為什么需要ContentProvider?
- Android中的應用程序運行在不同的進程空間中,因此不同應用程序中的數據是不能夠直接訪問的
- 為了增強程序之前的數據共享能力,Android系統雖然提供了像SharedPrefences這類簡單的跨程序邊界的訪問方法,但這些方法都存在一定的局限性
ContentProvider提供了應用之間共享數據的方法,應用程序通過ContentProvider訪問數據而不需要關心數據具體的存儲及訪問過程,這樣既提高了數據的訪問效率,同時也保護了數據
Android系統中附帶的ContentProvider包括:
- Browser:存儲如瀏覽器的信息
- CallLog:存儲通話記錄等信息
- Contacts:存儲聯系人等信息
- MediaStore:存儲媒體文件的信息
- Settings:存儲設備的設置和首選項信息
關于ContentProvider數據集
ContentProvider數據集類似于數據庫的數據表,每行是一條記錄,每列具有相同的數據類型,如下所示
ContentResolver
應用程序使用ContentResolver對象,利用URI,才能訪問ContentProvider提供的數據集
URI
什么是URI
URI:通用資源標志符(Uniform Resource Identifer),用來定位遠程或本地的可用資源;URI的基本格式如下
content://<authority>/<data_path>/<id>- content 固定前綴
- authority 授權者名稱,用來確定具體由哪一個ContentProvider提供資源
- data_path 數據路徑,用來確定請求的是哪個數據集
- id 數據編號,用來匹配數據集中_ID字段的值,如果請求的數據不止一條則可以省略
URI示例
content://contacts/people/ 表示全部聯系人信息的URI content://contacts/people/1 表示ID=1的聯系人信息的URI原生寫法
content://com.android.contacts/contacts/常量寫法
ContactsContract.Contacts.CONTENT_URI由于URI比較長,而且容易寫錯,所以在Android中定義了一些輔助類和常量來代替這些字符串
URI和URL
在Android中廣泛應用URI,而不是URL。URL是標識資源的物理位置,相當于文件的路徑,例如:
http://www.163.com/logo.pngURI則是標識資源的邏輯位置,并不提供資源的具體位置。
比如說電話本中的數據,如果用URL來標識的話,可能會是一個很復雜的文件結構,而一旦文件的存儲路徑改變,URL也必須改動。
但如果是URI,則可以用諸如content://contacts/people/這樣容易記錄的邏輯地址來標識,而且并不需要關心文件的具體位置,即使文件位置改動也不需要做變化
ContentProvider實例
ContentProvider實例1
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-UYxXHIJS-1623813168464)(009 Android之ContentProvider.assets/1623412259686.png)]
首先創建一個ContentProvider
指定URI的路徑
@Overridepublic Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder) {// TODO: Implement this to handle query requests from clients.Log.d("GuiShou","ContentProvider::query");return null;}然后在query方法中輸出一條日志
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><Buttonandroid:id="@+id/btn1"android:text="訪問ContentProvider"android:onClick="btnOnclick"android:layout_width="match_parent"android:layout_height="wrap_content" /> </LinearLayout>然后編寫頁面文件,新增一個按鈕,用于訪問ContentProvider
public void btnOnclick(View view) {//獲取內容解析者ContentResolver resolver=getContentResolver();//創建URI對象Uri uri= Uri.parse("content://myContentProvider");//查詢if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {Cursor cursor= resolver.query(uri,null,null,null,null,null);Log.d("GuiShou","Cursor::"+cursor);}}編寫onClick方法,利用ContentResolver調用ContentProvider的resolver方法
按鈕點擊之后,ContentResolver會檢測URI所指向的ContentProvider是否存在;如果存在,則調用該ContentProvider的query方法。所以URI的路徑至關重要,如果不存在,則后面的代碼無法執行成功
ContentProvider實例2
基于上個實例的代碼,在自己的ContentProvider中訪問數據庫。首先需要準備數據
首先新建一個類名為DBHelper,繼承自SQLiteOpenHelper
public class DBHelper extends SQLiteOpenHelper {public DBHelper(@Nullable Context context) {super(context, "mydata.db", null, 1);}@Overridepublic void onCreate(SQLiteDatabase db) {//創建表db.execSQL("create table person(_id integer primary key autoincrement,name varchar(20))");}@Overridepublic void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {} }重寫三個函數,在onCreate函數中創建一個數據庫文件
private DBHelper mDBHelper; private SQLiteDatabase mDatabase;@Overridepublic boolean onCreate() {mDBHelper=new DBHelper(getContext());return true;}在MyContentProvider類內創建DBHelper對象,并在onCreate方法中進行初始化
public static UriMatcher sUriMatcher=new UriMatcher(UriMatcher.NO_MATCH);private static final String authority = "myContentProvider";private static final int PERSONS =0x111 ;private static final int PERSONS_ID = 0x222;static {//content://myContentProvider/personsUriMatcher.addURI(authority,"person",PERSONS);//content://myContentProvider/person/idsUriMatcher.addURI(authority,"person/#",PERSONS_ID);}接著創建一個UriMatcher,并新增兩個URI路徑
@Overridepublic Uri insert(Uri uri, ContentValues values) {// TODO: Implement this to handle requests to insert a new row.//獲取數據庫對象mDatabase=mDBHelper.getReadableDatabase();//插入values數據long id= mDatabase.insert("person",null,values);//返回組合好的URI對象://content://myContentProvider/person/return ContentUris.withAppendedId(uri,id);}完成MyContentProvider的insert方法
@Overridepublic Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder) {// TODO: Implement this to handle query requests from clients.Log.d("GuiShou","ContentProvider::query");//獲取數據庫對象mDatabase=mDBHelper.getReadableDatabase();//match方法返回的是addURI的第三個參數codeint code=sUriMatcher.match(uri);if (code==PERSONS) {return mDatabase.query("person",new String[]{"_id","name"},null,null,null,null,null);}else if (code==PERSONS_ID) {long id= ContentUris.parseId(uri);return mDatabase.query("person",new String[]{"_id","name"},"_id=?",new String[]{""+id},null,null,null);}return null;}完成MyContentProvider的query方法。現在在MyContentProvider中還沒有數據,我們需要在里面新增數據,查詢的時候才能顯示出來
<Buttonandroid:id="@+id/btn2"android:text="插入數據"android:onClick="btnOnclick2"android:layout_width="match_parent"android:layout_height="wrap_content" />xml中新增一個按鈕,用于插入數據
//插入數據按鈕public void btnOnclick2(View view) {//獲取內容解析者ContentResolver resolver=getContentResolver();//創建URI對象Uri uri= Uri.parse("content://myContentProvider");//創建數據for (int i = 0; i <100 ; i++) {ContentValues values=new ContentValues();values.put("_id",""+i);values.put("name","王大錘"+i);resolver.insert(uri,values);}Log.d("GuiShou","插入數據完成");}實現插入數據的onClick代碼
public void btnOnclick(View view) {//獲取內容解析者ContentResolver resolver=getContentResolver();//查詢Uri uri1= Uri.parse("content://myContentProvider/person");if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {Cursor cursor= resolver.query(uri1,null,null,null,null,null);Log.d("GuiShou","Cursor::"+cursor);while (cursor.moveToNext()){int id= cursor.getInt(0);String name=cursor.getString(1);Log.d("GuiShou","id:"+id+"name:"+name);}}}接著完成查詢數據的按鈕,到此所有代碼編寫完成。點擊插入數據按鈕,效果如圖:
執行流程首先會通過ContentResolver找到對應的uri,并執行ContentProvider里的insert方法,insert則調用DBHelper的onCreate創建數據庫
點擊查詢按鈕,可以看到剛剛被插入的數據
同樣是通過ContentResolver找到對應的uri,調用了ContentProvider的query方法查詢了所有person數據
總結
以上是生活随笔為你收集整理的009 Android之ContentProvider的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 008 Android之Service
- 下一篇: 010 Android之逆向入门