Android基礎(chǔ)回顧(六)| 關(guān)于 Content provider

參考書籍:《第一行代碼》 第二版 郭霖
如有錯(cuò)漏奠旺,請(qǐng)批評(píng)指出蜘澜!

內(nèi)容提供器(Content Provider)主要用于在不同應(yīng)用程序之間實(shí)現(xiàn)數(shù)據(jù)共享功能(即跨程序數(shù)據(jù)共享)。它提供了一套完整的機(jī)制鄙信,允許一個(gè)程序訪問另一個(gè)程序的數(shù)據(jù),同時(shí)還能保證被訪問數(shù)據(jù)的安全性稽寒。目前扮碧,使用 Content Provider 是Android實(shí)現(xiàn)跨程序共享數(shù)據(jù)的標(biāo)準(zhǔn)方式趟章。Content Provider可以選擇只對(duì)某一部分?jǐn)?shù)據(jù)進(jìn)行共享杏糙,從而保證我們程序中的隱私數(shù)據(jù)不會(huì)有泄露的風(fēng)險(xiǎn)。

由于后面關(guān)于Content Provider的內(nèi)容會(huì)大量涉及運(yùn)行時(shí)權(quán)限蚓土,我們先來了解一下關(guān)于Android運(yùn)行時(shí)權(quán)限的內(nèi)容宏侍。

Android運(yùn)行時(shí)權(quán)限

  • 關(guān)于Android權(quán)限機(jī)制
    在Android開發(fā)過程中,我們會(huì)經(jīng)常遇到某些功能需要設(shè)備的一些權(quán)限蜀漆,比如讀取聯(lián)系人谅河、開啟攝像頭等。在Android6.0之前确丢,這個(gè)問題是很好解決的绷耍,只需要在AndroidManifest文件中聲明對(duì)應(yīng)權(quán)限即可,當(dāng)用戶安裝程序時(shí)鲜侥,這些權(quán)限都會(huì)一一列出來褂始,用戶繼續(xù)安裝就意味著同意應(yīng)用所請(qǐng)求的所有權(quán)限,這也就導(dǎo)致了很多應(yīng)用程序?yàn)E用權(quán)限的情況描函,造成了用戶隱私的安全問題崎苗。

    而在Android6.0之后的系統(tǒng)中,加入了運(yùn)行時(shí)權(quán)限的功能舀寓。也就是說胆数,用戶不需要在安裝程序時(shí)一次性授權(quán)所有權(quán)限,可以在使用過程中互墓,對(duì)相應(yīng)功能提出的授權(quán)申請(qǐng)選擇授權(quán)或拒絕授權(quán)必尼,比如說,我們?cè)诔醮问褂肣Q的掃一掃功能時(shí)篡撵,QQ會(huì)申請(qǐng)相機(jī)權(quán)限:

    如果我們?cè)试S判莉,就意味著對(duì)這個(gè)權(quán)限授權(quán)了齿诞,后面不需要再請(qǐng)求,如果我們拒絕了骂租,這個(gè)功能就無法使用祷杈,除非你在手機(jī)的權(quán)限管理中手動(dòng)授予應(yīng)用這個(gè)權(quán)限。

    當(dāng)然渗饮,并不是所有的權(quán)限都需要?jiǎng)討B(tài)申請(qǐng)但汞,在加入運(yùn)行時(shí)權(quán)限功能后,Android將權(quán)限分為兩個(gè)大類互站,一類是普通權(quán)限(和Android6.0之前一樣私蕾,系統(tǒng)會(huì)自動(dòng)授權(quán)),另一類是危險(xiǎn)權(quán)限胡桃,即需要我們動(dòng)態(tài)申請(qǐng)的權(quán)限踩叭。下面是Android中所有的危險(xiǎn)權(quán)限,一共9組24個(gè)權(quán)限:

    也就是說翠胰,在Android6.0以上的系統(tǒng)使用上面這些權(quán)限時(shí)容贝,我們不僅要在AndroidManifest文件中聲明,還需要?jiǎng)討B(tài)申請(qǐng)之景,不在這張表里的權(quán)限斤富,我們只需要在AndroidManifest文件中聲明一下即可。上面這些是關(guān)于Android權(quán)限機(jī)制的內(nèi)容锻狗,接下來我們來看看如何動(dòng)態(tài)申請(qǐng)權(quán)限满力。

  • 在程序運(yùn)行時(shí)申請(qǐng)權(quán)限
    在上面的表中,PHONE組有一個(gè) CALL_PHONE權(quán)限轻纪,這個(gè)權(quán)限是撥打電話需要的油额,我們現(xiàn)在就使用這個(gè)權(quán)限來寫一個(gè)撥打10086的功能。

    1. 首先在界面中添加一個(gè)Button刻帚,用來觸發(fā)撥打電話(很簡單潦嘶,不貼代碼了)。
    2. 在AndroidManifest文件中聲明權(quán)限.
    <uses-permission android:name="android.permission.CALL_PHONE"/>
    
    1. 在Activity中編寫點(diǎn)擊按鈕觸發(fā)撥打電話的邏輯
    public class CpMainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.cp_activity_main);
            ButterKnife.bind(this);
    
            initView();
        }
    
        private void initView() {
            Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar);
            setSupportActionBar(toolbar);
        }
    
        @OnClick(R.id.but_call)
        public void onClick(View v) {
            switch (v.getId()){
                default:
                    break;
                case R.id.but_call:
                    try {
                         Intent intent = new Intent(Intent.ACTION_CALL);
                         intent.setData(Uri.parse("tel:10086"));
                         startActivity(intent);
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                    break;
            }
        }
    }
    

    只需要看onClick()方法中的內(nèi)容我擂,邏輯很簡單衬以,就是當(dāng)我們點(diǎn)擊我們定義的Button時(shí),定義一個(gè)隱式Intent校摩,Intent的action指定為 “Intent.ACTION_CALL”看峻,這是一個(gè)系統(tǒng)內(nèi)置的打電話的動(dòng)作,然后data部分指定協(xié)議為 tel 衙吩,號(hào)碼是10086互妓,也就是當(dāng)我們點(diǎn)擊Button時(shí),會(huì)直接撥打10086,(寫在try catch 語句塊中是為了防止程序崩潰)。不過冯勉,這是在Android 6.0 之前的寫法澈蚌,如果手機(jī)的Android版本低于6.0,這么寫是可以灼狰。但是在Android6.0以上的系統(tǒng)中宛瞄,我們點(diǎn)擊Button是沒有反應(yīng)的(可以自行測試一下)。下面我們來看在Android6.0以上的系統(tǒng)中要如何申請(qǐng)權(quán)限:

    @OnClick(R.id.but_call)
    public void onClick(View v) {
        switch (v.getId()){
            default:
                break;
            case R.id.but_call:
                if (ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE)
                        != PackageManager.PERMISSION_GRANTED){
                    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CALL_PHONE}, 1);
                }else {
                    try {
                        Intent intent = new Intent(Intent.ACTION_CALL);
                        intent.setData(Uri.parse("tel:10086"));
                        startActivity(intent);
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
                break;
        }
    }
    
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode){
            default:
                break;
            case 1:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
                    try {
                        Intent intent = new Intent(Intent.ACTION_CALL);
                        intent.setData(Uri.parse("tel:10086"));
                        startActivity(intent);
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }else {
                    ToastUtil.showShortToast(this, "您已拒絕電話權(quán)限交胚,請(qǐng)手動(dòng)開啟");
                }
                break;
        }
    }
    

    首先份汗,在事件觸發(fā)時(shí),我們需要調(diào)用 ContextCompat 的 checkSelfPermission(Context context, String permission)方法來驗(yàn)證我們需要使用的權(quán)限是否授權(quán)蝴簇,具體的權(quán)限我們使用 Manifest.permission 來獲取杯活,這個(gè)方法有一個(gè)返回值,如果和 PackageManager.PERMISSION_GRANTED 相等熬词,說明用戶已經(jīng)授權(quán)旁钧,我們可以撥打電話,否則我們就需要進(jìn)行申請(qǐng)互拾。使用 ActivityCompat 的 requestPermissions(Activiti activity, String[] permissions, int requestCode) 方法歪今,可以向用戶申請(qǐng)權(quán)限,這個(gè)方法接收三個(gè)參數(shù)摩幔,第一個(gè)參數(shù)即當(dāng)前Activity彤委,第二個(gè)參數(shù)是一個(gè)String數(shù)組鞭铆,也就是說可以同時(shí)申請(qǐng)多條權(quán)限或衡,將權(quán)限名放入數(shù)組即可,第三個(gè)參數(shù)是一個(gè)請(qǐng)求碼车遂,用來區(qū)分我們申請(qǐng)權(quán)限的位置封断,只要是唯一值就行。

    在調(diào)用完requestPermission()方法后舶担,系統(tǒng)會(huì)彈出一個(gè)申請(qǐng)權(quán)限的對(duì)話框坡疼,用戶可以選擇同意或者拒絕,無論用戶選擇什么衣陶,最后都會(huì)回調(diào) onRequestPermissionsResult() 方法柄瑰,這時(shí)我們需要再來檢查用戶是否授權(quán),授權(quán)了就執(zhí)行我們的邏輯(即撥打電話)剪况,否則教沾,我們可以彈出一條Toast用來提示操作失敗。下面來看看效果:

    關(guān)于動(dòng)態(tài)權(quán)限的內(nèi)容就到這里译断,下面來看關(guān)于Content Provider 的用法授翻。Content Provider的用法一般有兩種,一種是使用現(xiàn)有的Content Provider 來讀取和操作相應(yīng)程序中的數(shù)據(jù),另一種是創(chuàng)建自己的內(nèi)容提供器堪唐,給我們程序的數(shù)據(jù)提供外部訪問接口巡语。

訪問其他程序中的數(shù)據(jù)

  • ContentResolver的基本用法
    一個(gè)應(yīng)用程序想要訪問其他程序通過Content Provider共享的數(shù)據(jù),就需要用到Content Resolver 類淮菠,可以通過Context的getContentResolver() 方法獲取到該類的實(shí)例男公,ContentResolver中提供了一系列方法用于對(duì)數(shù)據(jù)庫進(jìn)行CRUD操作,和SQLiteDatabase的CRUD操作相似合陵。不過ContentResolver 的CRUD方法不接收表名參數(shù)理澎,而是使用一個(gè)Uri參數(shù)代替,這個(gè)參數(shù)被稱為內(nèi)容URI曙寡。
    內(nèi)容URI給Content Provider 中的數(shù)據(jù)建立了唯一的標(biāo)示符糠爬,它主要由兩部分組成:authority和path。authority可以用包名來命名举庶,用于區(qū)分應(yīng)用程序执隧;path用于區(qū)分程序中的表。例如某個(gè)程序的包名是com.laughter.learnapplication户侥,并且數(shù)據(jù)庫中有兩張表table1和table2镀琉,那么內(nèi)容URI就是:
    content://com.laughter.learnapplication/table1
    content://com.laughter.learnapplication/table2
    “ content:// " 是協(xié)議聲明,需要加在頭部蕊唐。這樣看來屋摔,內(nèi)容URI可以清楚表達(dá)我們想要訪問那個(gè)程序的哪張表,也可以準(zhǔn)確標(biāo)識(shí)我們想要訪問的應(yīng)用程序中的數(shù)據(jù)替梨。
  1. 查詢數(shù)據(jù)
    想要查詢Content Provider中的數(shù)據(jù)钓试,我們首先要調(diào)用 Uri 的 parse() 方法將內(nèi)容URI解析成Uri對(duì)象,

    Uri uri = Uri.parse("content://com.laughter.learnapplication/table1");
    

    接下來就可以查詢數(shù)據(jù)了:

    Cursor cursor = getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder);
    

    下表是查詢語句中的參數(shù)說明:

    查詢完成后返回的是一個(gè) Cursor 對(duì)象,我們需要從 Cursor 對(duì)象中將數(shù)據(jù)逐條讀出:

    if(cursor != null){
        while(cursor.moveToNext()){
            String name = cursor.getString(cursor.getColumnIndex("name"));
            String num = cursor.getInt(cursor.getColumnIndex("num"));
        }
        cursor.close();
    }
    
  2. 添加數(shù)據(jù)

    ContentValues values = new ContentValues();
    values.put("name", name);
    values.put("num", num);
    getContentResolver().insert(uri, values);
    

    添加數(shù)據(jù)和SQLiteDatabase一樣副瀑,要借助于ContentValues弓熏;

  3. 修改數(shù)據(jù)
    假設(shè)要修改 name 為 laughter,num 為 0 這一條數(shù)據(jù)的 num 屬性

    ContentValues values = new ContentValues();
    values.put("num", num);
    getContentResolver().update(uri, values, "name = ? and num = ?", new String[] { "laughter", "0" });
    

    我們使用了 selection 和 selectionArgs這兩個(gè)參數(shù)對(duì)想要更新的數(shù)據(jù)進(jìn)行約束糠睡,保證修改的是我們想要修改的數(shù)據(jù)挽鞠。

  4. 刪除數(shù)據(jù)

    getContentResolver().delete(uri, "name = ?", new String[] { "laughter" });
    

    操作和SQLiteDatabase 相似,很容易理解狈孔。

  • 讀取系統(tǒng)聯(lián)系人
    接下來根據(jù)上面的內(nèi)容實(shí)現(xiàn)一個(gè)讀取系統(tǒng)聯(lián)系人并顯示出來的小應(yīng)用信认。
  1. 首先在Activity布局中添加一個(gè)ListView

    <ListView
        android:id="@+id/list_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    
  2. 查詢聯(lián)系人數(shù)據(jù),并使用ListView顯示出來均抽,簡單起見嫁赏,我們使用系統(tǒng)提供的 ArrayAdapter 以及 android.R.layout.simple_list_item_1 布局

    public class MainActivity extends AppCompatActivity {
    
        @BindView(R.id.list_view)
        ListView listView;
    
        private ArrayAdapter<String> adapter;
        private List<String> contctsList = new ArrayList<>();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            ButterKnife.bind(this);
    
            initView();
        }
    
        private void initView() {
            
            adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, contctsList);
            listView.setAdapter(adapter);
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS)
                    != PackageManager.PERMISSION_GRANTED){
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS}, 0);
            }else {
                quaryContacts();
            }
        }
    
        @Override
        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            switch (requestCode){
                case 0:
                    if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
                        quaryContacts();
                    }else {
                        ToastUtil.showShortToast(this, "您已拒絕授權(quán),無法讀取您的手機(jī)聯(lián)系人");
                    }
                    break;
                default:
                    break;
            }
        }
    
        private void quaryContacts() {
            Cursor cursor = null;
            try{
                cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                        null, null, null, null);
                if (cursor != null){
                    while (cursor.moveToNext()){
                        String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
                        String tel = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                        contctsList.add("\n" + name + "\n\n" + tel + "\n");
                    }
                    adapter.notifyDataSetChanged();
                }
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                if (cursor != null){
                    cursor.close();
                }
            }
        }
    }
    

    關(guān)于ListView的使用在前面的文章 Android基礎(chǔ)回顧(三)| 常用控件 — ListView和RecyclerView 中已經(jīng)講得很清楚了到忽,ButterKnife 的使用也講過 Android實(shí)踐(二) | 注解框架ButterKnife基本使用 橄教,我們直接看代碼的邏輯清寇,首先初始化ListView,然后檢查權(quán)限护蝶,這里使用的 READ_CONTACTS 權(quán)限屬于危險(xiǎn)權(quán)限华烟,也是需要在AndroidMenifest文件中聲明,并且動(dòng)態(tài)申請(qǐng)的:

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

    用戶授權(quán)后持灰,就開始查詢手機(jī)中的聯(lián)系人盔夜,這里我們的Uri參數(shù)給的是 ContactsContract.CommonDataKinds.Phone.CONTENT_URI,這是Android開發(fā)團(tuán)隊(duì)封裝好的堤魁,我們可以打印出來看看:

    就是這樣的一個(gè)值喂链,我們直接使用就行,因?yàn)槲覀円@取所有聯(lián)系人妥泉,所以不需要加約束條件椭微,后面的參數(shù)都傳null就行了。接著遍歷查詢的結(jié)果 Cursor 對(duì)象盲链,ContactsContract.CommonDataKinds.Phone.DISPLAY_NAMEContactsContract.CommonDataKinds.Phone.NUMBER 分別是聯(lián)系人姓名和聯(lián)系人號(hào)碼對(duì)應(yīng)的常量蝇率,直接使用,取出數(shù)據(jù)后逐條添加到ListView的數(shù)據(jù)源中刽沾,然后更新一下ListView本慕,最后別忘了關(guān)閉Cursor對(duì)象。下面來運(yùn)行一下看看效果吧:


上一篇:Android基礎(chǔ)回顧(五)| 數(shù)據(jù)存儲(chǔ)——持久化技術(shù)
下一篇:Android基礎(chǔ)回顧(七)| 使用手機(jī)多媒體


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末侧漓,一起剝皮案震驚了整個(gè)濱河市锅尘,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌布蔗,老刑警劉巖藤违,帶你破解...
    沈念sama閱讀 217,907評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異何鸡,居然都是意外死亡纺弊,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門骡男,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人傍睹,你說我怎么就攤上這事隔盛。” “怎么了拾稳?”我有些...
    開封第一講書人閱讀 164,298評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵吮炕,是天一觀的道長。 經(jīng)常有香客問我访得,道長龙亲,這世上最難降的妖魔是什么陕凹? 我笑而不...
    開封第一講書人閱讀 58,586評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮鳄炉,結(jié)果婚禮上杜耙,老公的妹妹穿的比我還像新娘。我一直安慰自己拂盯,他們只是感情好佑女,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著谈竿,像睡著了一般团驱。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上空凸,一...
    開封第一講書人閱讀 51,488評(píng)論 1 302
  • 那天嚎花,我揣著相機(jī)與錄音,去河邊找鬼呀洲。 笑死贩幻,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的两嘴。 我是一名探鬼主播丛楚,決...
    沈念sama閱讀 40,275評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼憔辫!你這毒婦竟也來了趣些?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,176評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤贰您,失蹤者是張志新(化名)和其女友劉穎坏平,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體锦亦,經(jīng)...
    沈念sama閱讀 45,619評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡舶替,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了杠园。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片顾瞪。...
    茶點(diǎn)故事閱讀 39,932評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖抛蚁,靈堂內(nèi)的尸體忽然破棺而出陈醒,到底是詐尸還是另有隱情,我是刑警寧澤瞧甩,帶...
    沈念sama閱讀 35,655評(píng)論 5 346
  • 正文 年R本政府宣布钉跷,位于F島的核電站,受9級(jí)特大地震影響肚逸,放射性物質(zhì)發(fā)生泄漏爷辙。R本人自食惡果不足惜彬坏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望膝晾。 院中可真熱鬧栓始,春花似錦、人聲如沸玷犹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽歹颓。三九已至坯屿,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間巍扛,已是汗流浹背领跛。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留撤奸,地道東北人吠昭。 一個(gè)月前我還...
    沈念sama閱讀 48,095評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像胧瓜,于是被迫代替她去往敵國和親矢棚。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • ¥開啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個(gè)線程府喳,因...
    小菜c閱讀 6,415評(píng)論 0 17
  • 0.Android手機(jī)操作系統(tǒng)的四層架構(gòu)? Applications , Application Framewor...
    lucas777閱讀 7,846評(píng)論 0 16
  • 2017年5月17日 Kylin_Wu 標(biāo)注(★☆)為考綱明確給出考點(diǎn)(必考) 常見手機(jī)系統(tǒng)(★☆) And...
    Azur_wxj閱讀 1,813評(píng)論 0 10
  • 我 是 冰 山 上 圣 潔 美 麗 的 雪 蓮 花 心 中 有 一 個(gè) 美 麗 清 純 的...
    平凡的世界_538a閱讀 1,009評(píng)論 21 29
  • 【你懂的】 失控發(fā)票的風(fēng)波經(jīng)歷了一個(gè)雙休蒲肋,在老板的督促下,終于在周一夜幕降臨之時(shí)風(fēng)平浪靜钝满。事后兜粘,辦事的人開著小車趁...
    和小雨閱讀 233評(píng)論 0 0