安卓第十四天筆記-內容提供者(ContentProvider)

来源:http://www.cnblogs.com/liunanjava/archive/2016/03/15/5236852.html
-Advertisement-
Play Games

ContentProvider是不同應用程式之間進行數據交換的一種方式或者稱標準API. http://www.qq.com:80/news.jsp ContentProvider要求的;Uri與上面類似   在AndroidManifest.xml中註冊ContentProvider,指定 建立一


安卓第十四天筆記-內容提供者(ContentProvider)

ContentProvider--內容提供者

1.ContentProvider簡介

ContentProvider是不同應用程式之間進行數據交換的一種方式或者稱標準API.

  • ContentProvider以某種Uri的方式對外提供數據,允許其他應用訪問或者修改數據
  • 其它的程式根據Uri去訪問操作指定的數據

2.Uri簡介

http://www.qq.com:80/news.jsp

  • http://:URL的協議部分,只要通過HTTP協議來訪問網路,這具部分是固定的.如FTP
  • www.qq.com:功能變數名稱部分
  • news.jsp:網站資源部分,訪問不能的資源這具部分是不同的,這個部分是動態的

ContentProvider要求的;Uri與上面類似

 content://com.pc.pp.provider/words

 

  • content://這個Android的ContentProvider規定的,就像預設的http://,ContentProvider的協議預設就是Content://
  • com.pc.pp.provider:這部分就是ContentProvider的authorities.系統就是由這具部分來找到操作哪個ContentProvider的.只要訪問指定的ContentProvider,這個部分是固定的
  • words:資源部分或者數據

3.建立ContentProvider

  1. 寫一個類繼承ContentProvider重寫query,insert,update,delete,getType等方法
  2. 在AndroidManifest.xml中註冊ContentProvider,指定

      android:authorities屬性  //這個給其它應用程式使用的
    

建立一個數據幫助類

public class BankSqliteOpenHelper extends SQLiteOpenHelper {

    public BankSqliteOpenHelper(Context context) {
        super(context, "bank.db", null, 1);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        String sql = "create table account(_id integer primary key, name varchar(30),money double)";
        db.execSQL(sql);

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {


    }

}

 

建立一個ContentProvider

  /**
本地資料庫的內容提供者,

@author 劉楠 *

2016-3-2下午8:35:19 */ public class BankDbProvider extends ContentProvider {

private static final String TAG = "BankDbProvider";

private static final int ACCOUNT = 0;

private static final int ACCOUNT_ID = 1;
//預設匹配,不能匹配就執行UriMatcher.NO_MATCH
private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
//資料庫操作類
private BankSqliteOpenHelper helper;

/**
 * 初始始化一些可以匹配的URI
 */
static {

    matcher.addURI("com.itheima.bankdb.BankDbProvider", "account", ACCOUNT);
    matcher.addURI("com.itheima.bankdb.BankDbProvider", "account/#",
            ACCOUNT_ID);

}

/**
 * 這個Provider被創建時執行,做一些初始始化操作
 */
@Override
public boolean onCreate() {

    helper = new BankSqliteOpenHelper(getContext());
    return true;
}

/**
 * 查詢操作
 */
@Override
public Cursor query(Uri uri, String[] projection, String selection,
        String[] selectionArgs, String sortOrder) {

    if (matcher.match(uri) == ACCOUNT) {

        SQLiteDatabase db = helper.getReadableDatabase();
        Cursor cursor = db.query("account", projection, selection,
                selectionArgs, null, null, sortOrder);
        return cursor;
    } else if (matcher.match(uri) == ACCOUNT_ID) {

        SQLiteDatabase db = helper.getReadableDatabase();
        long id = ContentUris.parseId(uri);
        Cursor cursor = db.query("account", null, "_id=?",
                new String[] { id + "" }, null, null, sortOrder);
        return cursor;
    } 
    return null;
}

/**
 * 返回類型,主要針對查詢操作
 * vnd.android.cursor.dir:表示返回多條數據
 * vnd.android.cursor.item:表示返回一條數據
 */
@Override
public String getType(Uri uri) {

    if (matcher.match(uri) == ACCOUNT) {
        return "vnd.android.cursor.dir/account";
    } else if (matcher.match(uri) == ACCOUNT_ID) {

        return "vnd.android.cursor.item/account";
    }

    return null;
}

/**
 * 插入操作
 */
@Override
public Uri insert(Uri uri, ContentValues values) {

    if (matcher.match(uri) == ACCOUNT) {

        SQLiteDatabase db = helper.getWritableDatabase();
        long insert = db.insert("account", null, values);

        db.close();
    }
    return uri;

}

/**
 * 刪除操作
 */
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {

    if (matcher.match(uri) == ACCOUNT) {

        SQLiteDatabase db = helper.getWritableDatabase();

        int delete = db.delete("account", selection, selectionArgs);

        db.close();
        return delete;
    }
    return 0;
}

/**
 * 更新操作
 */
@Override
public int update(Uri uri, ContentValues values, String selection,
        String[] selectionArgs) {

    if (matcher.match(uri) == ACCOUNT) {

        SQLiteDatabase db = helper.getWritableDatabase();
        int update = db.update("account", values, selection, selectionArgs);
        db.close();
        return update;
    }
    return 0;
   }

 }

 

在清單文件中註冊這個provider

<!-- 註冊Provider 
    authorities:對外暴露的訪問路徑
    -->
    <provider
        android:name="com.itheima.bankdb.provider.BankDbProvider"
        android:authorities="com.itheima.bankdb.BankDbProvider" >
    </provider>

 

authorities :可以隨便定義,建立使用包名.Provider

4.訪問這個應用程式的Provider

新建一個應用

ContentResolver resolver = getContentResolver();
使用這個對象來實現對象Privoider的解析
/**
 * 插入數據
 * 
 * @param v
 */
public void insert(View v) {
    ContentResolver resolver = getContentResolver();

    Uri uri = Uri.parse("content://com.itheima.bankdb.BankDbProvider/account");
    ContentValues values = new ContentValues();
    values.put("name", "lisi");
    values.put("money", 503.3);
    Uri insert = resolver.insert(uri, values);
    System.out.println("insert:"+insert);
}

/**
 * 更新
 * 
 * @param v
 */
public void update(View v) {
    ContentResolver resolver = getContentResolver();

    Uri uri = Uri.parse("content://com.itheima.bankdb.BankDbProvider/account");
    ContentValues values = new ContentValues();
    values.put("money", 1003.3);

    int update = resolver.update(uri, values, "name=?", new String[]{"lisi"});
    System.out.println("update"+update);
}

/**
 * 刪除
 * 
 * @param v
 */
public void delete(View v) {
    ContentResolver resolver = getContentResolver();

    Uri uri = Uri.parse("content://com.itheima.bankdb.BankDbProvider/account");

    int delete = resolver.delete(uri, "name=?", new String[]{"lisi"});
    System.out.println("delete:"+delete);
}

/**
 * 查詢全部
 * 
 * @param v
 */
public void query(View v) {
    ContentResolver resolver = getContentResolver();

    Uri uri = Uri.parse("content://com.itheima.bankdb.BankDbProvider/account");
    Cursor cursor = resolver.query(uri, null, null, null, null);

    while(cursor.moveToNext()){
        int id=cursor.getInt(cursor.getColumnIndex("_id"));
        String name = cursor.getString(cursor.getColumnIndex("name"));

        double money =cursor.getDouble(cursor.getColumnIndex("money"));
        Toast.makeText(this, "ID:"+id+"姓名:"+name+",Money:"+money, Toast.LENGTH_SHORT).show();

    }
    cursor.close();
}

/**
 * 查詢一個
 * 
 * @param v
 */
public void queryOne(View v) {
    ContentResolver resolver = getContentResolver();

    Uri uri = Uri.parse("content://com.itheima.bankdb.BankDbProvider/account/2");
    Cursor cursor = resolver.query(uri, null, null, null, null);

    while(cursor.moveToNext()){
        int id=cursor.getInt(cursor.getColumnIndex("_id"));
        String name = cursor.getString(cursor.getColumnIndex("name"));

        double money =cursor.getDouble(cursor.getColumnIndex("money"));
        Toast.makeText(this, "ID:"+id+"姓名:"+name+",Money:"+money, Toast.LENGTH_SHORT).show();

    }
    cursor.close();
}

 

5.使用簡訊的內容提供者

向簡訊中添加一條數據

    /**
 * 像簡訊中添加一條數據
 * @param v
 */
public void insert(View v){
    //獲取內容解析都
    ContentResolver resolver = getContentResolver();
    //查看源碼中找到提供的uri
    Uri uri =Uri.parse("content://sms");
    //要添加的數據就是一個MAP集合,對應的數據表的欄位
    ContentValues values = new ContentValues();
    values.put("address", "10086");
    values.put("date", System.currentTimeMillis());
    values.put("body", "這是一條新的簡訊");
    values.put("type", 1);
    resolver.insert(uri, values);

}

 

添加許可權

  <uses-permission android:name="android.permission.READ_SMS"/>
    <uses-permission android:name="android.permission.WRITE_SMS"/>

 

6.使用聯繫人ContentProvider

查詢聯繫人

    /**
 * 查詢所有聯繫人,
 * @param context
 * @return
 */
public static List<ContactInfo>  getContacts(Context context){
    List<ContactInfo> list = new ArrayList<ContactInfo>();
    Uri rowUri = Uri.parse("content://com.android.contacts/raw_contacts");
    Uri dataUri = Uri.parse("content://com.android.contacts/data");

    ContentResolver resolver = context.getContentResolver();

    Cursor rawCursor = resolver.query(rowUri, new String[]{"contact_id"}, null, null, null);
    while(rawCursor.moveToNext()){
        String id =rawCursor.getString(rawCursor.getColumnIndex("contact_id"));
        if(id==null){
            continue;
        }
        ContactInfo info = new ContactInfo();
        info.id=id;
        Cursor dataCursor= resolver.query(dataUri, new String[]{"data1","mimetype"}, "raw_contact_id=?", new String[]{id}, null);
        while(dataCursor.moveToNext()){
            String data1=dataCursor.getString(dataCursor.getColumnIndex("data1"));
            String mimetype=dataCursor.getString(dataCursor.getColumnIndex("mimetype"));

            if("vnd.android.cursor.item/email_v2".equals(mimetype)){
                info.email=data1;
            }else if("vnd.android.cursor.item/im".equals(mimetype)){
                info.im=data1;
            }else if("vnd.android.cursor.item/phone_v2".equals(mimetype)){
                info.phone=data1;
            }else if("vnd.android.cursor.item/name".equals(mimetype)){
                info.name=data1;
            }
        }
        dataCursor.close();
        list.add(info);
    }
    rawCursor.close();
    return list;
}

 

添加聯繫人

    /**
 * 添加聯繫人
 * 
 * @param v
 */
public void insert(View v) {
    String name = etName.getText().toString().trim();
    String phone = etPhone.getText().toString().trim();
    String email = etEmail.getText().toString().trim();

    if (TextUtils.isEmpty(name) || TextUtils.isEmpty(phone)
            || TextUtils.isEmpty(email)) {
        Toast.makeText(this, "名字,電話,郵件不能為空", Toast.LENGTH_SHORT).show();
        return;
    }

    Uri rowUri = Uri.parse("content://com.android.contacts/raw_contacts");
    Uri dataUri = Uri.parse("content://com.android.contacts/data");
    // 先查詢ID
    ContentResolver resolver = getContentResolver();

    Cursor rawCursor = resolver.query(rowUri, new String[] { "_id" }, null,
            null, null);
    rawCursor.moveToLast();
    int id = 1;
    id = rawCursor.getInt(rawCursor.getColumnIndex("_id")) + 1;
    rawCursor.close();
    // 插入raw_contact表ID
    ContentValues values = new ContentValues();
    values.put("contact_id", id);
    resolver.insert(rowUri, values);
    // 向data表中插入數據
    ContentValues nameValues = new ContentValues();
    nameValues.put("data1", name);
    nameValues.put("mimetype", "vnd.android.cursor.item/name");
    nameValues.put("raw_contact_id", id);
    resolver.insert(dataUri, nameValues);

    ContentValues phoneValues = new ContentValues();
    phoneValues.put("data1", phone);
    phoneValues.put("mimetype", "vnd.android.cursor.item/phone_v2");
    phoneValues.put("raw_contact_id", id);
    resolver.insert(dataUri, phoneValues);

    ContentValues emailValues = new ContentValues();
    emailValues.put("data1", email);
    emailValues.put("mimetype", "vnd.android.cursor.item/email_v2");
    emailValues.put("raw_contact_id", id);
    resolver.insert(dataUri, emailValues);

    Toast.makeText(this, "添加成功", Toast.LENGTH_SHORT).show();
}

 

添加許可權

<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>    

 

7.內容觀察者

ContentObserver 觀察某一個路徑的數據, 某個指定的數據,一旦數據發生了變化,那麼將會收到通知

作用: 資料庫的數據發生變化之後,會發佈一個通知出來,我們收到通知之後,再去查詢資料庫,即可得到最新的數據

發佈通知
    //參數一: 具體是什麼位置的數據發生了改變
        //參數二:具體的內容觀察者對象, 如果是null , 那麼表明不告訴具體的某一個人,
        getContext().getContentResolver().notifyChange(uri, null);

 


收到通知
    //註冊內容觀察者

    Uri uri = Uri.parse("content://com.itheima.bank.BACKDOOR/account");
    //參數一: 觀察的具體位置 ,uri
    //參數二: true : uri只要匹配前半段,也能收到通知, false . 所有的字母都全部匹配才能收到通知
    getContentResolver().registerContentObserver(uri, true, new MyObserver(new Handler()));

    ----------------------

    class MyObserver extends ContentObserver{

        public MyObserver(Handler handler) {
            super(handler);
        }

        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);
            Log.d(TAG, "表數據發生了改變..");
        }
    }

 

 

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 當內容及分類較多時,往往採用頂部標簽式導航欄,例如網易新聞客戶端的頂部分類導航,最近剛好有這樣的應用場景,參考網路上一些demo,實現了這種導航效果,記錄一些要點。 效果圖(由於視頻轉GIF掉幀,滑動和下拉動畫顯得比較生硬,剛發現quickTime可以直接錄製手機視頻,推薦一下,很方便) 其實就是在
  • Android應用檢查版本更新後,在通知欄下載,更新下載進度,下載完成自動安裝,效果圖如下: AndroidManifest文件中的versionCode用來標識版本,在伺服器放一個新版本的apk,versioncode大於當前版本,下麵代碼用來獲取versioncode的值 用當前versionc
  • 有時候我們在頁面跳轉的時候回傳遞相應的參數,如,你想把在第一個頁面的文本框里的內容顯示在第二個文本框中,或者你又想把第二個文本框中的內容改變之後到第一個頁面的文本框中,所有,這個時候我們就要用到頁面跳轉傳值 屬性傳值是正向傳值,只可以從前面一個頁面傳遞到第二個頁面,不可以從第二個頁面傳遞到第一個頁面
  • 在一些場景中,需要限制用戶的輸入字數,例如在textField里進行控制(textView也類似,崩潰原因也相同),如圖所示 系統會監聽文本輸入,需要註意的第一點是輸入法處於聯想輸入還未確定提交的時候,對於第三方輸入法例如搜狗,聯想狀態下的輸入,是監聽不到,除非點擊確定輸入到textField,才會
  • 單機搭建Android開發環境四,介紹了基於64位Ubuntu 12.04 Server版安裝git、repo、編譯環境,從內部伺服器下載Android5.1代碼並編譯測試。
  • 第二個界面中的lable顯示第一個界面textField中的文本 首先我們建立一個RootViewControllers和一個DetailViewControllers,在DetailViewControllers中聲明一個textString屬性,用於接收傳過來的字元串, RootViewCont
  • 面向對象編程進階和字元串 Δ一.類的設計模式—單例 【單例】程式允許過程中,有且僅有一塊記憶體空間存在,這種類的設計模式成為單例 【問】什麼時候用到單例 【答】數據共用的時候 1.單例的書寫格式 以+(加號)開頭的方法,可以直接被類調用;-(減號)開頭方法 ,是對象方法,用對象來調用; 2.認識單例
  • 首先創建2個新界面 , 然後創建一個類,如下圖   然後在AppDeleate.h   然後在AppDeleate.m中  然後進入AppStatus.h    AppStatus.m   FirstViewController.h中    FirstViewController.m中   Seco
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...