package="com.apress.book.PrankApp">
<uses-permission android:name=
"android.permission.RECEIVE_SMS" />
沒有權限標志,Android將你的應用程序無法啟動當它接收到一個短信。還有其他的權限我需要涵蓋你向前看。在此期間 , 你可以找到所有在列表的權限 Android 的文件資料 http://code.google.com/android/reference/android/ Manifest.permission.html 。
向我發送短信!
現在,你已經允許進行與手機的SMS層交互,你必須告訴手機做什么,當一個新的文本信息到達時。要做到這一點,你必須打開AndroidManifest.xml文件,添加一個新的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 , 當手機得到一個接收到的 SMS 。
在 Action 中分析 Intent Receiver
要完成這個要比我們想象的有一點困難。一個進程必須在一個 DDMS 中運行 。但在大多數情況下,你不想讓應用程序運行,除非新的事件觸發它。這問題的解決方案在Eclipse IDE中只是一個小小的把戲。當你一步一步往下走時,這可能會一點一點變得復雜。
在你的onReceiveIntent方法中放置一個斷點。開始調試應用程序,并讓模擬器位于“Hello World,PrankActivity”屏幕上。在Eclipse中,切換視圖到DDMS。你可以按這命令+ F8鍵幾次或選擇菜單 Window ?? Open Perspective ?? DDMS 。
沿著左邊窗口,在Device選項卡上,你現在應該看有一個綠色bug圖標在你的應用旁邊。這是DDMS告訴你調試器附加到你的PrankApp進程中。在它的下面是Emulator Control選項卡。在這里你可以發送短信消息。首先輸入任何一個電話號碼,選擇SMS,鍵入一個測試消息,并按下Send。
如果你的配置正確,你應該看到Eclipse切換到Debug透視圖,并停止在你的新設置斷點上。
注意:如果沒有發生,首先確保你設置了權限正確。如果他們不正確,你應該看到一個失敗的權限信息顯示在DDMS屏幕底部的LogCat標簽中。此外,請確保你的應用程序已經在運行,并在Devices選項卡有綠色調試圖標在它的旁邊。如果所有這些都不奏效,比較你的項目與文中的示例。
目前為止,如果你正確地完成了。你的Intent的onReceiveIntent功能被調用,當每一個SMS消息發送到手機上。接下來,你就必須弄清楚如何得到短信的內容。
什么是在一個SMS中?
可悲的是,到目前為止Android關于接收和過濾SMS信息的文檔只不過是混亂的。我懷疑這不是一項需要告訴開發人員的重要功能。我不同意這些優先事項,但是使我有機會填補空缺。
下面是methodonReceiveIntent的代碼,功能是監聽新的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;
}
你還需要輸入兩個類庫來完成這項工作:
Import android.telephony.gsm.SmsMessage;
Import android.provider.Telephony;
getMessageFromIntent 方法是在 Telephony 類中 , 這將返回 SMS 信息的數組?,F在剩下的就是得到短信的有效載荷。你要找的觸發惡作劇活動的特殊代碼為文本
“ 0xBADCAT0_Fire_The_Missiles ! ”
它必須是一個適當的獨特組合,以便它不會被觸發事故。你不會希望自己的惡作劇失火并提醒受害人太早的。
注意:在Android里,沒有記載的功能是很可能還沒有完成。由于接收短信的文檔幾乎不存在,你應該會有些變化在如何處理手機簡訊上。更可能的是整體的方法應該是相似的,但它有把握地認為其中的一些細節將改變SDK的前到達它的最終版本。這個例子是有關學習如何使用意圖接收器多是有關文本的消息通信資料。
觸發活動
重要的是要記住,意圖接收器的生命周期短,只有只要方法調用onReceiveIntent。一旦出于這一職能,Android是免費殺死進程中運行你的應用程序。任何異步功能會死去,如果是一個十分棘手的死亡開始。如果你想要做超越了簡單的處理方法內的任何事情,你需要啟動服務或活動。既然你要同時播放音樂和警報你的受害者,他們去過了,你需要啟動的一項活動。你完成此情況如下:
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);
}
你會看到這里是增補 NEW_TASK_LAUNCH 在 setLaunchFlags 。你需要做任何你要發送的 Intent action , 將啟動一項新的活動。此外,正如你在啟動畫面示例應用程序,你必須添加一個新的行動,你的Activity的Intent filter。那個過程應該看起來很熟悉:
<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>
現在 , 如果你在前面正確地添加了代碼 , 當你從 DDMS 透視圖中 發送 SMS 消息時 , 你應該看到你的應用跳出到前臺 , 顯示 “Hello World ,PrankActivity ” 文本在屏幕上。
索具的活動
一個最后的工作你需要添加 , 在得到卑鄙的音樂播放服務之前 : 裝配 Activity , 以回應你的 Intent Receiver 發送的活動 。如果應用程序正常啟動,你要立即關閉了。同樣,如果可以通過菜單啟動,這樣你的惡作劇的計劃就會過早的曝光。要做到這一點,你必須檢索發射的Intent,并調用getAction方法來計算出在什么情況下,它已經啟動。該PrankActivity的OnCreate方法現在看起來應該代碼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();
}
首先你會得到發起 Activity 的Intent 。使用目前得到的 Intent , 你可以用 getAction 方法檢索調用的行動。這個將返回一個包含啟動事件的字符串,你核對你的著名音樂行動列在原來的XML。如果在啟動事件為你的活動來自正常的方式(從菜單或從啟動調試器),該行動字符串將是null。如果是這樣的話,你要立即使用finish方法關閉活動。
注意:OnCreate方法被調用當你的應用被首次啟動時。如果你已經啟動你的應用程序,然后退出(使用返回鍵),應用程序仍然在后臺運行。如果在這時,你發送短信,你的活動將回到前臺,但其OnStart方法將調用而不是OnCreat。
你今天想羞辱誰呢?
雖然可能有些矯枉過正,你要使用Android的service對象來處理音樂播放。我打算這樣做有因為另個原因:
n ?? 這是一個好的機會來展示以簡單的方式service的使用,在簡單的環境。
n ?? 潛在的,它會讓你啟動音樂不用看到應用程序,使你的惡作劇的應用程序更卑鄙。
神經與服務
為什么你要使用的服務?從本質上講,它意味著是一個對象,與用戶界面分離的可運行地過程。這是完美的情況,當一個開發人員希望的功能(無論是網絡或多媒體相關)能夠獨立運行。例子包括:音頻播放,網絡交易的后臺,和邪惡的惡作劇程序。雖然服務允許多個應用程序(打開通信信道)與他們綁定,你會使用它作為一個簡單的后臺進程。同樣,services有很多用途不只是這個簡單的例子。
創建service
添加一個新類的源碼包。我已經再次調用PrankService(沒有點創意)。在最基本的層面,service要重寫onBind方法。要獲得服務類編譯,它必須看,至少有一點點,如代碼2-5。
Code Listing 2-5. A Stripped-Down Service
public class PrankService extends Service
{
public IBinder onBind(Intent intent)
{
return null;
}
}
在這個例子中,你不會使用該服務onBind方法進行互動。你可以簡單地啟動和停止服務在你的主要活動內。要做到這一點,你必須重寫兩個方法在服務類:
OnStart (Int startId ,Bundle argument )
onDestroy()
當OnStart被調用時,你會開始播放的媒體文件。當服務被破壞,就會明確地停止。這不是必然要求,但你會明白。
啟動服務
開始一個新的服務應該類似于開始活動。自從你已經接觸到這是幾次,我就在給你一段代碼,讓你整理一下。 調用前面列出的PrankActivity OnCreate方法。簡單替換注釋“ We’ll need to start the music service here ”用下面的代碼行:
startService(new Intent
("com.apress.START_AUDIO_SERVICE"), null );
同樣,這個看上去很熟悉。啟動Activity和啟動service之間唯一的區別是(除了不同的方法調用)是隨Intent傳遞bundle(實際上是一個地圖或哈希表)參數的能力。這bundle將被傳遞到OnCreate方法服務。
啟動音樂
BREW和Java一樣,Android的媒體播放(簡單的播放/停止計算)非常簡單易用。當你服務的OnStart函數被調用,你會加載和播放/res/raw 目錄中的測試音頻文件首先要做的是復制音頻樣本文件導入/res/raw(如果沒有這個目錄,繼續并創建它)。下一步,放下羞辱,并復制寫入尊重,音頻文件原始文件夾。如果你使用Eclipse,你應該添加相應的元素R.raw。在你的情況下,它的R.raw.test。
現在你有一個音樂文件的引用,你可以添加程序 PrankService 的要求如下 :
public void onStart(int startId, Bundle arguments)
{
MediaPlayer p;
super .onStart(startId, arguments);
player = MediaPlayer.create(this , R.raw.test);
player.start();
}
請記住 , 是一個重寫的 OnStart 方法 , 因此你必須調用父類同一函數或 Android 將變得不穩定。在這一點上,你需要用MediaPlayer的靜態類創建一個新的媒體播放器對象。因為service是context的子類,你將一個指針傳遞給你當前的context和靜態變量代表你的測試媒體。在這一點上,你可以調用play,現在你可以開始忙了。播放會繼續在后臺運行,直到stopService這個方法是由你的主Activity調用。
當stopService被調用時,下面的方法將調用:
public void onDestroy()
{
super.onDestroy();
player.stop();
}
同情的行動
既然你是一個不錯的愛開玩笑的人 , 你要給你的受害者一個臺階下。正如你之前見過的,Activity是由Intent Receiver觸發的,在活動啟動服務的時間點上。正如你剛才看到的,service是負責播放噪聲激怒你副總工程師。同樣,因為你是仁慈的在你的執行回報的同時,你必須為受害者設計關閉音樂方法。添加在你的PrankActivity下面的方法可以實現你善意的行動:
public boolean onKeyDown(int keyCode, KeyEvent event)
{
stopService(new Intent(
"com.apress.START_AUDIO_SERVICE"));
finish();
return true;
}
配置文件
下面是表現如下所示 :
<service android:name=".PrankService">
<intent-filter>
<action android:name=
"com.apress.START_AUDIO_SERVICE" />
<category android:name=
"android.intent.category.DEFAULT" />
</intent-filter>
</service>
禪宗和報復的藝術
通過不光明正大的小惡作劇應用程序的使用 , 你應該明白了 Intents ,Intent Receivers ,services 和Activities 如何 共同在先進的 、 主要是后臺 的 應用程序中運行的。我現在要改變一下方式,一步一步做,你做了什么以及如何實現它。
讓我做的更好
你做了以下內容:
1。你使用正確的權限和系統接收器的意圖級短信的意圖安排的對象是PrankSMSReciever每次實例化一個手機上的SMS到達。如果你的Intent Receiver發現一個非常特定的SMS的有效載荷,它將通過發送Intent將啟動你的活動。
2。這項活動名為PrankActivity,會監聽被PrankSMSReceiver的特定intent action。當它收到確切intent action,你的活動將顯示一個“gotcha”消息給受害者。同時,該活動將發出意圖旨在啟動服務。如果在任何時候受害人/用戶按下一個電話上的鍵,應用程序將退出,音樂服務將終止。
3。服務類,稱為PrankService,監聽PrankActivity的intent,將啟動并開始播放令人討厭,預定義的音頻文件。它將繼續播放,直到它被要求停止通過PrankActivity的調用方法stopService。
注意:此示例應用程序不涉及手機的本地短信應用。因為所有的intent receiver傳入的通知意圖,你的應用將被爭奪用戶與Android的關注短信收件箱的應用。在生產中,這可能需要相當計時器也許觸發文本有效載荷,這是一個微妙多一點 “0xBADCAT0_Fire_The_Missiles !”
在Android中移動數據
最后,你需要把重點放在內容解析器。 Android不會給SDK特別的手機文件系統的訪問權限,如Brew一樣。它也沒有提供一個RecordStore,像Java ME一樣。在你的Activities、Intent Receiver和services之間,你傳遞數據的主要方法是必須通過ContentResolver超類。雖然你可以存儲數據通過文件,參數,和其他數據庫,可以采取許多形式,Android附帶的幾個重要內置content resovlers。這里有一個列表,Android的主要content resovlers,你可能要經?;踊A上:
瀏覽器
書簽
搜索歷史
電話呼叫
通話記錄
最近通話
聯系
系統設置
硬件設置(藍牙,網絡設置)
軟件設置
Android 的文檔提供了非常好的示例 :http://code.google.com/android/ devel /data/contentproviders.html #usingacp 。馬上我要給你演示怎樣添加一個書簽到手機瀏覽器的書簽列表。首先,你要搜索當前的書簽列表,查看你的鏈接是否存在。第二,你要添加書簽,如果不存在。
注意:可以創建你自己的content provider,作為一種方式,為了公共訪問封裝Android的SQLite的執行。你將進入如何在后面的章節中這一點。現在你只是去處理content resolver交給的“client”方面。
Android采用了自定義的SQLite實現,來存儲本地信息。如果你不熟悉SQL的基礎知識,現在也許是一個學習的機會。為表述方便,我要假設你了解基本的SQL查詢命令。如果你需要進一步提高,Apress上有一個很好的資源http://apress.com/book/ catalog?category=145 。
無恥的自我推銷
讓我們說一下你的應用程序中“about”部分,你想有一個按鈕,添加你的商業軟件網頁到用戶的web書簽。你要確保它不添加兩次,如果你的用戶有再次點擊該按鈕意外。為了使這個實例簡單,你將觸發這個事件在你示例應用程序中,當用戶按下一個鍵。
注意:在一個有趣的注意,如果你需要證明,作為一個開發人員,Android是還沒有完全成熟的,你只要看看比對下文件的android.content.ContentResolver方法getDataFilePath,其中規定: “ 請不要使用此功能!有人說這一點,他們不應該。你沒有直接的訪問文件內的內容提供商。不要碰這個。走開。 “ 這是好,知道即使是對Android的文檔技術作家有幽默感。
獲取用戶的書簽
這應該是顯而易見的,至少在這一點,開發人員可以做一些非常邪惡的事情,訪問用戶的書簽。目前還不清楚,在這一點,Android會做什么以防止發生這類事情。我想這得由運營商來鎖定或監視此行為。在任何情況下,你將使用一個調用方法managedQuery,它將返回一個列表用戶的書簽:
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");
現在我將分解每一個操作。你首先要書簽網址列索引。再次,因為Android通過SQL格式提供其多數內部數據的訪問,你應該習慣于用數據庫的方式引你保存的信息。接下來,你將設置游標,一個類似Java ME中RecordStore枚舉對象,設置字符串數值的映射。因為你只關心列包含的網址,它保存非常簡單。方法調用managedQuery是調用將返回你的數據。你可以通過URI中為書簽存儲字符串,交給你了簡單的映射數值,不需要where語句,并告訴它按降序排列的網址。
搜索結果
搜索結果很簡單只要迭代游標對象,是通過簡單的光標迭代對象和退出一列從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 的內容 , 但現在你會只是看你的 www.apress.com 鏈接。很明顯,如果此代碼的運行是上述Apress網址,你不會找到它。因為用戶希望添加貴公司的網址在虛擬的“About” ” 部分中,你也要給他們。
使用Content Resolver添加邪惡公司網址
也許他們不是邪惡,但你加入他們。由于Apress也許是公司最邪惡那里(不是我有偏見,記?。?,你讓他們擺脫它,只此一次。下面是一個美麗的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);
想大多數軟件開發工具包,有不止一種方法來完成相同的任務。早些時候,你有更復雜的方法加書簽。這個方法是有用的,因為它給你一個參考如何添加元素通過ContentResolver不具有輔助功能?,F在,這里的簡單的方法:android.provider.Browser.saveBookmark(this,“Apress”,url);幫助函數會啟動一個對話框,要求用戶確認增加書簽。這可能是最用戶友好的方式來添加書簽,除非你想控制對話框的模樣。
平衡早餐的組成
在過去的三個例子你探討了Android的所有主要構建模塊。一開始你看到了實用的啟動畫面。這讓你探索了基本知識關于啟動、維護和移動通過Activity對象。這是你學習intents and interprocess/object communication邁出的第一步。使用和傳遞意圖在活動,服務,內容處理,接收器和意圖之間可能是一個最重要的事情,這是Android與其他移動環境的區別。
對于Activity和通信基礎知識,你已經有了經驗,你繼續學習服務和意圖接收器。要使用這兩個組成部分,你烹調了 狡猾的 惡作劇應用程序,既能強迫你使用所有3個組建(活動,服務,和意圖的接收器),使所有三個互相溝通。幾乎是旁注,你研究什么需要得到通知時,短信在手機上到達。最后,你探討如何檢索和寫入的內容是解析器本機設備:瀏覽器的書簽數據庫。事情的證明并非總是按計劃進行,Android拒絕加入你在一個新的嘗試通過傳統的書簽內容解析方法,該方法forcedthat我已經介紹的基本知識,現在是時候讓手機用戶在權衡多一點。
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/lihaifeng555/archive/2009/09/27/4599691.aspx
posted on 2010-05-10 20:51
漂漂 閱讀(1820)
評論(0) 編輯 收藏 引用 所屬分類:
android 開發