• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆 - 224  文章 - 41  trackbacks - 0
            <2008年11月>
            2627282930311
            2345678
            9101112131415
            16171819202122
            23242526272829
            30123456

            享受編程

            常用鏈接

            留言簿(11)

            隨筆分類(159)

            隨筆檔案(224)

            文章分類(2)

            文章檔案(4)

            經(jīng)典c++博客

            搜索

            •  

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            可參考下面的文章:http://www.ibm.com/developerworks/cn/opensource/os-cn-android-actvt/index.html

            原文地址:http://blog.csdn.net/lihaifeng555/archive/2009/09/27/4599691.aspx

            在Android里,應(yīng)用程序是通過清單目錄定義的。每個(gè)應(yīng)用程序都是定義在AndroidManifest.xml里,其聲明了其進(jìn)入點(diǎn)(Entry Point)、通訊層(Communication Layer)、授權(quán)(Permission),以及活動(dòng)(Activity)和意圖(Intent)等。其中,有4個(gè)基礎(chǔ)組件,我們稱之為Android的主要組件,他們組成了豐富的Android應(yīng)用程序。

            Activity: Android 應(yīng)用程序的UI(User Interface)基本組件。

            Intent receiver: 可隨時(shí)被啟動(dòng)來處理Intent,并執(zhí)行其任務(wù)。

            Service: 非UI功能的后臺(tái)處理組件。

            Content provider: 跨程序的共享資料之存儲(chǔ)者。

            Android vs. Java ME vs. BREW

            一個(gè)BREW應(yīng)用程序,在所有絕大多數(shù)情況下,是由一個(gè)單獨(dú)的小程序組成,這個(gè)小程序是通過接收和發(fā)送活動(dòng)與手機(jī)的其他部分通信的。另一方面,你可以將一個(gè)Java ME應(yīng)用看做Midlet類的擴(kuò)展。這個(gè)Midlet有啟動(dòng)、停止、暫停、鍵處理(key handling)的功能,并且可以完成任何手機(jī)和應(yīng)用的交互。一個(gè)Java ME應(yīng)用程序通常由一個(gè)單獨(dú)的Midlet組成。

            Android應(yīng)用程序有許多活動(dòng),通過AndroidManifest.xml文件,這些活動(dòng)可以被注冊(cè)在手機(jī)中。 在面向Android的開發(fā)與面向其他手機(jī)開發(fā)工具包的開發(fā)之間,Android的multiactivity架構(gòu)或許是的他們之間主要的區(qū)別。正是這個(gè)事實(shí)使編寫模塊化、分割的代碼(modular, compartmentalized code)更容易。在BREW和Java ME中,開發(fā)人員可以執(zhí)行在Midlet或小程序范圍內(nèi)的大部分功能。在Android中,你可以寫一個(gè)活動(dòng)、內(nèi)容處理程序(content handler)、意圖接收器(intent receiver)、或服務(wù)以應(yīng)對(duì)幾乎任何東西。一旦你編寫了編輯文本文件的活動(dòng),通過發(fā)送和接收意向的行動(dòng),您可以引用這個(gè)活動(dòng)在您將來所有編寫的應(yīng)用中。這個(gè)這并不是說,這種架構(gòu)在BREW或Java ME中是不能實(shí)現(xiàn)的,他們只是必須在Java和C或C++編程的基礎(chǔ)上,或在BREW中通過繁瑣的擴(kuò)展實(shí)現(xiàn),而不是被平滑地集成到應(yīng)用框架中。

             


            Functionality

            就像Midlet,活動(dòng)使用了一系列的功能與外面的世界進(jìn)行交換。在他的基礎(chǔ)上,你編寫的活動(dòng)必須重寫方法OnCreate,你還要重寫其他功能,包括:onStop、onPause、onResume和onKeyDown。這幾個(gè)功能可以讓最大限度地將你開發(fā)的活動(dòng)綁定到Android手機(jī)中。在默認(rèn)情況下,在Eclipse中創(chuàng)建新的Android應(yīng)用程序?qū)?zhí)行一個(gè)“Hello,World”應(yīng)用程序。我會(huì)告訴你如何從這個(gè)基本應(yīng)用到功能齊全的畫面。

            如何添加圖片(Image)資源

            首先將圖片資源(例如menu_background.jpg)直接拷貝到/res/drawable文件夾中。此時(shí),Eclipse的Android插件(Android Plug-In)會(huì)自動(dòng)將一個(gè)新的ID值添加到R.java里。所以R.java文檔中會(huì)多加了一行指令如下:

            public static final int menu_background=0x7f020001;

            在應(yīng)用程序?qū)⒕陀么薎D值來取得這個(gè)圖標(biāo)文件,并顯示或處理它。

            如何定義XML布局 (Layout) 文件

            剛才已經(jīng)新增了一個(gè)圖片資源文件。此時(shí),在定義布局XML文件中,就可以引用此圖片。這些布局XML文件都放在在/res/layout文件夾中,其中Eclipse的Android插件已經(jīng)生成了一個(gè)main.xml文件。現(xiàn)在,你可利用Eclipse的 File>New>File菜單選項(xiàng)來生成新布局XML文件,例如:splash.xml。然后,以main.xml內(nèi)容為模板,將之拷貝到新的splash.xml里,下一步移動(dòng)<TextView>并且增加<ImageView>,內(nèi)容如下:

            <ImageView android:src="@drawable/menu_background"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent">
            </ImageView>

            在Android的XML布局文件里,使用@drawable/就能輕松地引用/res文件夾中的資源,例如上面的的android:src="@drawable/menu_background"。此外,layout_width和layout_height 則說明這個(gè)ImageButton顯示出來的大小(Size)。splash.xml也成為一項(xiàng)新的資源。所以在R.java裡也會(huì)自動(dòng)產(chǎn)生新的一行,如下:

            public static final int splash=0x7f030001;


            繪制啟動(dòng)畫面

             

            現(xiàn)在,你的初始畫面被定義完成,可以激活和顯示。你現(xiàn)有的Android活動(dòng)已制定了main.xml,所以你要轉(zhuǎn)移到新的初始布局。為了切換,更改OnCreate方法中的代碼:

            setContentView(R.layout.main);

            setContentView(R.layout.splash);

            運(yùn)行應(yīng)用程序,看著你新創(chuàng)建的啟動(dòng)畫面。到目前為止,如果你得到了錯(cuò)誤信息,檢查以確認(rèn)你的名字是否匹配。如果圖片沒有顯示,確保它被正確地放置在res/rawable文件夾,并splash.xml應(yīng)用了正確的名稱和文件。

               

            時(shí)間可以解決任何問題

             

            啟動(dòng)屏幕開始展現(xiàn),但啟動(dòng)畫面單獨(dú)作無聊的應(yīng)用程序,所以你需要進(jìn)入主菜單。你會(huì)使用簡(jiǎn)單的內(nèi)嵌定義線程來完成的定時(shí)器,有一些常數(shù)需要在定義線程前初始化。為了看上去完整,我將包括全部的OnCreate方法。代碼如下。

            Code Listing 2-1. Timing the Splash Screen

            long m_dwSplashTime = 3000;

            boolean m_bPaused = false ;

            boolean m_bSplashActive = true ;

            public void onCreate(Bundle icicle)

            {

            super .onCreate(icicle);

            //Draw the splash screen

            setContentView(R.layout.splash);

            //Very simple timer thread

            Thread splashTimer = new Thread()

            {

            public void run()

            {

            try

            {

            //Wait loop

            long ms = 0;

            while (m_bSplashActive && ms < m_dwSplashTime)

            {

            sleep(100);

            //Advance the timer only if we're running.

            if (!m_bPaused)

            ms += 100;

            }

            //Advance to the next screen.

            startActivity(new Intent(

            "com.google.app.splashy.CLEARSPLASH"));

            }

            catch (Exception e)

            {

            Log.e("Splash", e.toString());

            }

            finally

            {

            finish();

            }

            }

            };

            splashTimer.start();

            }

              

            到現(xiàn)在 , 你才開始看到一些 Java 代碼。這個(gè)簡(jiǎn)單的線程直到運(yùn)行時(shí)間計(jì)數(shù)器超過 m_dwSplashTime 才停止。雖然有實(shí)現(xiàn)一個(gè)計(jì)時(shí)器多種方式,選擇這種方式有兩個(gè)原因:


            此計(jì)數(shù)器可以暫停。該計(jì)時(shí)器只有m_bPaused標(biāo)志為false時(shí)才推動(dòng)。正如你將看到在一分鐘內(nèi),如果你調(diào)用活動(dòng)的OnPause方法,可以方便暫停計(jì)時(shí)器。這并不總是對(duì)啟動(dòng)畫面的需求,這對(duì)其他以時(shí)間為基礎(chǔ)的業(yè)務(wù)是重要的。
             


            移動(dòng)到下一個(gè)屏幕很簡(jiǎn)單,只要改變的m_bSplashActive標(biāo)記為false。推進(jìn)到下一個(gè)屏幕,如果你執(zhí)行這在時(shí)尚,不要求你作出的行動(dòng),然后取消更傳統(tǒng)的計(jì)時(shí)器。
             

            有了這個(gè)代碼,只要你以毫秒為單位設(shè)置m_dwSplashTime,你應(yīng)該看到啟動(dòng)畫面。當(dāng)時(shí)間到了或用戶使用按鍵中斷了啟動(dòng)畫面,startActivity將被調(diào)用。finish可以關(guān)閉啟動(dòng)活動(dòng),使用戶不必通過從主菜單上選擇Back返回。你需要執(zhí)行一項(xiàng)活動(dòng),接受CLEARSPLASH意圖的行動(dòng)。與此同時(shí),讓我們回顧一些其他重要活動(dòng)的方法你需要重寫。

             

            暫停,恢復(fù),沖洗,重復(fù)

            由于呼入電話,短信或其他中斷,你的活動(dòng)被掛起時(shí),暫停啟動(dòng)計(jì)時(shí)器,如下:

            protected void onPause()

            {

            super.onPause();

            m_bPaused = true;

            }

            對(duì)于這些大部分覆蓋的方法 , 在做任何事情之前 , 你需要調(diào)用超類。如果你查看計(jì)時(shí)器線程,如果m_bPaused是true,你會(huì)看到負(fù)責(zé)跟蹤時(shí)間的MS計(jì)數(shù)器保持時(shí)間沒有前進(jìn)。在這一點(diǎn)上,我相信你可以猜測(cè)onResume的樣子:

            protected void onResume()

            {

            super.onResume();

            m_bPaused = false;

            }

            當(dāng)你的應(yīng)用程序恢復(fù),計(jì)時(shí)器線程添加時(shí)間恢復(fù)到MS計(jì)數(shù)器。

             

            基礎(chǔ)的 Key Handling

            在活動(dòng)內(nèi),Key Handling是處理覆蓋onKeyDown方法。我們將使用此功能允許用戶取消你不完美的啟動(dòng)畫面。正如在本節(jié)開始你看到的計(jì)時(shí)器線程,通過m_bSplashActive設(shè)置,你在計(jì)時(shí)器循環(huán)中了異常語句。為了異常處理,你只需要重寫onKeyDown方法使之切換啟動(dòng)標(biāo)記為false。下面的代碼需要添加:

            public boolean onKeyDown(int keyCode, KeyEvent event)

            {

            //if we get any key, clear the splash screen

            super .onKeyDown(keyCode, event);

            m_bSplashActive = false ;

            return true;

            }

            現(xiàn)在 , 當(dāng)用戶按下任意鍵 , 屏幕將被推進(jìn)到下一個(gè)路程通過計(jì)時(shí)器循環(huán)。

             

            Clear intent

            有一件事你需要在啟動(dòng)畫面之前做 , 我相信你想知道有關(guān) startActivity 方法調(diào)用。這里應(yīng)該簡(jiǎn)單介紹一下intent。Intent是一個(gè)對(duì)象,在兩個(gè)或兩個(gè)以上活動(dòng)、內(nèi)容處理(content handlers)、意圖接收器(intent receiver)、或服務(wù)之間,可以作為一個(gè)通訊事件。你會(huì)使用com.google.app.splashy.CLEARSPLASH調(diào)用 startActivity 。當(dāng)startActivity被調(diào)用時(shí),Android搜索所有配置清單文件,尋找已注冊(cè)為CLEARSPLASH Intent action節(jié)點(diǎn)。

            你要增加一個(gè)新類MainMenu,其作為主菜單activity。它要繼承Activity類,實(shí)現(xiàn)OnCreate方法,在R.layout.main中調(diào)用setContentView方法。你要打開的AndroidManifest.xml并增加新的 activity 元素。在 </activity> 結(jié)束符之后, 你應(yīng)該插入以下內(nèi)容:

            <activity android:name=".MainMenu"

            android:label="@string/app_name">

            <intent-filter>

            <action android:name=

            "com.google.app.splashy.CLEARSPLASH"/>

            <category android:name=

            "android.intent.category.DEFAULT"/>

            </intent-filter>

            </activity>

            確定活動(dòng)的名稱為 .MainMenu 。這會(huì)告訴 Android 加載和運(yùn)行 Java 類。在 Intent filer 標(biāo)簽中 , 注冊(cè)為 com.apress.splash.CLEARSPLASH 的 Intent Action 。在現(xiàn)實(shí)中,名稱意圖可能是beef.funkporium.swizzle,只要名稱在startActivity調(diào)用和前面的Android配置清單中一致,所有正確的事情應(yīng)繼續(xù)發(fā)生。

             

            一項(xiàng)活動(dòng)的生命周期

            Activity的生命周期被包括在Google的文檔中。但是,如果你先仔細(xì)考慮生產(chǎn)Activity的底層原理,你不能錯(cuò)過這個(gè)重要的信息。在這一點(diǎn),你的啟動(dòng)畫面,你應(yīng)該準(zhǔn)備好推出。

            為了說明,我還增加了以功能在啟動(dòng)畫面活動(dòng)中:

            protected void onStop()

            {

            super.onStop();

            }

            protected void onDestroy()

            {

            super.onDestroy();

            }

            如果你方斷點(diǎn)在上面活動(dòng)的所有功能,在調(diào)試模式下運(yùn)行它,你會(huì)看到斷點(diǎn)與下面順序一致:

            1. onCreate

            2. onStart

            3. onResume

            4. 在這一點(diǎn)上,你的活動(dòng)目前已經(jīng)運(yùn)行。在三秒鐘內(nèi),計(jì)時(shí)器線程將達(dá)到結(jié)束,并調(diào)用startActivity結(jié)算的意圖。下一步,它將調(diào)用finish,它告訴Android關(guān)閉啟動(dòng)畫面活動(dòng)。

            5. onPause

            6. onStop

            7. onDestroy

            5. onPause

            6. onStop

            7. onDestroy

            從開始到結(jié)束 Activity , 這是一般的生命周期來。你可以找到對(duì)生命和時(shí)代的 Android 活動(dòng)更全面地披露 , 在谷歌的文檔活動(dòng)中 http://code.google.com/android/reference/android/app/ Activity.html 。你甚至可以找到漂亮圖形。從本質(zhì)上講,手機(jī)使用了以前的組合功能提醒你的主要事件可以發(fā)生在你的應(yīng)用程序:?jiǎn)?dòng),關(guān)閉,暫停和恢復(fù)。我已經(jīng)討論過,Activity將要成為任何傳統(tǒng)應(yīng)用的的核心組件;他們給你控制了屏幕,能夠接收用戶輸入。

             

            總結(jié)

            到目前為止,我已經(jīng)探討了活動(dòng)如何成在手機(jī)中,他們?nèi)绾螁?dòng)和停止,以及他們?nèi)绾闻c基礎(chǔ)層溝通。我演示了如何顯示一個(gè)簡(jiǎn)單的XML視圖屏幕,以及如何活性之間切換兩個(gè)反應(yīng)都在一個(gè)關(guān)鍵的事件和結(jié)束時(shí)的一個(gè)指定的時(shí)間量。在短期內(nèi),你需要了解更多有Android如何使用意向,意圖接收器,過濾器和意圖溝通。要做到這一點(diǎn),你需要一個(gè)示例應(yīng)用程序。

             

            創(chuàng)建一個(gè)Intent Receiver

            Intent Receiver是Android重要的組成部分,從它的名字可以看出其作用。它的作用是等待接收注冊(cè)的Intent Action,Android是按照BREW的通知模式實(shí)現(xiàn)的。我們將使用一個(gè)簡(jiǎn)單的應(yīng)用,展現(xiàn)一個(gè)復(fù)雜的Intent Receiver任務(wù):輸入文本消息的接收和響應(yīng)。

             

            事情的起因

            我們開始設(shè)想這樣一幅畫面:一天下午,當(dāng)你回到你的辦公桌,你發(fā)現(xiàn)你的辦公桌,從地毯到天花板與可愛的粉紅色的圖片,鋪滿最令人討厭的圖畫。你知道這是誰在做,現(xiàn)在是你報(bào)復(fù)的時(shí)候了。你也知道你的工程部副總裁最厭惡一首特殊的歌。這首歌是 “ La Bamba “ 。讓你決定通過一個(gè)休眠程序操縱你同事的Android手機(jī)。我會(huì)告訴你如何制作一個(gè)Android應(yīng)用程序,收到特定的短信后,播放這種恥辱效應(yīng)的音頻文件。這會(huì)使你的副總對(duì)你的新敵人產(chǎn)生強(qiáng)烈的憤慨。同時(shí),你要給他一個(gè)機(jī)會(huì)關(guān)閉聲音了。這種惡作劇程序要求Intent Receiver,Activity,Service,以及所有三種方式進(jìn)行通信。

               

            這有什么實(shí)際的通途嗎?這可能有嗎?

            這是一個(gè)很好的問題。雖然表面上看來不是很實(shí)用應(yīng)用,我相信,如果有一點(diǎn)想像力,你可以發(fā)現(xiàn)其很多重要的現(xiàn)實(shí)用途:從推送電子郵件通知到內(nèi)部電話應(yīng)用通信。

            你將向前邁進(jìn)四個(gè)階段。在每個(gè)階段,你將了解更多關(guān)于Intent receives,services,所有這些應(yīng)用程序之間的相互作用件:


            通知收到一個(gè)短信
             


            打開短信的內(nèi)容和找到特殊的凈荷
             


            當(dāng)短信到達(dá)Activity啟動(dòng),并且意識(shí)到啟動(dòng)發(fā)生在接收器的控制下
             


            開始一個(gè)新的服務(wù),將播放音頻文件
             

               

            使用Intent Receiver

            在你開始編寫Intent Receiver之前,你需要了解你為什么會(huì)使用他。Intent Receriver沒有或幾乎沒有內(nèi)存占用、linkage和系統(tǒng)開銷。在啟動(dòng)時(shí),一個(gè)活動(dòng)必須將所有大量的引入的類加載,Intent Receriver則沒有這些約束。由于某種類型的新Intent可以達(dá)到破碎頻率(例如網(wǎng)絡(luò)狀態(tài)更新),一個(gè)輕量級(jí)的對(duì)象必須在分析數(shù)據(jù)的第一階段。如果它是一個(gè)適當(dāng)?shù)臅r(shí)間喚醒一個(gè)更大的用戶界面程序或大幅后臺(tái)服務(wù),意圖接收機(jī)應(yīng)采取這種行動(dòng)。

             

            提示:意圖接收器可以經(jīng)常的啟動(dòng)和關(guān)閉(這依靠他們的監(jiān)聽),試圖讓它們變地重量輕,使用盡可能少的類庫。你的用戶不會(huì)高興,如果他們電話在緩慢地爬行,因?yàn)槟阋呀?jīng)插入到太多特定的事件處理開銷。

             

            編寫Intent Receiver

            第一件事首先你需要?jiǎng)?chuàng)建一個(gè)這個(gè)小惡作劇應(yīng)用程序建立新項(xiàng)目。在源目錄中,創(chuàng)建一個(gè)新類,將成為新的Intent Receiver。在第一階段,它看起來應(yīng)該像這樣:

            public class PrankSMSReceiver extends IntentReceiver

            {

            public void onReceiveIntent

            (Context context, Intent intent)

            {

            return;

            }

            }

            現(xiàn)在你已經(jīng)設(shè)定了階級(jí) , 你必須告訴你想要 Android 接收 SMS 事件。你可以通過修改 AndroidManifest.xml 文件給你許可和登記 RECEIVE_SMS 的 Intent action 。

             

            權(quán)限

            運(yùn)營(yíng)商,用戶,甚至開發(fā)人員可能不希望給Android應(yīng)用自由支配,貫穿其手機(jī)和網(wǎng)絡(luò)的特權(quán)層。因此,谷歌推出一種被移動(dòng)發(fā)人員認(rèn)可的權(quán)限概念。為了能夠接收短信息,你需要通知手機(jī)你可以接收。

            在Android中,所有元素的權(quán)限聲明在特別的配置文件中,你添加的權(quán)限在<manifest>標(biāo)記后(代碼2-2)。該示例應(yīng)用程序?qū)⒈环Q為PrankApp。其活動(dòng)主要是rankActivity。

            Code Listing 2-2. Adding Permissions to Receive SMS Messages

            <?xml version="1.0" encoding="utf-8"?>

            <manifest xmlns:android=

            "

            package="com.apress.book.PrankApp">

            <uses-permission android:name=

            "android.permission.RECEIVE_SMS" />

            沒有權(quán)限標(biāo)志,Android將你的應(yīng)用程序無法啟動(dòng)當(dāng)它接收到一個(gè)短信。還有其他的權(quán)限我需要涵蓋你向前看。在此期間 , 你可以找到所有在列表的權(quán)限 Android 的文件資料 http://code.google.com/android/reference/android/ Manifest.permission.html 。

             

            向我發(fā)送短信!

            現(xiàn)在,你已經(jīng)允許進(jìn)行與手機(jī)的SMS層交互,你必須告訴手機(jī)做什么,當(dāng)一個(gè)新的文本信息到達(dá)時(shí)。要做到這一點(diǎn),你必須打開AndroidManifest.xml文件,添加一個(gè)新的Intent Receiver。代碼清單2-3顯示了要插入的代碼。

            Code Listing 2-3. Registering the New Intent Receiver for

            Incoming SMSs

            </activity>

            <receiver android:name=

            "PrankSMSReceiver"android:enabled="true">

            <intent-filter>

            <actionandroid:name="android.provider.Telephony.SMS_RECEIVED"

            />

            <categoryandroid:name="android.intent.category.DEFAULT" />

            </intent-filter>

            </receiver>

            這就是你每次必須要接受的 Intent notification , 當(dāng)手機(jī)得到一個(gè)接收到的 SMS 。

             

               

            在 Action 中分析 Intent Receiver

            要完成這個(gè)要比我們想象的有一點(diǎn)困難。一個(gè)進(jìn)程必須在一個(gè) DDMS 中運(yùn)行 。但在大多數(shù)情況下,你不想讓應(yīng)用程序運(yùn)行,除非新的事件觸發(fā)它。這問題的解決方案在Eclipse IDE中只是一個(gè)小小的把戲。當(dāng)你一步一步往下走時(shí),這可能會(huì)一點(diǎn)一點(diǎn)變得復(fù)雜。

            在你的onReceiveIntent方法中放置一個(gè)斷點(diǎn)。開始調(diào)試應(yīng)用程序,并讓模擬器位于“Hello World,PrankActivity”屏幕上。在Eclipse中,切換視圖到DDMS。你可以按這命令+ F8鍵幾次或選擇菜單 Window ?? Open Perspective ?? DDMS 。

             

            沿著左邊窗口,在Device選項(xiàng)卡上,你現(xiàn)在應(yīng)該看有一個(gè)綠色bug圖標(biāo)在你的應(yīng)用旁邊。這是DDMS告訴你調(diào)試器附加到你的PrankApp進(jìn)程中。在它的下面是Emulator Control選項(xiàng)卡。在這里你可以發(fā)送短信消息。首先輸入任何一個(gè)電話號(hào)碼,選擇SMS,鍵入一個(gè)測(cè)試消息,并按下Send。

             

            如果你的配置正確,你應(yīng)該看到Eclipse切換到Debug透視圖,并停止在你的新設(shè)置斷點(diǎn)上。

             

            注意:如果沒有發(fā)生,首先確保你設(shè)置了權(quán)限正確。如果他們不正確,你應(yīng)該看到一個(gè)失敗的權(quán)限信息顯示在DDMS屏幕底部的LogCat標(biāo)簽中。此外,請(qǐng)確保你的應(yīng)用程序已經(jīng)在運(yùn)行,并在Devices選項(xiàng)卡有綠色調(diào)試圖標(biāo)在它的旁邊。如果所有這些都不奏效,比較你的項(xiàng)目與文中的示例。

             

            目前為止,如果你正確地完成了。你的Intent的onReceiveIntent功能被調(diào)用,當(dāng)每一個(gè)SMS消息發(fā)送到手機(jī)上。接下來,你就必須弄清楚如何得到短信的內(nèi)容。

             

            什么是在一個(gè)SMS中?

            可悲的是,到目前為止Android關(guān)于接收和過濾SMS信息的文檔只不過是混亂的。我懷疑這不是一項(xiàng)需要告訴開發(fā)人員的重要功能。我不同意這些優(yōu)先事項(xiàng),但是使我有機(jī)會(huì)填補(bǔ)空缺。

            下面是methodonReceiveIntent的代碼,功能是監(jiān)聽新的SMS信息:

            public void onReceiveIntent

            (Context context, Intent intent)

            {

            SmsMessage msg[] =

            Telephony.Sms.Intents.getMessagesFromIntent(intent);

            for(int i = 0; i < msg.length; i++)

            {

            String msgTxt = msg[i].getMessageBody();

            if (msgTxt.equals("0xBADCAT0_Fire_The_Missiles!"))

            {

            //Start the pranking here

            }

            }

            return;

            }

            你還需要輸入兩個(gè)類庫來完成這項(xiàng)工作:

            Import android.telephony.gsm.SmsMessage;

            Import android.provider.Telephony;

            getMessageFromIntent 方法是在 Telephony 類中 , 這將返回 SMS 信息的數(shù)組。現(xiàn)在剩下的就是得到短信的有效載荷。你要找的觸發(fā)惡作劇活動(dòng)的特殊代碼為文本

            “ 0xBADCAT0_Fire_The_Missiles ! ”

            它必須是一個(gè)適當(dāng)?shù)莫?dú)特組合,以便它不會(huì)被觸發(fā)事故。你不會(huì)希望自己的惡作劇失火并提醒受害人太早的。

            注意:在Android里,沒有記載的功能是很可能還沒有完成。由于接收短信的文檔幾乎不存在,你應(yīng)該會(huì)有些變化在如何處理手機(jī)簡(jiǎn)訊上。更可能的是整體的方法應(yīng)該是相似的,但它有把握地認(rèn)為其中的一些細(xì)節(jié)將改變SDK的前到達(dá)它的最終版本。這個(gè)例子是有關(guān)學(xué)習(xí)如何使用意圖接收器多是有關(guān)文本的消息通信資料。

             

            觸發(fā)活動(dòng)

            重要的是要記住,意圖接收器的生命周期短,只有只要方法調(diào)用onReceiveIntent。一旦出于這一職能,Android是免費(fèi)殺死進(jìn)程中運(yùn)行你的應(yīng)用程序。任何異步功能會(huì)死去,如果是一個(gè)十分棘手的死亡開始。如果你想要做超越了簡(jiǎn)單的處理方法內(nèi)的任何事情,你需要啟動(dòng)服務(wù)或活動(dòng)。既然你要同時(shí)播放音樂和警報(bào)你的受害者,他們?nèi)ミ^了,你需要啟動(dòng)的一項(xiàng)活動(dòng)。你完成此情況如下:

            if (msgTxt.equals("0xBADCAT0_Fire_The_Missiles!"))

            {

            //Start the Activity

            Intent startActivity = new Intent();

            startActivity.setLaunchFlags(Intent.NEW_TASK_LAUNCH);

            startActivity.setAction("com.apress.START_THE_MUSIC");

            context.startActivity(startActivity);

            }

            你會(huì)看到這里是增補(bǔ) NEW_TASK_LAUNCH 在 setLaunchFlags 。你需要做任何你要發(fā)送的 Intent action , 將啟動(dòng)一項(xiàng)新的活動(dòng)。此外,正如你在啟動(dòng)畫面示例應(yīng)用程序,你必須添加一個(gè)新的行動(dòng),你的Activity的Intent filter。那個(gè)過程應(yīng)該看起來很熟悉:

            <intent-filter>

            <action android:name="android.intent.action.MAIN" />

            <action android:name="com.apress.START_THE_MUSIC" />

            <category android:name=

            "android.intent.category.LAUNCHER" />

            <category android:name=

            "android.intent.category.DEFAULT" />

            </intent-filter>

            現(xiàn)在 , 如果你在前面正確地添加了代碼 , 當(dāng)你從 DDMS 透視圖中 發(fā)送 SMS 消息時(shí) , 你應(yīng)該看到你的應(yīng)用跳出到前臺(tái) , 顯示 “Hello World ,PrankActivity ” 文本在屏幕上。

             

            索具的活動(dòng)

            一個(gè)最后的工作你需要添加 , 在得到卑鄙的音樂播放服務(wù)之前 : 裝配 Activity , 以回應(yīng)你的 Intent Receiver 發(fā)送的活動(dòng) 。如果應(yīng)用程序正常啟動(dòng),你要立即關(guān)閉了。同樣,如果可以通過菜單啟動(dòng),這樣你的惡作劇的計(jì)劃就會(huì)過早的曝光。要做到這一點(diǎn),你必須檢索發(fā)射的Intent,并調(diào)用getAction方法來計(jì)算出在什么情況下,它已經(jīng)啟動(dòng)。該P(yáng)rankActivity的OnCreate方法現(xiàn)在看起來應(yīng)該代碼2-4。

            Code Listing 2-4. Launching on a Specific Intent Action

            public void onCreate(Bundle icicle)

            {

            super .onCreate(icicle);

            Intent i = getIntent();

            String action = i.getAction();

            if (action != null &&

            action.equals("com.apress.START_THE_MUSIC"))

            {

            setContentView(R.layout.pranked);

            //We'll need to start the music service here

            }

            else

            finish();

            }

             

            首先你會(huì)得到發(fā)起 Activity 的Intent 。使用目前得到的 Intent , 你可以用 getAction 方法檢索調(diào)用的行動(dòng)。這個(gè)將返回一個(gè)包含啟動(dòng)事件的字符串,你核對(duì)你的著名音樂行動(dòng)列在原來的XML。如果在啟動(dòng)事件為你的活動(dòng)來自正常的方式(從菜單或從啟動(dòng)調(diào)試器),該行動(dòng)字符串將是null。如果是這樣的話,你要立即使用finish方法關(guān)閉活動(dòng)。

            注意:OnCreate方法被調(diào)用當(dāng)你的應(yīng)用被首次啟動(dòng)時(shí)。如果你已經(jīng)啟動(dòng)你的應(yīng)用程序,然后退出(使用返回鍵),應(yīng)用程序仍然在后臺(tái)運(yùn)行。如果在這時(shí),你發(fā)送短信,你的活動(dòng)將回到前臺(tái),但其OnStart方法將調(diào)用而不是OnCreat。

             

            你今天想羞辱誰呢?

            雖然可能有些矯枉過正,你要使用Android的service對(duì)象來處理音樂播放。我打算這樣做有因?yàn)榱韨€(gè)原因:

            n         ?? 這是一個(gè)好的機(jī)會(huì)來展示以簡(jiǎn)單的方式service的使用,在簡(jiǎn)單的環(huán)境。

            n         ?? 潛在的,它會(huì)讓你啟動(dòng)音樂不用看到應(yīng)用程序,使你的惡作劇的應(yīng)用程序更卑鄙。

            神經(jīng)與服務(wù)

            為什么你要使用的服務(wù)?從本質(zhì)上講,它意味著是一個(gè)對(duì)象,與用戶界面分離的可運(yùn)行地過程。這是完美的情況,當(dāng)一個(gè)開發(fā)人員希望的功能(無論是網(wǎng)絡(luò)或多媒體相關(guān))能夠獨(dú)立運(yùn)行。例子包括:音頻播放,網(wǎng)絡(luò)交易的后臺(tái),和邪惡的惡作劇程序。雖然服務(wù)允許多個(gè)應(yīng)用程序(打開通信信道)與他們綁定,你會(huì)使用它作為一個(gè)簡(jiǎn)單的后臺(tái)進(jìn)程。同樣,services有很多用途不只是這個(gè)簡(jiǎn)單的例子。

            創(chuàng)建service

            添加一個(gè)新類的源碼包。我已經(jīng)再次調(diào)用PrankService(沒有點(diǎn)創(chuàng)意)。在最基本的層面,service要重寫onBind方法。要獲得服務(wù)類編譯,它必須看,至少有一點(diǎn)點(diǎn),如代碼2-5。

            Code Listing 2-5. A Stripped-Down Service

            public class PrankService extends Service

            {

            public IBinder onBind(Intent intent)

            {

            return null;

            }

            }

            在這個(gè)例子中,你不會(huì)使用該服務(wù)onBind方法進(jìn)行互動(dòng)。你可以簡(jiǎn)單地啟動(dòng)和停止服務(wù)在你的主要活動(dòng)內(nèi)。要做到這一點(diǎn),你必須重寫兩個(gè)方法在服務(wù)類:

            OnStart (Int startId ,Bundle argument )
            onDestroy()

            當(dāng)OnStart被調(diào)用時(shí),你會(huì)開始播放的媒體文件。當(dāng)服務(wù)被破壞,就會(huì)明確地停止。這不是必然要求,但你會(huì)明白。

            啟動(dòng)服務(wù)

            開始一個(gè)新的服務(wù)應(yīng)該類似于開始活動(dòng)。自從你已經(jīng)接觸到這是幾次,我就在給你一段代碼,讓你整理一下。 調(diào)用前面列出的PrankActivity OnCreate方法。簡(jiǎn)單替換注釋“ We’ll need to start the music service here ”用下面的代碼行:

            startService(new Intent

            ("com.apress.START_AUDIO_SERVICE"), null );

            同樣,這個(gè)看上去很熟悉。啟動(dòng)Activity和啟動(dòng)service之間唯一的區(qū)別是(除了不同的方法調(diào)用)是隨Intent傳遞bundle(實(shí)際上是一個(gè)地圖或哈希表)參數(shù)的能力。這bundle將被傳遞到OnCreate方法服務(wù)。

            啟動(dòng)音樂

            BREW和Java一樣,Android的媒體播放(簡(jiǎn)單的播放/停止計(jì)算)非常簡(jiǎn)單易用。當(dāng)你服務(wù)的OnStart函數(shù)被調(diào)用,你會(huì)加載和播放/res/raw 目錄中的測(cè)試音頻文件首先要做的是復(fù)制音頻樣本文件導(dǎo)入/res/raw(如果沒有這個(gè)目錄,繼續(xù)并創(chuàng)建它)。下一步,放下羞辱,并復(fù)制寫入尊重,音頻文件原始文件夾。如果你使用Eclipse,你應(yīng)該添加相應(yīng)的元素R.raw。在你的情況下,它的R.raw.test。

            現(xiàn)在你有一個(gè)音樂文件的引用,你可以添加程序 PrankService 的要求如下 :

            public void onStart(int startId, Bundle arguments)

            {

            MediaPlayer p;

            super .onStart(startId, arguments);

            player = MediaPlayer.create(this , R.raw.test);

            player.start();

            }

            請(qǐng)記住 , 是一個(gè)重寫的 OnStart 方法 , 因此你必須調(diào)用父類同一函數(shù)或 Android 將變得不穩(wěn)定。在這一點(diǎn)上,你需要用MediaPlayer的靜態(tài)類創(chuàng)建一個(gè)新的媒體播放器對(duì)象。因?yàn)閟ervice是context的子類,你將一個(gè)指針傳遞給你當(dāng)前的context和靜態(tài)變量代表你的測(cè)試媒體。在這一點(diǎn)上,你可以調(diào)用play,現(xiàn)在你可以開始忙了。播放會(huì)繼續(xù)在后臺(tái)運(yùn)行,直到stopService這個(gè)方法是由你的主Activity調(diào)用。

            當(dāng)stopService被調(diào)用時(shí),下面的方法將調(diào)用:

            public void onDestroy()

            {

            super.onDestroy();

            player.stop();

            }

             

            同情的行動(dòng)

            既然你是一個(gè)不錯(cuò)的愛開玩笑的人 , 你要給你的受害者一個(gè)臺(tái)階下。正如你之前見過的,Activity是由Intent Receiver觸發(fā)的,在活動(dòng)啟動(dòng)服務(wù)的時(shí)間點(diǎn)上。正如你剛才看到的,service是負(fù)責(zé)播放噪聲激怒你副總工程師。同樣,因?yàn)槟闶侨蚀鹊脑谀愕膱?zhí)行回報(bào)的同時(shí),你必須為受害者設(shè)計(jì)關(guān)閉音樂方法。添加在你的PrankActivity下面的方法可以實(shí)現(xiàn)你善意的行動(dòng):

            public boolean onKeyDown(int keyCode, KeyEvent event)

            {

            stopService(new Intent(

            "com.apress.START_AUDIO_SERVICE"));

            finish();

            return true;

            }

             

            配置文件

            下面是表現(xiàn)如下所示 :

            <service android:name=".PrankService">

            <intent-filter>

            <action android:name=

            "com.apress.START_AUDIO_SERVICE" />

            <category android:name=

            "android.intent.category.DEFAULT" />

            </intent-filter>

            </service>

             

             

            禪宗和報(bào)復(fù)的藝術(shù)

            通過不光明正大的小惡作劇應(yīng)用程序的使用 , 你應(yīng)該明白了 Intents ,Intent Receivers ,services 和Activities 如何 共同在先進(jìn)的 、 主要是后臺(tái) 的 應(yīng)用程序中運(yùn)行的。我現(xiàn)在要改變一下方式,一步一步做,你做了什么以及如何實(shí)現(xiàn)它。

            讓我做的更好

            你做了以下內(nèi)容:

            1。你使用正確的權(quán)限和系統(tǒng)接收器的意圖級(jí)短信的意圖安排的對(duì)象是PrankSMSReciever每次實(shí)例化一個(gè)手機(jī)上的SMS到達(dá)。如果你的Intent Receiver發(fā)現(xiàn)一個(gè)非常特定的SMS的有效載荷,它將通過發(fā)送Intent將啟動(dòng)你的活動(dòng)。

            2。這項(xiàng)活動(dòng)名為PrankActivity,會(huì)監(jiān)聽被PrankSMSReceiver的特定intent action。當(dāng)它收到確切intent action,你的活動(dòng)將顯示一個(gè)“gotcha”消息給受害者。同時(shí),該活動(dòng)將發(fā)出意圖旨在啟動(dòng)服務(wù)。如果在任何時(shí)候受害人/用戶按下一個(gè)電話上的鍵,應(yīng)用程序?qū)⑼顺觯魳贩?wù)將終止。

            3。服務(wù)類,稱為PrankService,監(jiān)聽PrankActivity的intent,將啟動(dòng)并開始播放令人討厭,預(yù)定義的音頻文件。它將繼續(xù)播放,直到它被要求停止通過PrankActivity的調(diào)用方法stopService。

            注意:此示例應(yīng)用程序不涉及手機(jī)的本地短信應(yīng)用。因?yàn)樗械膇ntent receiver傳入的通知意圖,你的應(yīng)用將被爭(zhēng)奪用戶與Android的關(guān)注短信收件箱的應(yīng)用。在生產(chǎn)中,這可能需要相當(dāng)計(jì)時(shí)器也許觸發(fā)文本有效載荷,這是一個(gè)微妙多一點(diǎn) “0xBADCAT0_Fire_The_Missiles !”

             

            在Android中移動(dòng)數(shù)據(jù)

            最后,你需要把重點(diǎn)放在內(nèi)容解析器。 Android不會(huì)給SDK特別的手機(jī)文件系統(tǒng)的訪問權(quán)限,如Brew一樣。它也沒有提供一個(gè)RecordStore,像Java ME一樣。在你的Activities、Intent  Receiver和services之間,你傳遞數(shù)據(jù)的主要方法是必須通過ContentResolver超類。雖然你可以存儲(chǔ)數(shù)據(jù)通過文件,參數(shù),和其他數(shù)據(jù)庫,可以采取許多形式,Android附帶的幾個(gè)重要內(nèi)置content resovlers。這里有一個(gè)列表,Android的主要content resovlers,你可能要經(jīng)常互動(dòng)基礎(chǔ)上:


            瀏覽器

            書簽
            搜索歷史


            電話呼叫
            通話記錄
            最近通話


            聯(lián)系

            系統(tǒng)設(shè)置
            硬件設(shè)置(藍(lán)牙,網(wǎng)絡(luò)設(shè)置)
            軟件設(shè)置

            Android 的文檔提供了非常好的示例 :http://code.google.com/android/ devel /data/contentproviders.html #usingacp 。馬上我要給你演示怎樣添加一個(gè)書簽到手機(jī)瀏覽器的書簽列表。首先,你要搜索當(dāng)前的書簽列表,查看你的鏈接是否存在。第二,你要添加書簽,如果不存在。

             

            注意:可以創(chuàng)建你自己的content provider,作為一種方式,為了公共訪問封裝Android的SQLite的執(zhí)行。你將進(jìn)入如何在后面的章節(jié)中這一點(diǎn)。現(xiàn)在你只是去處理content resolver交給的“client”方面。

             

            Android采用了自定義的SQLite實(shí)現(xiàn),來存儲(chǔ)本地信息。如果你不熟悉SQL的基礎(chǔ)知識(shí),現(xiàn)在也許是一個(gè)學(xué)習(xí)的機(jī)會(huì)。為表述方便,我要假設(shè)你了解基本的SQL查詢命令。如果你需要進(jìn)一步提高,Apress上有一個(gè)很好的資源http://apress.com/book/ catalog?category=145 。

             

            無恥的自我推銷

            讓我們說一下你的應(yīng)用程序中“about”部分,你想有一個(gè)按鈕,添加你的商業(yè)軟件網(wǎng)頁到用戶的web書簽。你要確保它不添加兩次,如果你的用戶有再次點(diǎn)擊該按鈕意外。為了使這個(gè)實(shí)例簡(jiǎn)單,你將觸發(fā)這個(gè)事件在你示例應(yīng)用程序中,當(dāng)用戶按下一個(gè)鍵。

            注意:在一個(gè)有趣的注意,如果你需要證明,作為一個(gè)開發(fā)人員,Android是還沒有完全成熟的,你只要看看比對(duì)下文件的android.content.ContentResolver方法getDataFilePath,其中規(guī)定: “ 請(qǐng)不要使用此功能!有人說這一點(diǎn),他們不應(yīng)該。你沒有直接的訪問文件內(nèi)的內(nèi)容提供商。不要碰這個(gè)。走開。 “ 這是好,知道即使是對(duì)Android的文檔技術(shù)作家有幽默感。

             

            獲取用戶的書簽

            這應(yīng)該是顯而易見的,至少在這一點(diǎn),開發(fā)人員可以做一些非常邪惡的事情,訪問用戶的書簽。目前還不清楚,在這一點(diǎn),Android會(huì)做什么以防止發(fā)生這類事情。我想這得由運(yùn)營(yíng)商來鎖定或監(jiān)視此行為。在任何情況下,你將使用一個(gè)調(diào)用方法managedQuery,它將返回一個(gè)列表用戶的書簽:

             

            Cursor bookmarks =

            android.provider.Browser.getAllBookmarks

            (getContentResolver());

            int urlColumn = bookmarks.getColumnIndex(

            android.provider.Browser.BookmarkColumns.URL );

            Cursor results;

            String[] proj = new String[]

            {

            android.provider.BaseColumns._ID,

            android.provider.Browser.BookmarkColumns.URL,

            android.provider.Browser.BookmarkColumns.TITLE

            };

            results =

            managedQuery(android.provider.Browser.BOOKMARKS_URI,

            proj, null ,

            android.provider.Browser.BookmarkColumns.URL

            + " ASC");

            現(xiàn)在我將分解每一個(gè)操作。你首先要書簽網(wǎng)址列索引。再次,因?yàn)锳ndroid通過SQL格式提供其多數(shù)內(nèi)部數(shù)據(jù)的訪問,你應(yīng)該習(xí)慣于用數(shù)據(jù)庫的方式引你保存的信息。接下來,你將設(shè)置游標(biāo),一個(gè)類似Java ME中RecordStore枚舉對(duì)象,設(shè)置字符串?dāng)?shù)值的映射。因?yàn)槟阒魂P(guān)心列包含的網(wǎng)址,它保存非常簡(jiǎn)單。方法調(diào)用managedQuery是調(diào)用將返回你的數(shù)據(jù)。你可以通過URI中為書簽存儲(chǔ)字符串,交給你了簡(jiǎn)單的映射數(shù)值,不需要where語句,并告訴它按降序排列的網(wǎng)址。

             

            搜索結(jié)果

            搜索結(jié)果很簡(jiǎn)單只要迭代游標(biāo)對(duì)象,是通過簡(jiǎn)單的光標(biāo)迭代對(duì)象和退出一列從URL字符串ID你檢索前 :

            Cursor results =

            android.provider.Browser.getAllBookmarks

            (getContentResolver());

            int urlColumn =

            results.getColumnIndex

            (android.provider.Browser.BookmarkColumns.URL);

            results.first();

            do

            {

            //url is a method param

            //containing what we're looking for

            if(results.getString(urlColumn).equals(url))

            return false;

            } while (results.next());

            你可以做更多的基于 URL 的內(nèi)容 , 但現(xiàn)在你會(huì)只是看你的 www.apress.com 鏈接。很明顯,如果此代碼的運(yùn)行是上述Apress網(wǎng)址,你不會(huì)找到它。因?yàn)橛脩粝M砑淤F公司的網(wǎng)址在虛擬的“About” ” 部分中,你也要給他們。

            使用Content Resolver添加邪惡公司網(wǎng)址

            也許他們不是邪惡,但你加入他們。由于Apress也許是公司最邪惡那里(不是我有偏見,記住),你讓他們擺脫它,只此一次。下面是一個(gè)美麗的ContentReceiver方式添加書簽記錄:

            ContentValues inputValues = new ContentValues();

            inputValues.put

            (android.provider.Browser.BookmarkColumns.BOOKMARK,

            "1");

            inputValues.put

            (android.provider.Browser.BookmarkColumns.URL,

            "

            inputValues.put

            (android.provider.Browser.BookmarkColumns.TITLE,

            "Apress, the not so evil company");

            ContentResolver cr = getContentResolver();

            Uri uri =

            cr.insert

            (android.provider.Browser.BOOKMARKS_URI,

            inputValues);

            想大多數(shù)軟件開發(fā)工具包,有不止一種方法來完成相同的任務(wù)。早些時(shí)候,你有更復(fù)雜的方法加書簽。這個(gè)方法是有用的,因?yàn)樗o你一個(gè)參考如何添加元素通過ContentResolver不具有輔助功能。現(xiàn)在,這里的簡(jiǎn)單的方法:android.provider.Browser.saveBookmark(this,“Apress”,url);幫助函數(shù)會(huì)啟動(dòng)一個(gè)對(duì)話框,要求用戶確認(rèn)增加書簽。這可能是最用戶友好的方式來添加書簽,除非你想控制對(duì)話框的模樣。

            平衡早餐的組成

            在過去的三個(gè)例子你探討了Android的所有主要構(gòu)建模塊。一開始你看到了實(shí)用的啟動(dòng)畫面。這讓你探索了基本知識(shí)關(guān)于啟動(dòng)、維護(hù)和移動(dòng)通過Activity對(duì)象。這是你學(xué)習(xí)intents and interprocess/object communication邁出的第一步。使用和傳遞意圖在活動(dòng),服務(wù),內(nèi)容處理,接收器和意圖之間可能是一個(gè)最重要的事情,這是Android與其他移動(dòng)環(huán)境的區(qū)別。

            對(duì)于Activity和通信基礎(chǔ)知識(shí),你已經(jīng)有了經(jīng)驗(yàn),你繼續(xù)學(xué)習(xí)服務(wù)和意圖接收器。要使用這兩個(gè)組成部分,你烹調(diào)了 狡猾的 惡作劇應(yīng)用程序,既能強(qiáng)迫你使用所有3個(gè)組建(活動(dòng),服務(wù),和意圖的接收器),使所有三個(gè)互相溝通。幾乎是旁注,你研究什么需要得到通知時(shí),短信在手機(jī)上到達(dá)。最后,你探討如何檢索和寫入的內(nèi)容是解析器本機(jī)設(shè)備:瀏覽器的書簽數(shù)據(jù)庫。事情的證明并非總是按計(jì)劃進(jìn)行,Android拒絕加入你在一個(gè)新的嘗試通過傳統(tǒng)的書簽內(nèi)容解析方法,該方法forcedthat我已經(jīng)介紹的基本知識(shí),現(xiàn)在是時(shí)候讓手機(jī)用戶在權(quán)衡多一點(diǎn)。

             

            本文來自CSDN博客,轉(zhuǎn)載請(qǐng)標(biāo)明出處:http://blog.csdn.net/lihaifeng555/archive/2009/09/27/4599691.aspx

            posted on 2010-05-10 20:51 漂漂 閱讀(1819) 評(píng)論(0)  編輯 收藏 引用 所屬分類: android 開發(fā)
            亚洲狠狠久久综合一区77777| 久久久久久久精品成人热色戒 | 久久久久亚洲精品中文字幕| 97久久精品人人澡人人爽| 久久男人AV资源网站| 久久午夜福利无码1000合集| 国内精品久久久久影院日本| 精品久久久久久99人妻| 精品国产乱码久久久久软件| 88久久精品无码一区二区毛片 | Xx性欧美肥妇精品久久久久久| 久久se这里只有精品| 亚洲精品无码成人片久久| 国产午夜精品久久久久九九| 色偷偷偷久久伊人大杳蕉| 久久国产午夜精品一区二区三区| 亚洲精品蜜桃久久久久久| 久久精品夜色噜噜亚洲A∨| 人妻久久久一区二区三区| 精品久久久久久99人妻| 久久国产色AV免费观看| 国产精品美女久久福利网站| 国产69精品久久久久99尤物 | 久久成人国产精品| AV无码久久久久不卡蜜桃| 久久国产精品免费一区| 久久精品国产精品青草| 色欲av伊人久久大香线蕉影院 | 91精品国产91久久| 999久久久免费精品国产| 中文国产成人精品久久不卡| 中文字幕无码av激情不卡久久| 久久精品视频91| 国产精品99久久久久久猫咪| 久久国产一区二区| 国产精品久久久久9999| 国内精品伊人久久久久av一坑 | 青草国产精品久久久久久| 人妻无码精品久久亚瑟影视| 狠狠色丁香久久婷婷综合_中| 亚洲乱码日产精品a级毛片久久|