04Android學習從零單排之ContentProvider

04Android學習從零單排之ContentProvider

讀了那麼多年的書讓我明白一個道理。人要穩重,不要想到啥就做啥。做一行越久即使你不會,幾年之後慢慢的你也會了,加上一點努力你或許你能成爲別人眼中的專家。

ContentProvider簡介

ContentProvider 在android中的作用是對外共享數據,也就是說你可以通過ContentProvider把應用中的數據共享給其他應用訪問,其他應用可以通過ContentProvider 對你應用中的數據進行添刪改查。

ContentProvider實際應用場景

ContentProvider實際應用場景,主要是通過getContentResolver來獲取安卓系統中已經通過ContentProvider共享好的數據。例如,讀取短信數據、獲取聯繫人信息,它們都是通過ContentProvider把數據庫對外提供好的,一般我們很少會ContentProvider把自己的應用程序數據暴露出去。

ContentProvider共享數據的使用步驟

1、定義一個類繼承ContentProvider,並在清單文件中配置provider和android:authorities節點。
2、定義路徑匹配規則
3、添加路徑匹配規則,以供其他應用程序訪問。
4、判斷匹配規則,和定義的匹配規則是否相同。相同數據即可不其他應用操作。

public class AccountProvider extends ContentProvider {

    private static final int QUERYSUCESS = 1;  //ctrl+shift+x 變成大些  ctrl+shift小寫加Y
    private static final int ADDSUCESS = 2;
    private static final int DELSUCESS = 3;
    private static final int UPDATESUCESS = 4;


    //(1) 定義路徑匹配規則  
    static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
    private MyOpenHelper helper;
    //(2) 添加路徑匹配規則  
    static{
        /**
         * authority  主機名 自己定義 
         * path 路徑  
         * 
         */
        matcher.addURI("com.itheima.account.provider", "query", QUERYSUCESS);  //添加 query方法的匹配規則 
        matcher.addURI("com.itheima.account.provider", "add", ADDSUCESS);  //添加 add方法的匹配規則 
        matcher.addURI("com.itheima.account.provider", "delete", DELSUCESS);  //添加 add方法的匹配規則 
        matcher.addURI("com.itheima.account.provider", "update", UPDATESUCESS);  //添加 add方法的匹配規則 

    }


    @Override
    public boolean onCreate() {

        helper = new MyOpenHelper(getContext());

        return false;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
            String[] selectionArgs, String sortOrder) {
        //(3)獲取匹配code 
        int code = matcher.match(uri);
        if (code == QUERYSUCESS) {
            //說明匹配成功  

            SQLiteDatabase db = helper.getReadableDatabase();
            Cursor cursor = db.query("info", projection, selection, selectionArgs, null, null, sortOrder);
            return cursor;
        }else {

            throw new IllegalArgumentException("路徑不匹配 請檢查");
        }


    }

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

    @Override
    public Uri insert(Uri uri, ContentValues values) {
       int code = matcher.match(uri);
       if (code == ADDSUCESS ) {
           //匹配成功 
            SQLiteDatabase db = helper.getReadableDatabase();
            //代表插入到了多少行 
            long insert = db.insert("info", null, values);
            return Uri.parse("com.itheima.account.provider"+insert); 

    }else {

        throw new IllegalArgumentException("路徑不匹配 請檢查");
    }


    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        int code = matcher.match(uri);
        if (code == DELSUCESS) {
            SQLiteDatabase db = helper.getReadableDatabase();
            int delete = db.delete("info", selection, selectionArgs);
            //刪除了多少行

            return delete;
        }else {
            throw new IllegalArgumentException("路徑不匹配 請檢查");

        }


    }

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

        int code = matcher.match(uri);
        if (code == UPDATESUCESS) {
            SQLiteDatabase db = helper.getReadableDatabase();
            int update = db.update("info", values, selection, selectionArgs);
            //刪除了多少行

            return update;
        }else {
            throw new IllegalArgumentException("路徑不匹配 請檢查");

        }


    }

}
清單文件中配置provider
<provider
    android:name="com.itheima.transation.AccountProvider"
    android:authorities="com.itheima.account.provider" ></provider>

以上內容在實際開發中一般不常見。下面通過案例的方式,學習並使用ContentProvider共享數據的共享的數據。


ContentProvider之短信備份案例

1、通過內容解析者getContentResolver()查詢短信數據庫。
2、把查詢出來的結果通過xml文件保存起來。

public void backsms(View view){
        //寫入到xml文件中
        XmlSerializer serializer = Xml.newSerializer();
        File file = new File(Environment.getExternalStorageDirectory().getPath()+"/Download", "smsback.xml");
        try {
            FileOutputStream fos = new FileOutputStream(file);
            serializer.setOutput(fos,"utf-8");
            //文檔開始
            serializer.startDocument("utf-8",true);
            //開始節點
            serializer.startTag(null,"smss");
            //循環寫 xml sms  body address date
            //1、利用內容解析者 獲取我們關心列
            //content://sms 是短信的匹配規則
            Uri uri = Uri.parse("content://sms");
            Cursor cursor = getContentResolver().query(uri, new String[]{"address", "date", "body"}, null, null, null);
            if (cursor != null&&cursor.getCount()>0) {
                while(cursor.moveToNext()){
                    String address = cursor.getString(0);
                    String date = cursor.getString(1);
                    String body = cursor.getString(2);
                    String datef = formatDate(date);
                    //開始寫 xml 的  sms節點
                    serializer.startTag(null,"sms");

                    serializer.startTag(null,"address");
                    //如果不做這個判斷,讀取到是草稿短信,就會報空指針異常。
                    if (TextUtils.isEmpty(address)){
                        serializer.text("草稿箱");
                    }else{
                        serializer.text(address);
                    }
                    serializer.endTag(null,"address");

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

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

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

            serializer.endTag(null,"smss");
            serializer.endDocument();
            //關閉數據庫查詢
            cursor.close();
            fos.close();//釋放資源

            Toast.makeText(getApplicationContext(),"短信備份完成。",Toast.LENGTH_SHORT).show();
        } catch (Exception e) {
            Toast.makeText(getApplicationContext(),"短信備份失敗。",Toast.LENGTH_SHORT).show();
            e.printStackTrace();
        }

 //不要忘記添加短信權限

    }

    /**
     * 時間格式轉換
     * @param date
     * @return
     */
    private String formatDate(String date){
        long l = System.currentTimeMillis();
        SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
        String format1 = format.format(new Date(new Long(date)));
        return format1;
    }

ContentProvider之短信插入案例

public void insertSms(View view){
        //通過內容解析者,插入數據到短信數據庫中
        ContentResolver resolver = getContentResolver();
        Uri uri = Uri.parse("content://sms");
        String phoneNumber = mTvPhone.getText().toString().trim();
        String context = mTvPhone.getText().toString().trim();
            long l = System.currentTimeMillis();
            ContentValues values = new ContentValues();
            values.put("address",context);
            values.put("date",l);
            values.put("body",phoneNumber);
        //從這裏插入你添加的短信數據
            resolver.insert(uri,values);
    }
    //不要忘記添加短信權限

ContentProvider之讀取聯繫人案例

由於讀取聯繫人是實際開發中比較常用的功能,因此在這裏我把讀取聯繫人抽取成了工具類,方便以後再開發中,直接哪來用。
這個讀取聯繫人的工具類,只是最簡單的實現功能,代碼還有很多需要完善的地方,在此不做修改了,等用到的時候在優化。

public class ReadContactUtils {
    public List<ContactsBean> readContacts(Context context){
        //自定義一個javabean,用於存儲短信格式,javabean在此就不貼出來了,根據實際需求自己定義。
        List<ContactsBean> contactsBeanList = new ArrayList<>();
        //(1)去raw_contacts表查詢  contact_id列,contact_id記錄了聯繫人的數目
        Uri contactsUri = Uri.parse("content://com.android.contacts/raw_contacts");
        Uri dataUri = Uri.parse("content://com.android.contacts/data");

        Cursor contactsCursor = context.getContentResolver().query(contactsUri, new String[]{"contact_id"}, null, null, null);
        if (contactsCursor!= null&&contactsCursor.getCount()>0) {
            while(contactsCursor.moveToNext()){
                String  contactsID = contactsCursor.getString(0);
                //判斷contactsID不爲null說明聯繫人存在
                if (contactsID != null) {
                    ContactsBean contactsBean = new ContactsBean();
                    contactsBean.setId(contactsID);
                    //(2)根據 contact_id 去查 data表    查詢data1列 和 mimetype_id 列
                    Cursor dataCursor = context.getContentResolver().query(dataUri, new String[]{"data1","mimetype"}, "raw_contact_id=?", new String[]{contactsID}, null);
                    if (dataCursor != null&&dataCursor.getCount()>0) {
                        while (dataCursor.moveToNext()){
                            if (dataCursor!=null){
                                String data1 = dataCursor.getString(0);//獲取data1列的數據,就是聯繫人的詳情數據
                                String mimetype = dataCursor.getString(1);//獲取mimetype列數據

                                //(3)拿mimetype 數據做一下對比,然後取出聯繫人號碼或者其他信息

                                if("vnd.android.cursor.item/name".equals(mimetype)){
                                    System.out.println("姓名data1:"+data1);
                                    contactsBean.setName(data1);
                                }else if("vnd.android.cursor.item/phone_v2".equals(mimetype)){
                                    System.out.println("電話號碼data1:"+data1);
                                    contactsBean.setPhone(data1);
                                }

                            }
                        }
                    }
                contactsBeanList.add(contactsBean);
                }
            }
//                System.out.println("一共有"+contactsID+"個聯繫人");
        }
        return contactsBeanList;
    }

ContentProvider之插入聯繫人案例

public void addContact(View view){
        String name = mTvName.getText().toString().trim();
        String number = mTvNumber.getText().toString().trim();

        //添加聯繫人之前先查詢聯繫的contact_id
        Uri contactsUri = Uri.parse("content://com.android.contacts/raw_contacts");
        Uri dataUri = Uri.parse("content://com.android.contacts/data");
        Cursor cursor = getContentResolver().query(contactsUri, null, null, null, null);
        int contact_id = cursor.getCount();
//        System.out.println("contact_id"+contact_id);
        //2現在開始插入聯繫人id
        ContentValues Values = new ContentValues();
        //3爲什麼加1,是在原來的基礎上+1
        int newContact_id = contact_id+1;
        Values.put("contact_id",newContact_id);
        getContentResolver().insert(contactsUri,Values);
        //4開始插入聯繫人姓名
        ContentValues nameValues = new ContentValues();
        nameValues.put("raw_contact_id",newContact_id);
        nameValues.put("mimetype","vnd.android.cursor.item/name");
        nameValues.put("data1",name);
        getContentResolver().insert(dataUri,nameValues);
        //5插入聯繫人手機號碼
        ContentValues numberValues = new ContentValues();
        numberValues.put("raw_contact_id", newContact_id);
        numberValues.put("mimetype", "vnd.android.cursor.item/phone_v2");
        numberValues.put("data1",number);
        getContentResolver().insert(dataUri,numberValues);

        Toast.makeText(getApplicationContext(),"聯繫人插入成功",Toast.LENGTH_SHORT).show();
    }

關於作者
- Email:[email protected]
- 項目地址:https://github.com/swordman20/Hsia04ContentProviderDemo.git

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章