1. 程式人生 > >[安卓基礎]學習第九天

[安卓基礎]學習第九天

一、為什麼需要內容提供者

1-1.回憶定義資料庫

  1. 新建一個類繼承SQLiteOpenHelper
public class MyOpenHelper extends SQLiteOpenHelper {

    public MyOpenHelper(Context context) {
        super(context, "test.db", null, 1);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("create table info(_id integer primary key autoincrement,name varchar(20),money varchar(20))"
); db.execSQL("insert into info(name,money) values(?,?)", new String[]{"張三","5000"}); db.execSQL("insert into info(name,money) values(?,?)", new String[]{"李四","3000"}); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // TODO Auto-generated method stub
} }
  1. 開啟資料庫
MyOpenHelper myOpenHelper = new MyOpenHelper(this);

        SQLiteDatabase db = myOpenHelper.getWritableDatabase();
  1. 讀取資料庫
    Cursor cursor = db.query("info", null, null, null, null, null, null);
    if (cursor != null && cursor.getCount() > 0) {
        while
(cursor.moveToNext()) { String name = cursor.getString(1); String phone = cursor.getString(2); System.out.println("___" + name + ": " + phone); } }
  1. chmod linux下修改文改檔案的許可權

二、內容提供者的原理

image

- 內容提供者把資料進行封裝,其他應用都是用過內容解析者來訪問
- 定義內容提供者,定義一個類繼承ContentProvider

三、實現內容提供者的步驟

  1. 定義一個類繼承ContentProvider
public class TestdbProvider extends ContentProvider {

    @Override
    public boolean onCreate() {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
            String[] selectionArgs, String sortOrder) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public String getType(Uri uri) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection,
            String[] selectionArgs) {
        // TODO Auto-generated method stub
        return 0;
    }

}
  1. 在清單檔案進行配置
    <provider
        android:name="com.elnui.day09_db.TestdbProvider"
        android:authorities="com.elnui.testdbprovider"
        android:exported="true"
        android:enabled="true">
    </provider>
  1. 寫一個靜態程式碼塊,新增匹配規則
    static
    {
        /**
         * authority 和清單檔案裡面定義的要一樣
         * path 任意的路徑
         * 
         * com.elnui.provider/query
         * */
        sUriMather.addURI("com.elnui.provider", "query", QUERY_SUCCESS);
    }

[完整的TestdbProvider類程式碼]

public class TestdbProvider extends ContentProvider {

    // 定義一個urimatcher,路徑匹配器
    private static final UriMatcher sUriMather = new UriMatcher(UriMatcher.NO_MATCH);

    private static final int QUERY_SUCCESS = 1;

    private MyOpenHelper myOpenHelper;

    // 定義靜態程式碼塊,新增匹配規則,規則可以多個
    static
    {
        /**
         * authority 和清單檔案裡面定義的要一樣
         * path 任意的路徑
         * 
         * com.elnui.provider/query
         * */
        sUriMather.addURI("com.elnui.testdbprovider", "query", QUERY_SUCCESS);
    }

    @Override
    public boolean onCreate() {
        myOpenHelper = new MyOpenHelper(getContext());
        return false;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
            String[] selectionArgs, String sortOrder) {

        int code = sUriMather.match(uri);
        if(code == QUERY_SUCCESS){  // 說明路徑匹配成功
            /**
             *  資料庫的查詢
             * */
            SQLiteDatabase db = myOpenHelper.getReadableDatabase();

            /**
             * table 表名
             * columns 查詢的列,由引數String[] projection給出
             * selection 查詢的條件
             * selectionArgs 查詢的條件引數
             * */
            Cursor cursor = db.query("info", projection, selection, selectionArgs, null, null, sortOrder);

            // 注意,這裡的Cursor不能關
            return cursor;
        }else{
            throw new IllegalArgumentException("路徑不匹配,請檢查");
        }
    }

    @Override
    public String getType(Uri uri) {
        return null;
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        return null;
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        return 0;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection,
            String[] selectionArgs) {
        // TODO Auto-generated method stub
        return 0;
    }

}
  1. 解析
    Uri uri = Uri.parse("content://com.elnui.testdbprovider/query");    // 路徑和內容提供者路徑一樣,前面還應加協議content://
    /**
     * uri 
     * projection 查詢列
     * selection
     * selectionArgs
     * sortOrder
     * */
    Cursor cursor = getContentResolver().query(uri, null, null, null, null);

    if(cursor != null){
        while(cursor.moveToNext()){
            String name = cursor.getString(1);
            String phone = cursor.getString(2);

            System.out.println("___2" + name + ": " + phone);
        }
    }

四、備份簡訊案例

public void click1(View v){

        try {
            // 獲取XmlSerializer序列化例項
            XmlSerializer serializer = Xml.newSerializer();

            // 設定序列化引數
            File file = new File(Environment.getExternalStorageDirectory().getPath(),"backup.xml");
            FileOutputStream fos = new FileOutputStream(file);
            serializer.setOutput(fos, "utf-8");

            // 開始寫
            serializer.startDocument("utf-8", true);
            serializer.startTag(null, "smss");



            // 使用內容解析者去解析即可
            Uri uri = Uri.parse("content://sms/inbox");

            Cursor cursor = getContentResolver().query(uri, new String[]{"address","date","body"}, null, null, null);
            if(cursor != null){
                while(cursor.moveToNext()){
                    String addr = cursor.getString(0);
                    String date = cursor.getString(1);
                    String body = cursor.getString(2);

                    System.out.println("___" + addr + date + body);

                    // 寫sms節點
                    serializer.startTag(null, "sms");

                    // address
                    serializer.startTag(null, "address");
                    serializer.text(addr);
                    serializer.endTag(null, "address");

                    // body
                    serializer.startTag(null, "body");
                    serializer.text(body);
                    serializer.endTag(null, "body");

                    // date
                    serializer.startTag(null, "date");
                    serializer.text(date);
                    serializer.endTag(null, "date");

                    serializer.endTag(null, "sms");
                }
                serializer.endTag(null, "smss");

                serializer.endDocument();
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

五、利用內容提供者插入簡訊

public void click1(View v){
        Uri uri = Uri.parse("content://sms");
        ContentValues values = new ContentValues();
        values.put("address","10086");
        values.put("body","你的花費餘額不足!");
        values.put("date",  System.currentTimeMillis());
        getContentResolver().insert(uri, values);
    }

六、讀取聯絡人的案例

6-1. 三張重要的表

  1. data表

    • raw_contact_id ,實際上是raw_contacts表
    • mimetype_id ,1-email, 2-im, 3-nickname,5-phone, 7-name, 8-address,實際上對應mimetype表
  2. raw_contacts表

  3. mimetypes

6-2.實現步驟

  1. 讀raw_contacts表的contact_id欄位,獲取聯絡人總數
  2. 根據raw_contacts_id讀取data表的data1列和mimetype列

6-3.小細節

getContentResolver().query(data_uri, new String[]{"data1","mimetype_id"}, "raw_contact_id=?", new String[]{contact_id}, null);
查詢的不是data表,查詢的是view_data的檢視

七、插入聯絡人

  1. 先往raw_contact表,contact_id列插入元素
  2. 同步到data表,data1列存所以聯絡人資料
public void click1(View v){
        Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
        Uri data_uri = Uri.parse("content://com.android.contacts/data");

        String name = et_name.getText().toString().trim();
        String address = et_address.getText().toString().trim();
        String emall = et_email.getText().toString().trim();
        String phone = et_phone.getText().toString().trim();

        // 查詢raw_contacts中共幾條資料
        Cursor cursor = getContentResolver().query(uri, null, null, null, null);
        int count = cursor.getCount();
        int countid = count+1;

        ContentValues values = new ContentValues();
        values.put("contact_id", countid);

        getContentResolver().insert(uri, values);

        ////////////////////////////////////////////////////////////////////////
        // 插入名字
        ContentValues valuesName = new ContentValues();
        valuesName.put("data1", name);  //把資料插入到data1列
        valuesName.put("raw_contact_id", countid);//插入的資料屬於那條聯絡人
        valuesName.put("mimetype","vnd.android.cursor.item/name");  //插入的 資料的資料型別是名字
        getContentResolver().insert(data_uri, valuesName);

        // 插入地址
        ContentValues valuesAddress = new ContentValues();
        valuesAddress.put("data1", address);    //把資料插入到data1列
        valuesAddress.put("raw_contact_id", countid);//插入的資料屬於那條聯絡人
        valuesAddress.put("mimetype","vnd.android.cursor.item/postal-address_v2");  //插入的 資料的資料型別是名字
        getContentResolver().insert(data_uri, valuesAddress);

        // 插入email
        ContentValues valuesMail = new ContentValues();
        valuesMail.put("data1", emall); //把資料插入到data1列
        valuesMail.put("raw_contact_id", countid);//插入的資料屬於那條聯絡人
        valuesMail.put("mimetype","vnd.android.cursor.item/email_v2");  //插入的 資料的資料型別是名字
        getContentResolver().insert(data_uri, valuesMail);

        // 插入號碼
        ContentValues valuesPhone = new ContentValues();
        valuesPhone.put("data1", phone);    //把資料插入到data1列
        valuesPhone.put("raw_contact_id", countid);//插入的資料屬於那條聯絡人
        valuesPhone.put("mimetype","vnd.android.cursor.item/phone_v2"); //插入的 資料的資料型別是名字
        getContentResolver().insert(data_uri, valuesPhone);


    }

八、內容觀察者

==內容提供者==是四大元件,需要在清單檔案配置

8-1.被觀察的提供者中新增

            // 資料庫被改了,自己傳送訊息
            getContext().getContentResolver().notifyChange(uri, null);

8-2.內容觀察者

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

        // 註冊記憶體觀察者
        Uri uri = Uri.parse("content://com.elnui.testdbprovider");
        getContentResolver().registerContentObserver(uri, true, new MyObserver(new Handler()));
    }

    private class MyObserver extends ContentObserver{

        public MyObserver(Handler handler) {
            super(handler);
        }
        @Override
        public void onChange(boolean selfChange) {
            System.out.println("___[ContentObserver]資料被修改了");
            super.onChange(selfChange);
        }
    }

九、內容觀察者應用場景

十、安卓中的動畫