268.Android基礎之ContentProvider(AS)

ContentProvider是Android的四大組件之一,主要用於跨進程通信

ContentProvider的作用

  1. 使用現有的內容提供者來讀取和操作相應程序中的數據
  2. 創建自己的內容提供者給自己程序的數據提供外部訪問接口。

統一資源標識符(URI)

就像訪問網站需要域名一樣,Android中用內容URI給內容提供者中的數據建立了唯一標識符。它主要由三部分組成:協議聲明、authority和path。

Android中規定URI以“content:”開頭,代表協議聲明。
authority表示授權信息,用於對不同應用程序進行區分,爲了避免衝突,一般都採用程序包名的方式來命名。
path表示表名,用於對同一應用程序中不同的表進行區分,通常會添加到authority後面。
authorities是內容提供者的地址,通過這個地址可以訪問內容提供者,精確的知道訪問的是哪一個內容提供者
exported:可以導出數據,獲取到數據

Uri後面添加參數來進一步限定訪問哪一個數據表,比如下面的Uri是com.ldw.po限定訪問的是po表

Uri.parse("content://com.ldw.po/po")

AndroidManifist.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.ldw.a19contpro">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <provider
            android:name=".MyProvider"
            android:authorities="com.ldw.mypo"
            android:enabled="true"
            android:exported="true"></provider>

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

使用現有的ContentProvider比如讀取所有的短信

List<Message> smsList;
public void click1(View v){
        //訪問內容提供者
        ContentResolver cr = getContentResolver();
        //根據源代碼,查詢所有的信息不需要匹配參數,裏面還有其他的參數,例如inbox,sent,draft等等
        //短信內容提供者的主機名Uri:sms
        Cursor cursor = cr.query(Uri.parse("content://sms"), new String[]{"address", "date", "body", "type"}, null, null, null);
        while(cursor.moveToNext()){
            String address = cursor.getString(0);
            long date = cursor.getLong(1);
            String body = cursor.getString(2);
            String type = cursor.getString(3);

            Message sms = new Message(address, date, body, type);
            smsList.add(sms);
            System.out.println(address + ";" + date + ";" + body + ";" + type);
        }
    }

ContentResolver類

首先說一個問題,爲什麼要使用通過ContentResolver類從而與ContentProvider類進行交互,而不直接訪問ContentProvider類呢?

一個APP可能會有多個ContentProvider,若需要了解每個ContentProvider的不同實現從而再完成數據交互,
那整個操作過程也太複雜了,耦合高不利於擴展。因此Android單獨設計了一個 ContentResolver類對所有的
ContentProvider進行統一管理。

ContentResolver類裏常用的就四大方法:增、刪、改、查,emmm有種數據庫的感覺。其實確實和數據庫操作很像。

自定義ContentProvider

1.手動創建數據庫MyOpenHelper.java

package com.ldw.a19contpro;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import androidx.annotation.Nullable;

/**
 * author: ldw
 * created on: 2019/12/28 20:08
 * description:
 */
public class MyOpenHelper extends SQLiteOpenHelper {

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

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        sqLiteDatabase.execSQL("create table so(_id integer primary key autoincrement, name char(10), money integer(20))");
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {

    }
}

2.自定義 ContentProvider 類

這一步主要是通過繼承ContentProvider類,來實現自己的ContentProvider的邏輯。
在Android Studio中,可以直接用右鍵New->Other->Content Provider的方式來創建自定義ContentProvider。

App1:

Manifist.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.ldw.a19contpro">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <provider
            android:name=".MyProvider"
            android:authorities="com.ldw.mypo"
            android:enabled="true"
            android:exported="true"></provider>

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

MyOpenHelper.java

package com.ldw.a19contpro;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import androidx.annotation.Nullable;

/**
 * author: ldw
 * created on: 2019/12/28 20:08
 * description:
 */
public class MyOpenHelper extends SQLiteOpenHelper {

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

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        sqLiteDatabase.execSQL("create table so(_id integer primary key autoincrement, name char(10), money integer(20))");
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {

    }
}

MyProvider.java內容提供者

package com.ldw.a19contpro;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;

public class MyProvider extends ContentProvider {
    private MyOpenHelper my;
    SQLiteDatabase db;
    public MyProvider() {
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        // Implement this to handle requests to delete one or more rows.
        int i = db.delete("so", selection, selectionArgs);
        return i;
    }

    @Override
    public String getType(Uri uri) {
        // TODO: Implement this to handle requests for the MIME type of the data
        // at the given URI.
        return null;
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        // TODO: Implement this to handle requests to insert a new row.
        db.insert("so", null, values);
        return uri;
    }

    @Override
    public boolean onCreate() {
        // TODO: Implement this to initialize your content provider on startup.
        my = new MyOpenHelper(getContext(), "so.db", null, 1);
        db = my.getWritableDatabase();
        return false;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
                        String[] selectionArgs, String sortOrder) {
        // TODO: Implement this to handle query requests from clients.
        Cursor cursor = db.query("so", projection, selection, selectionArgs, null, null, sortOrder, null);
        return cursor;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection,
                      String[] selectionArgs) {
        // TODO: Implement this to handle requests to update one or more rows.
        int i = db.update("so", values, selection, selectionArgs);
        return i;
    }
}

MainActivity.java創建數據庫

package com.ldw.a19contpro;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        MyOpenHelper myOpenHelper = new MyOpenHelper(this, "so.db", null, 1);
        myOpenHelper.getWritableDatabase();
    }
}

App2

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical"
    >

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="插入"
        android:onClick="insert"
        />
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="刪除"
        android:onClick="delete"
        />
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="修改"
        android:onClick="update"
        />
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="查詢"
        android:onClick="query"
        />
</LinearLayout>

MainActivity.java

package com.ldw.a17contentvisitor;

import androidx.appcompat.app.AppCompatActivity;

import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void insert(View v){
        ContentResolver cr = getContentResolver();
        ContentValues contentValues = new ContentValues();
        contentValues.put("name", "AAA");
        contentValues.put("money", "25000");
        cr.insert(Uri.parse("content://com.ldw.mypo"), contentValues);
        contentValues.put("name", "BBB");
        contentValues.put("money", "15000");
        //Uri前面必須帶前綴,是內容提供者的地址
        cr.insert(Uri.parse("content://com.ldw.mypo"), contentValues);
        contentValues.put("name", "CCC");
        contentValues.put("money", "15000");
        //Uri前面必須帶前綴,是內容提供者的地址
        cr.insert(Uri.parse("content://com.ldw.mypo"), contentValues);
        contentValues.put("name", "DDD");
        contentValues.put("money", "15000");
        //Uri前面必須帶前綴,是內容提供者的地址
        cr.insert(Uri.parse("content://com.ldw.mypo"), contentValues);
    }

    public void delete(View v){
        ContentResolver contentResolver = getContentResolver();
        int i = contentResolver.delete(Uri.parse("content://com.ldw.mypo"), "name = ?", new String[]{"AAA"});
        System.out.println("刪除的行是===" + i);
    }

    public void update(View v){
        ContentResolver contentResolver = getContentResolver();
        ContentValues contentValues = new ContentValues();
        contentValues.put("money", "25000");
        int i = contentResolver.update(Uri.parse("content://com.ldw.mypo"), contentValues,"name = ?", new String[]{"CCC"});
        System.out.println("編輯的行是===" + i);
    }

    public void query(View v){
        ContentResolver contentResolver = getContentResolver();
        Cursor cursor = contentResolver.query(Uri.parse("content://com.ldw.mypo"), null, null, null, null);
        while (cursor.moveToNext()) {
            String name = cursor.getString(1);
            String money = cursor.getString(2);
            System.out.println("name===" + name + "; money===" + money);
        }
    }
}

 

發佈了474 篇原創文章 · 獲贊 78 · 訪問量 25萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章