四大組件之ContentProvider

四大組件之ContentProvider

ContentProvider簡介

ContentProvider的主要作用是實現不同的應用程序之間的數據的共享,而且還保證了數據的安全性。 ContentProvider是android提供的實現程序之間數據共享的一套機制。

ContentProvider的使用

1.創建ContentProvider

  • 首先我們要爲應用程序準備數據,我們在數據庫裏面添加100條數據

        public class MySQLiteOpenHelper extends SQLiteOpenHelper {
    
        public MySQLiteOpenHelper(Context context) {
            super(context, "mydb.db", null, 1);
            // TODO Auto-generated constructor stub
        }
    
        @Override
        public void onCreate(SQLiteDatabase db) {
            // TODO Auto-generated method stub
            //創建一張表
            db.execSQL("create table student( _id integer primary key autoincrement,name text,age text,score text)");
            //向表中插入100條記錄
            for(int i=0;i<100;i++){
                db.execSQL("insert into student(name,age,score)values('zhangsan"+i+"','"+(20+i)+"','"+(60+i)+"')");
            }
        }
        //更新時調用
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            // TODO Auto-generated method stub
    
        }
    
    } 
    
  • 添加完數據之後,開始創建自己的ContentProvider。我們需要建一個類,繼承 ContentProvider 類,然後複寫裏面的方法

    public class MyContentProder extends ContentProvider {
        //創建一個UriMatcher對象
        private static final UriMatcher urimatcher =new UriMatcher(UriMatcher.NO_MATCH);
        private static final int INSERT=1;
        private static final int DELETE=2;
        private static final int UPDATE=3;
        private static final int QUERY=4;
        private MySQLiteOpenHelper helper;
        static{
            //添加uri
            urimatcher.addURI("com.example.provider", "insert", INSERT);
            urimatcher.addURI("com.example.provider", "delete", DELETE);
            urimatcher.addURI("com.example.provider", "update", UPDATE);
            urimatcher.addURI("com.example.provider", "query", QUERY);
        }
        @Override
        public boolean onCreate() {
            helper = new MySQLiteOpenHelper(getContext());
            return false;
        }
    
        @Override
        public Cursor query(Uri uri, String[] projection, String selection,
                String[] selectionArgs, String sortOrder) {
            // TODO Auto-generated method stub
            //匹配uri
            if(urimatcher.match(uri)==QUERY){
                SQLiteDatabase db = helper.getWritableDatabase();
                Cursor cursor = db.query("student", projection, selection, selectionArgs, null, null, sortOrder);
    
                return cursor;
            }
            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
            if(urimatcher.match(uri)==INSERT){
                SQLiteDatabase db = helper.getWritableDatabase();
                long insert2 = db.insert("student", null, values);
                db.close();
                return Uri.parse("content://com.example.provider"+insert2);
            }
            return null;
        }
    
        @Override
        public int delete(Uri uri, String selection, String[] selectionArgs) {
            // TODO Auto-generated method stub
            if(urimatcher.match(uri)==DELETE){
                SQLiteDatabase db = helper.getWritableDatabase();
                int delete2 = db.delete("student", selection, selectionArgs);
                return delete2;
            }
            return 0;
        }
    
        @Override
        public int update(Uri uri, ContentValues values, String selection,
                String[] selectionArgs) {
            // TODO Auto-generated method stub
            if(urimatcher.match(uri)==UPDATE){
                SQLiteDatabase db = helper.getWritableDatabase();
                int update2 = db.update("student", values, selection, selectionArgs);
                return update2;
            }
            return 0;
        }
    
    }
    
  • 和其他的幾大大組件組件一樣ContentProvider也需要在Manifest.xml裏面註冊,註冊ContentProvider的時候,還要配置兩個額外的屬性。

    <provider android:name="com.example.contentproviderdemo.MyContentProder"
        android:authorities="com.example.provider"
        android:exported="true">
    </provider>
    

這樣,我們就將這個application裏面的數據通過ContentProvider暴露出去了,其他的application就可以通過getContentResolver()來訪問這個application裏面的數據。

2.在另外的application中進行對數據庫的內容的操作

上面我們已經將數據暴露出來了,這裏我們就在另外的application中來操作數據。

  • 我們在另外的一個application的佈局文件中定義4個button,分別用來對contentprovide的數據進行增刪改查。

    <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"
        android:orientation="vertical">
    
        <Button 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="click1"
            android:text="查詢"/>
         <Button 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="click2"
            android:text="刪除"/>
          <Button 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="click3"
            android:text="添加"/>
           <Button 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="click4"
            android:text="更新"/>
    
    </LinearLayout>  
    
  • 在Mainctivity裏面,我們通過設置button的點擊事件來操作數據。

    public class MainActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }
    
        // 查詢
        public void click1(View v) {
            Uri uri = Uri.parse("content://com.example.provider/query");
            Cursor cursor = getContentResolver().query(uri, null, null, null, null);
            if(cursor!=null && cursor.getCount()>0){
                while(cursor.moveToNext()){
                    String name = cursor.getString(1);
                    String age =cursor.getString(2);
                    String score = cursor.getString(3);
                    System.out.println(name+" "+age+"  "+score);
                }
            }
        }
    
        // 刪除
        public void click2(View v) {
            Uri uri = Uri.parse("content://com.example.provider/delete");
            int delete = getContentResolver().delete(uri, "_id=?", new String[]{"1"});
            System.out.println(delete);
        }
    
        // 添加
        public void click3(View v) {
            Uri uri = Uri.parse("content://com.example.provider/insert");
            ContentValues values =new ContentValues();
            values.put("name", "xiaoming");
            values.put("age", "100");
            values.put("score", "200");
            Uri insert = getContentResolver().insert(uri, values );
            System.out.println(insert);
        } 
        // 更新
        public void click4(View v) {
            Uri uri = Uri.parse("content://com.example.provider/update");
            ContentValues values =new ContentValues();
            values.put("score", "2000");
            int update = getContentResolver().update(uri, values , "_id =?", new String[]{"100"});
            System.out.println(update);
        }
    }
    

到這裏爲止,我們就已經會使用ContentProvider了。下面我們來寫一個短信備份的案例。

使用ContentProvider實現手機短信備份

1.獲取短信存儲的信息

毫無疑問,手機短信存儲在手機的數據庫裏面,所以我們首先要知道短信存儲的情況。我們可以在手機文件夾的 \data\data\com.android.providers.telephony\databases\ 目錄下找到mmssms.db文件,這就是存儲短信的表,我們打開這張後發現,我們只需要通過查詢這個表的3個字段就可以進行短信的完整備份,它們分別是:date表示短信的發送日期、address短信來源的號碼、body表示短信的具體內容。

2.得到系統爲短信設置的ContentProvider的Uri

想要得到這個,我們百度或者自己查下系統上層應用的源代碼。如果我們要在源碼裏面找的話,需要在\providers\TelephonyProvider\src\com\android\providers\telephony\SmsProvider.java這個文件裏面找。這裏我粘一段靜態代碼塊的內容參考:

 static {
    sURLMatcher.addURI("sms", null, SMS_ALL);
    sURLMatcher.addURI("sms", "#", SMS_ALL_ID);
    sURLMatcher.addURI("sms", "inbox", SMS_INBOX);
    sURLMatcher.addURI("sms", "inbox/#", SMS_INBOX_ID);
    sURLMatcher.addURI("sms", "sent", SMS_SENT);
    //省略若干
    ...
    }

3.備份短信

備份短信的思路:從數據庫中將短信獲取後,將其序列化到SDcard中。

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    public void click(View v){
        //設置Uri
        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){
            //獲取xml解析器,開始序列化
            XmlSerializer serializer = Xml.newSerializer();
            //設置文件存儲的位置
            File file =new File(Environment.getExternalStorageDirectory(),"smss.xml");
            //設置輸出流

            FileOutputStream fos;
            try {
                fos = new FileOutputStream(file);
                serializer.setOutput(fos, "utf-8");
                //開始文檔
                serializer.startDocument("utf-8", true);
                //根標籤
                serializer.startTag(null, "smss");
                //將查詢到的數據序列化到XML文件中
                while (cursor.moveToNext()) {

                    String address = cursor.getString(0);//短信人電話  爲null
                    String date = cursor.getString(1);//短信發送時間
                    String body = cursor.getString(2);//短信內容
                    //根目錄下的一級標題
                    serializer.startTag(null, "sms");
                    //設置address
                    serializer.startTag(null, "address");
                    serializer.text(address);
                    serializer.endTag(null, "address");

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

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

                    serializer.endTag(null, "sms");
                }
                serializer.endTag(null, "smss");
                //結束文檔
                serializer.endDocument();
                Toast.makeText(this, "序列化完成", 0).show();;
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }
    }
}

最後,我們需要添加相應的權限。

<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章