Android4開發入門經典 之 第二部分:Android應用的核心基礎【私塾線上原創】

xinqing010發表於2012-03-01

Android應用中的元件

Application Components

Android應用中最主要的元件是:

1:Activity:活動,活動是最基本的Andorid應用程式元件,應用程式中,一個活動通常就是一個單獨的螢幕。
2:Service:服務,服務是執行在後臺的,通常是具有一段較長生命週期且沒有使用者介面的程式。比較好的一個例子就是播放歌曲的媒體播放器,就算你導航到其它螢幕時音樂也還是在播放。
3:Content provider:內容提供者,內容提供者實現了一組標準的方法,從而能夠讓不同的應用之間可以相互儲存或讀取彼此的內容,當然都需要實現自己的內容提供器。
4:Broadcast receiver:廣播接收者,你可以使用BroadcastReceiver來讓你的應用對一個外部的事件做出響應。比如:當電話呼入時,資料網路可用時。
 

Intent基本概念

Intent是什麼

是一個簡單的訊息物件,它表示程式想做某事的“意圖”,可以用來”啟用”Activity、Service或BroadCast Receiver。

比如想要從一個Activity啟動另外一個Activity,就可以這麼寫:

 

java程式碼:
Button btnToT2 = (Button)this.findViewById(R.id.btn_toT2);
btnToT2.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
Intent in = new Intent();
in.setClass(HelloWorldActivity.this, T2.class);
HelloWorldActivity.this.startActivity(in);
}
});
 

Intent物件能包含下面六種資料:

1:Component name,元件名稱:來處理Intent的元件類的全路徑名稱。可以通過setComponent()、setClass()、setClassName()方法來進行設定,通過 getComponent()方法進行讀取。
2:Action,動作:一個描述要做什麼事情的字串。在Intent類裡面預定義了。
3:Data,資料:用來描述Action對應的具體的資料和資料的MIME Type,比如要打電話,那麼就是電話資料的uri,通常是“tel://”後面加上號碼。如果是其他的資料,通常是“content://”型別的uri。
相應的setData()方法僅僅用來設定URI,而setType()方法僅僅設定MIME Type,setDataAndType()可以同時設定,另外可以通過相應的get方法獲取值。
4:Category,類別:用來描述元件應該如何處理Intent的附加資訊。在Intent類中有Category具體的預定義。可以通過addCategory()、removeCategory()和getCategories()來操作Category。
5:Extras,額外資料:傳遞給元件的附加資料,通常是key-value對。可以通過putExtras()和getExtras()方法來運算元據
6:Flags,標記:各種各樣的類別標記,用來描述如何裝載Activity,以及裝載後如何處理這些Activity。

 Intent通常被分成兩種:顯式的和隱式的

1:顯式的Intent:直接根據元件的名稱來進行指派,通常用作應用內部的訊息傳遞機制,比如啟動service或其他Activity等。
2:隱式的Intent:不用根據元件的名稱來進行指派,通常用作啟動其他應用的元件。比如接收廣播訊息,Android系統需要尋找到最合適處理這個訊息的應用,通常會使用Intent Filter來實現。

Intent Filter基本概念

Intent Filter是什麼

用來描述一個Activities、Services、BroadCast Receivers能夠操作哪些intent。它們都可以包含一到多個Intent Filter。
nIntent Filter能包含的資料通常只有三種:
action、data(包括URI和型別)、category。

Intent Filter通常在AndroidManifest.xml檔案裡面配置使用

一個簡要的示例如:


java程式碼:

   
   

Intent基本示例

發簡訊的示例

 

java程式碼:
Uri uri = Uri.parse(“smsto:傳送的號碼");
Intent in = new Intent(Intent.ACTION_SENDTO,uri);
in.putExtra("sms_body", "發個簡訊玩");
Hello.this.startActivity(in);

打電話的示例:


java程式碼:
Uri uri = Uri.parse(“tel:傳送的號碼");
Intent in = new Intent(Intent.ACTION_CALL,uri);
Hello.this.startActivity(in);
 
記得在AndroidManifest.xml檔案中進行授權,,這些許可權可以在Manifest.permission裡面查到。

資源

什麼是資源

資源是程式外部檔案,也就是非程式碼的檔案,它被程式碼使用並在編譯時編入應用程式。Android支援不同型別的資原始檔,包括XML,PNG以及JPEG 。

資源型別

Android平臺上存在不同的資源型別,大部分資源型別以及預設的存放包路徑,在上一節課的時候已經作了介紹。

建立資源

通常,你可以通過三種型別的檔案來建立資源:XML檔案(除點陣圖以及原資料檔案),點陣圖檔案(對於圖片)以及原始資料(其它型別,例如聲音檔案,等等)。

Android支援的單位

1:px 畫素:螢幕上的點
2:in 英寸:長度單位
3:mm 毫米:長度單位
4:pt 磅:1/72英寸
5:dp 與密度無關的畫素:一種基於螢幕密度的抽象單位,在每英寸160點的顯示器上,1dp = 1px
6:dip 等同於dp
7:sp 與刻度無關的畫素:與dp類似,但是可以根據使用者字型大小的首選項來進行縮放
建議:始終使用sp作為文字大小的單位,dip或dp作為其他元素的單位。

在程式碼裡面使用資源

資源最終會被編譯成APK檔案,Android會建立一個包裝類,命名為R,它指向你程式中所有的資源。這個類包含很多子類。每一種都是Android 支援的,同時,編譯後會產生一個資原始檔。每個類提供一個或多個編譯後資源的識別符號,裡面包含了字串,佈局檔案(全屏或者部分螢幕),以及影像資源。這樣你就能在你的程式碼裡使用這些資源了。
注意:R引用的是資源ID,是一個int值,如果需要文字型的資料,應該使用getText方法,比如: this.getText(R.string. app_name);

從其他資源類裡引用資源

一個在屬性或者資源裡提供的數值可以被指向一個具體的資源,可以通過一個引用來使用這些資源。比如HelloWorld裡面引用strings.xml裡面的文字。
基本語法:@[:]/
用‘@’的字首是說明資源引用,後面的文字是資源的名字,前面的示例沒有指定包,因為是在自己的包裡引用資源。

引用系統資源

要使用系統資源,你需要使用android包,比如:

java程式碼:

系統帶的資源資料很多,可以通過android.R和它包含的類去檢視。
 
當然,也可以訪問自己的color定義,比如在res/values/建立一個colors.xml,然後定義自己要使用的顏色,示例如下:

    #770000ff

那麼上面那句話就修改成:
android:textColor="@color/my_color"

主題屬性引用

另一種資源數值允許你引用當前主題屬性值。這種屬性引用只能被用於特殊的資源類以及XML屬性中;它允許你根據現在主題風格將你定製的UI變得更標準化,而不用使用大量的具體數值。
語法為:?[:][/]
示例如下:

java程式碼:
注意除來我們將字首'?'代替了'@',其他非常像資源引用。當你使用這個標記,系統會自動查詢你提供的屬性的名字 -- 資源工具知道肯定會有資源屬性相符合,你不需要使用資源識別符號到主題裡去尋找相應的資料而不是直接使用原資料。

對不同的語言和設定提供不同的資源

你可以根據產品介面語言以及硬體配置設定不同的資源。注意,雖然你可以包含不同的字串,佈局以及其他資源,但開發包(SDK)不會給你顯式的方法去指定不同的資源去載入。Android檢測你的硬體以及位置資訊選擇合適的設定去載入。使用者可以到裝置上的設定介面去選擇不同的語言。
要包含不同的資源,在同一目錄下建立並行的資料夾,在每個資料夾後加上合適的名字,這個名字能表明一些配置資訊(如語言,原始螢幕等等)。
比如:

java程式碼:
res/
    drawable/  
        icon.png
        background.png   
    drawable-hdpi/ 
        icon.png
        background.png

配置限定名稱(或修飾語)

Android系統可以配置的限定名稱的詳細列表,參見Dev Guide/Application Resources /Providing Resources 的 table 2。
這裡有幾點說明:
1:你可以在一個資源型別後面,新增任意多個限定名稱,名稱之間以破折號分開,但是他們的先後順序必須和上面table2文件裡面的順序保持一致

java程式碼:
Wrong: drawable-hdpi-port/
Correct: drawable-port-hdpi/
2:限定名稱大小寫敏感,也不能出現兩個一樣的限定名稱,即使大小寫不一樣
3:一個式子裡同一個型別修飾語中只有一個值是有效的
4:你可以指定多個引數去定義不同的配置,但是引數必須是table2裡的
5:所有目錄,無論是限制的,還是不限制的,只要在 res/ 目錄下,是不能巢狀的

Android如何找到最合適的資源

Android將會挑出哪些基本資原始檔在執行時會被使用,這依靠當前的配置。舉例來說吧,假如有如下的drawable資原始檔夾:

java程式碼:
drawable/
drawable-en/
drawable-fr-rCA/
drawable-en-port/
drawable-en-notouch-12key/
drawable-port-ldpi/
drawable-port-notouch-12key/
假設當前的裝置配置為:
Locale = en-GB
Screen rientation = port
Screen pixel density = hdpi
Touchscreen type = notouch
Primary text input method = 12key

資源的國際化

1:建立預設的本地資源
其實就是預設的那些資原始檔夾和檔名稱的定義
2: Android的資源國際化的實現方式,其實就是依靠設定修飾符來區分,如果某個語言沒有找到相應的資原始檔夾,那麼就使用預設的本地資源
3:要注意各個資料夾只是內容的表現形式不一樣,但是資源的名稱和內容應該是一樣的
4:在Java裡面引用的時候,是無需考慮修飾符的,照樣是通過R來引用
5:如果你希望在Java裡面訪問到本地的一些資訊,可以這麼寫:
String locale = context.getResources().getConfiguration().locale.getDisplayName();
如果在Activity裡面,context就是this了。

安全和許可權

安全架構

1:Android安全學中的一個重要的設計點是在預設情況下應用程式沒有許可權執行對其它應用程式、作業系統或使用者有害的操作。如讀/寫使用者的隱私資料(如聯絡人資訊),讀/寫其它應用程式的檔案,執行網路訪問,保持裝置活動等。
2:應用程式的程式是一個安全的沙箱。它不能干擾其它應用程式,除非在它需要新增原有沙箱不能提供的功能時明確宣告許可權。

應用程式簽名

所有的Android應用程式(.apk檔案)必須通過一個證照的簽名,此證照的私鑰必須被開發者所掌握。這個證照的標識是應用程式的作者。這個證照不需要通過證照組織的簽署:Android應用程式對於使用自簽署的證照是完全允許的和特別的。
這個證照僅僅被用於與應用程式建立信任關係,不是為了大規模的控制應用程式可否被安裝。最重要的方面是通過確定能夠訪問原始簽名許可權和能夠共享使用者ID的簽名來影響安全。

使用者標識和檔案訪問

1:Android的作業系統linux是一個多使用者的作業系統,每個應用就相當於一個使用者
2:系統預設的為每個應用分配一個ID,使用者ID 在應用程式安裝到裝置中時被分配,並且在這個裝置中保持它的永久性。
3:某個應用程式所建立的任何檔案,都不能被其他應用程式讀寫
4:每個程式有自己的虛擬機器,因此應用的程式碼能夠與其他應用獨立開來進行執行
5:每個應用程式都在其自己的linux程式中執行,硬體禁止一個程式訪問其他程式的記憶體
6:有些時候,有可能需要兩個應用共享同樣的Linux user ID,以便他們能互相訪問檔案,資源等,這要求兩個應用必須有相同的簽名。可以設定每一個包中的AndroidManifest.xml檔案中的manifest 標籤屬性sharedUserId,使得他們擁有相同的使用者ID。

使用許可權

一個基本的Android應用程式沒有與其相關聯的許可權,意味著它不能做任何影響使用者體驗或裝置中的資料的有害操作。要利用這個裝置的保護特性,在你的應用程式需要時,你必須在AndroidManifest.xml檔案中包含一個或更多的 標籤來宣告此許可權。
比如接收簡訊的許可權:
 
可以在Manifest.permission找到Android系統提供的許可權定義。
 

應用、任務、程式和執行緒

應用

一個android 包 (簡稱 .apk ) ,裡面包含應用程式的程式碼以及資源。這是一個應用釋出,使用者能下載並安裝到他們裝置上的檔案。

任務

其實就是一次執行起來的一個活動棧,通常使用者能當它為一個“應用程式”來啟動和操作。

程式

一個應用通常會對應到一個程式,注意,不是一次執行一個程式,跟windows不一樣,只要程式沒有銷燬,那麼無論你啟動幾回這個任務,都可能是在一個程式裡。

執行緒

任務、活動等的實際執行環境,每個程式包含一個或多個執行緒。多數情況下,Android 避免在程式裡建立多餘的執行緒,除非它建立它自己的執行緒,我們應保持應用程式的單執行緒性,也就是執行在主執行緒裡面。
 


程式的生命週期

在大多數情況下,每個Android應用程式都執行在自己的Linux程式中,當應用程式的某些程式碼需要執行時,這個程式就被建立並一直執行下去,直到系統認為該程式不再有用為止,然後系統將回收程式佔用的記憶體以便分配給其它的應用程式。 Android會盡可能長時間的為應用程式維持程式。

程式按重要性分類,第一類程式最重要,通常最後被銷燬

1:前臺(Foreground)程式,與使用者當前正在做的事情密切相關。不同的應用程式元件能夠通過不同的方法使它的宿主程式移到前臺。當下面任何一個條件滿足時,可以考慮將程式移到前臺:
(1)程式正在執行一個與使用者互動的Activity ,它的onResume()方法被呼叫
(2)程式有一個Service,該Service對應的Activity正在與使用者互動
(3)程式有一個Service被呼叫startForeground()方法,要求到前臺來執行
(4)程式有一個Service,並且在Service的某個回撥函式(onCreate()、onStart()、 或onDestroy())內有正在執行的程式碼。
(5)程式有一正在執行的BroadcastReceiver,它的onReceive()方法正在執行
2:可見(visible)程式,它有一個可以被使用者從螢幕上看到的Activity,但不在前臺,它的onPause()方法被呼叫。這樣的程式一般不允許被殺死,除非為了保證前臺程式的執行不得不這樣做。
3:服務(service)程式,有一個已經用startService() 方法啟動的Service。雖然這些程式使用者無法直接看到,但它們做的事情卻是使用者所關心的(例如後臺MP3播放、後臺資料上傳下載等)。因此,系統將一直執行這些程式除非記憶體不足以維持所有的前臺程式和可見程式。
4:後臺(background)程式, 擁有一個當前使用者看不到的Activity(它的onStop()方法被呼叫)。這些程式對使用者體驗沒有直接的影響。如果它們正確執行了Activity生命期,系統可以在任意時刻殺死程式來回收記憶體,並提供給前面三種型別的程式使用。
5:空(empty)程式,不包含任何處於活動狀態的應用程式元件。保留這種程式的唯一原因是,當下次應用程式的某個元件需要執行時,不需要重新建立程式,這樣可以提高啟動速度。

Android中的執行緒

概述

1:當一個Android應用被裝載執行的時候,系統會建立一個執行緒來執行這個應用,通常稱之為主執行緒“main thread”,也被稱為UI Thread。
2:系統不會為每個元件例項去建立單獨的執行緒,通常一個應用所有的元件都是執行在一個Linux程式和相應的主執行緒裡面。
3:UI Thread不是執行緒安全的,因此你介面上的操作,都應該儘量在UI Thread裡面執行,而不能在自己啟動的其他工作執行緒裡面執行。
4:因此建議,對於Android這種單執行緒模式:
(1)不要阻塞UI Thread
(2)不要在UI Thread之外訪問Android 的UI toolkit
5:如果有長時間的處理,比如要裝載一個大的圖片,就需要開啟一個單獨的執行緒來裝載,通常稱之為Worker Thread。 

一種典型的錯誤實現

下面在click listener裡面,用一個單獨的執行緒去下載了一個圖片,並設定到ImageView上顯示出來

java程式碼:
public void onClick(View v) {
    new Thread(new Runnable() {       
public void run() {    
   Bitmap b = loadImage ("http://sishuok.com/image.png");           
   mImageView.setImageBitmap(b);       
}   
    }).start();
}
乍一看,覺得這樣的實現好像是可以的,但是請注意,它違反了上面建議的第2條,“不要在UI Thread之外訪問Android 的UI toolkit”,通過worker thread去設定UI Thread裡面的元件,可能會導致不可預期的結果。

解決辦法

要解決上面這個問題也很簡單,Android提供瞭如下幾種方式:

1:Activity.runOnUiThread(Runnable)
2:View.post(Runnable)
3:View.postDelayed(Runnable, long)

比如使用View.post來解決的示例程式碼如下:


java程式碼:
public void onClick(View v) {   
  new Thread(new Runnable() {       
    public void run() {           
      final Bitmap bitmap = loadImage("http://sishuok.com/image.png");
      mImageView.post(new Runnable() {
        public void run() {                   
          mImageView.setImageBitmap(bitmap);               
        }    });     }   
 }).start();
}
 

ADB

ADB簡介

adb(Android Debug Bridge)是Android 提供的一個通用除錯工具,藉助這個工具,可以管理裝置或手機模擬器的狀態。

ADB常用操作

1:進入裝置或模擬器的Shell
adb shell
通過以上命令,可以進入裝置或模擬器的shell 環境中,在這個Linux Shell 中,你可以執行各種Linux 的命令,
另外如果只想執行一條shell 命令,可以採用以下方式:
adb shell [command]
2:安裝應用到模擬器
adb install app.apk
3:解除安裝指定軟體,如果加 -k 引數,為解除安裝軟體但是保留配置和快取檔案。
adb uninstall [-k]
4:複製一個檔案或目錄到裝置或模擬器上:
adb push test.txt /tmp/test.txt
5:從裝置或模擬器上覆制一個檔案或目錄
adb pull /android/lib/libwebcore.os
6:取得當前執行的模擬器、裝置的例項列表及每個例項的狀態
adb devices
7:獲取裝置序列號
adb get-serialno
8:訪問資料庫SQLite3
Shell下直接  sqlite3
視訊配套PPT,視訊地址【 Android4開發入門經典獨家視訊課程

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/26715458/viewspace-717424/,如需轉載,請註明出處,否則將追究法律責任。

相關文章