星期六, 10月 29, 2011

Activity (四)

Android應用程式學習筆記

Shutting Down an Activity

呼叫finish()方法就可以關閉activity,你也可以從另外一個activity呼叫finishActivity()方法關閉activity。


Managing the Activity Lifecycle

藉由回調方法管理activity的生命週期對於開發強健且靈活的應用程式來說是相當重要的,activity的生命週期直接受到與它相關的其他activity,它的task及back stack所影響。

activity有三個基本的狀態:
Resumed
Activity運行在前台且擁有用戶焦點。
Paused
其他Activity運行在前台且擁有用戶焦點,但是activity仍是可見的,那就是其他activities顯示在它的上面,其他activtiy部分是透明的或是不會完全覆蓋整個屏幕。被暫停的activity仍是活的,但是系統可能在極低記憶體的狀態下殺掉被暫停的activity。 
Stopped
Activity完全被其他activtiy遮掩(activity現在運行於後台),被停止的activity也仍是活的,然而被停止的activity不會被用戶看見且它可能被系統殺掉,當系統需要記憶體空間時。
如果activity處在暫停或是停止狀態,系統可以從記憶體停止這些activity,不論是要求它們結束或是殺掉它們的程序,當'它們再次被啟動,再全部重建。


Implementing the lifecycle callbacks

當activity轉換狀態,會接收許多回調方法通知。所有回調方法都可以複寫來完成在狀態改變時適合的工作,以下就是生命週期中所有回調方法:



public class ExampleActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // The activity is being created.
    }
    @Override
    protected void onStart() {
        super.onStart();
        // The activity is about to become visible.
    }
    @Override
    protected void onResume() {
        super.onResume();
        // The activity has become visible (it is now "resumed").
    }
    @Override
    protected void onPause() {
        super.onPause();
        // Another activity is taking focus (this activity is about to be "paused").
    }
    @Override
    protected void onStop() {
        super.onStop();
        // The activity is no longer visible (it is now "stopped")
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        // The activity is about to be destroyed.
    }
}


這些方法定義了activtiy的整個生命週期,藉由實現這些方法,你可以注意到在生命週期中有三個巢狀迴圈:

  • Entire lifetime-Activity的entire lifetime發生在呼叫onCreate()方法與呼叫onDestory()方法之間,你的activity應該在onCreate()方法中設置"總體"狀態(比如定義布局),在onDestory()方法中釋放所有剩下的資源。例如,如果你的activity有一個執行緒在後台執行從網路下載資料的工作,activtiy在onCreate()方法中建立執行緒,而在onDestory()方法中停止執行緒。
  • Visible lifetime-Activity的visible lifetime發生在呼叫onStart()方法與onStop()方法之間,在此時段中,用戶可以在屏幕上看見activity並與它互動。例如,當新的activity啟動而activity不再可見時,onStop()方法被呼叫。在onStart()與onStop()之間,你可以保有顯示activity給用戶的資源。例如,你可以在onStart()方法註冊BroadcastReciever監視影響UI的改變,在onStop()方法撤銷BroadcastReciever。系統可能在activity的生命週期中多次呼叫onStart()方法和onStop()方法,當activity對於用戶為可見與隱藏之間交替時。
  • Foreground lifetime-Activity的foreground lifetime發生在呼叫onResume()方法與呼叫onPause()方法之間,在此時段中,activity在屏幕上是在所有其他activity前面且擁有用戶焦點。activity會頻繁地轉進與轉出前台,例如,當裝置進入睡眠狀態時呼叫onPause()方法,或是當一個對話框出現。因為經常在此狀態轉換,這兩個方法在程式碼中應該要公平,避免變慢造成用戶在此狀態轉換時需要等待。
下圖顯示這些loops及兩狀態之間的路徑。

在這裡做個小小總結:

1.關閉activity有兩個方法,呼叫finish()及finishActivity()。
2.Activtiy生命週期中有三個迴圈,Entire lifetime、Visible lifetime、Foreground lifetime。
3.Entire lifetime為onCreate()與onDestory()之間,為activity的整個生命週期,主要執行取得資源與釋放資源的工作。
4.Visible lifetime為onStart()與onStop()之間,為activity可以被看見的時間,主要執行與使用者介面相關的工作。
5.Foreground lifetime為onResume()與onPause()之間,為activity被用戶使用的時間。
6.當執行到onCreate()時,用戶還未看見activity,當執行到onStart()時,用戶才看見activtiy。

星期三, 10月 26, 2011

Activity (三)

Amdroid應用程式學習筆記

Starting an Activity

你可以呼叫startActivity()啟動其他activity,傳入Intent物件來描述你想啟動的activity,Intent不是明確指定你想起動的activity就是描述你想執行的動作類型(系統會為你挑選適合的activity,可能是不同應用程式的activity),Intent物件也可以攜帶小量的數據到你想啟動的activity使用。

當你在自己的應用程式完成啟動其他activity,通常都是啟動已知的activity,你可以建立一個intent明確地用類別名稱定義你想啟動的activity是哪個,以下就是一個activity如何啟動另一個名稱為SignInActivity的activity的例子。


Intent intent = new Intent(this, SignInActivity.class);
startActivity(intent);

然而,你的應用程式也想執行一些動作,例如發送電子郵件、編輯簡訊或是狀態更新,既然這樣,你的應用程式也許沒有自己的activities可以執行這些動作,所以你可以使用在裝置上其他應用程式所提供的activity,且這些activity可以執行動作。這是intent有價值的地方-你可以建立一個intent描述你想執行的動作,然後系統啟動來自其他應用程式適合的activity。如果有許多activity都可以完成intent描述的動作,用戶可以選擇其中一個使用。舉例,你想允許用戶寄發電子訊息,你可以如此建立intent:


Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);
startActivity(intent);

EXTRA_EMAIL額外加到intent的是電子郵件地址的字串陣列,當電子郵件應用程式回應這個intent,應用程式讀取intent中的字串陣列。在此狀況,電子郵件應用程式啟動,用戶用完,你的activity就會恢復。


Starting an activity for a result


有時候你可能想要從你啟動的activity接收結果,既然這樣,呼叫startActivityForResult()方法啟動activity取代startActivity()方法,從被啟動的activity接收結果,實現onActivityResult()回調方法,以下為如何建立intent與處理結果:


private void pickContact() {
    // Create an intent to "pick" a contact, as defined by the content provider URI
    Intent intent = new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI);
    startActivityForResult(intent, PICK_CONTACT_REQUEST);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // If the request went well (OK) and the request was PICK_CONTACT_REQUEST
    if (resultCode == Activity.RESULT_OK && requestCode == PICK_CONTACT_REQUEST) {
        // Perform a query to the contact's content provider for the contact's name
        Cursor cursor = getContentResolver().query(data.getData(),
        new String[] {Contacts.DISPLAY_NAME}, null, null, null);
        if (cursor.moveToFirst()) { // True if the cursor is not empty
            int columnIndex = cursor.getColumnIndex(Contacts.DISPLAY_NAME);
            String name = cursor.getString(columnIndex);
            // Do something with the selected contact's name...
        }
    }
}

在此例子中,演示了你使用onActivityResult()方法處理activity結果的基本邏輯,第一個條件式檢查請求是否成功-如果成功,resultCode為RESULT_OK-回應的請求是否已知,requestCode配對startActivytForResult()的第二個參數。

contentResolver執行查詢,回傳一個Cursor物件,通過cursor物件讀取結果。

星期二, 10月 25, 2011

Activity (二)

Android應用程式學習筆記

Creating an Activity


建立一個activity,你必須建立Activity類的子類,在子類,你需要實現回調方法,系統會在activity專換不同生命週期狀態時呼叫,比如,activity建立、停止、恢復、銷毀,兩個最重要的回調方法是:
onCreate()
你必定實現此方法,系統建立你的activity時呼叫此方法,在實現此方法中,你應該初始化你的activity中重要的變數。最重要的是,這是你必須呼叫setContentView()方法去顯示activity的使用者介面的地方。
onPause()
當用戶離開你的activity時,系統呼叫此方法, 這通常是你應該堅持保存任何改變超過目前用戶的使用期間。


Implementing a user interface

 Activity的使用者介面是由view的階層所提供,每個view控制activity的視窗中特定的矩形空間,並且可以回應用戶的互動,比如,view可以是一個按鈕,當用戶觸碰它時啟動動作。

Android提供許多現成的views,你可以使用來設計及組織你的布局,"Widget"是view,桌面的小工具,"Layouts"由ViewGroup衍生的View,比如,線性布局或是相關布局,你可以運用view及viewgroup來創造你的桌面小工具或是布局,然後應用在你的activity上。

使用view定義布局最普遍的方式是存在你的應用程式資源中的XML布局文件,這樣的方式,你可以維護從定義應用程式行為的程式碼中分離的使用者介面的設計。你可以利用setContentView()方法傳入布局文件的ID,將布局文件設置為使用者介面。


Declaring the activity in the manifest

你必須在manifest文件中宣告你的activity,這樣系統才可以存取。宣告activity,打開你的manifest文件,並在<application>標籤範圍內加入<activity>標籤。例如:


<manifest ... >
  <application ... >
      <activity android:name=".ExampleActivity" />
      ...
  </application ... >
  ...</manifest >

有許多屬性你可以包含在此標籤中去定義activity的屬性,比如activity的標題、activity的圖像或是activity的使用者介面主題風格。android:name屬性是唯一一定要有的屬性。一旦你發行了應用程式,你就不應該改變這個名稱,因為如果你改變了,可能會破壞一些功能,比如,應用程式的捷徑。


Using intent filters

<activity>標籤也可以利用<intent-filter>指定多個intent過濾器,為了就是讓其他應用程式也可以活化它。

當你使用Android SDK工具建立新的應用程式時,工具自動地為你建立activity,它包含一個intent過濾器用來回應"main"動作,intent過濾器看起來像:


<activity android:name=".ExampleActivity" android:icon="@drawable/app_icon">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

<action>標籤指定了activity是應用程式的"main"的進入點,<category>標籤指定該activity應該被列表在系統上,讓用戶可以啟動它。

如果你不想允許你的應用程式受其他應用程式的activities活化,那你就不需要任何intent過濾器,只需要有"main"action和"Launcher"cagetory。

然而,如果你想你的activity回應從其他應用程式傳來的明確intent,那就必須為你的activity另外加上intent過濾器,每個過濾器必須有<intent-filter>標籤,<intent-filter>標籤必須包含<action>標籤,選擇性包含<category>標籤及<data>標籤,這些標籤決定你的activity回應那一種形式的intent。

星期二, 10月 18, 2011

MapView

Android應用程式學習筆記

MapView

顯示地圖的View,從Google Map Service取得數據。當它為焦點時,它可以抓取按鍵和觸碰手勢去搖鏡頭和變焦地圖。你也可以在程式碼中控制(getController())和可以繪製Overlay物件在地圖上(getOverlays())。

地圖可以顯示許多種模式:setSatellite(boolean)設定為衛星地圖、setTracffic(boolean)、setStreetView(boolean)。

首選的變焦機制就是內建的變焦機制,setBuildInZoomControls(boolean),當用戶搖鏡頭時,變焦控制會自動出現在MapView的底部。

MapView也是一個ViewGroup,LayoutParameters允許你附加其他View。

MapView只能藉由MapActivity建立,這是因為MapView必須依賴在後台存取網路及檔案系統的執行續。這些執行續的生命週期是由MapActivity看管,Tips是在應用程式目錄下緩衝的檔案系統,緩衝是自動管理,所以你不需要做任何事。

為了在MapView顯示Google Map,你必須註冊Google Map Service並獲得Map API 金鑰,可以參考如何利用Eclipse取得MD5 Fingerprint文章。

一旦你取得金鑰,你需要在XML布局文件中MapView的android:apiKey屬性上引用它。

Package com.google.android.maps

Android應用程式學習筆記

Package com.google.android.maps

此地圖套件允許應用程式顯示及控制Google Map介面,建立一個Google Map,你需要繼承MapActivity並且在布局上實現一個MapView。

為了在應用程式中使用MapView,你需要一個有"android:apiKey"屬性的MapView。

注意此套件並不是Android函式庫的標準套件,為了使用它,你必須在Androidmanifest文件中新增xml標籤在<application>標籤範圍中:

<uses-library android:name="com.google.android.maps" />


星期一, 10月 17, 2011

如何利用Eclipse取得MD5 Fingerprint

Android應用程式學習筆記

如何利用Eclipse取得MD5 Fingerprint

為何需要取得MD5 Fingerprint?
因為如果是想使用Google Map API就必須取得使用金鑰,那取得金鑰必須先取得MD5 fingerprint,再到官網產生金鑰。得到金鑰就能在應用程式中使用MapView等Google Map APIs。

取得方式有許多,可以使用指令完成,那對於指令不熟該怎麼辦?

以下就是不須透過指令,也一樣可以取得MD5 fingerprint的流程。

1.打開Eclipse。
2.Help > Install New Software。
3.在work with:中輸入http://keytool.sourceforge.net/update。
4.等到Name表中出現"Keytool",選取"Keytool"。
5.點擊Next。
6.當一切安裝完成時,在Eclipse中會出現"Keytool"菜單。



7.點擊Keytool > Open keystore。
8.點擊"Browse"然後在.android目錄下找到"debug.keystore"。
9.輸入android為密碼。
10.雙擊"androiddebugkey",顯示MD5 Fingerprint。



取得MD5 Fingerprint到Maps API Key Signup產生金鑰。

星期日, 10月 16, 2011

LocationManager LocationProvider LocationListener

Android應用程式學習筆記

LocationManager
此類提供存取系統定位服務,這些服務允許應用程式定期獲得裝置地理位置的更新,或是啟動應用程式指定的Intent,當裝置接近預設的地理位置時。 
你無須直接實現此類,透過context.getSystemService(Context.LOCATIO_SERVICE)取得LocationManager。
以下介紹幾個此類中的方法。
 public LocationProvider getProvider(String name)-取得名稱為name的LocationProvider。如果沒有此LocationProvider,回傳值為null。
public List<String> getProviders(boolean EnableOnly)-取得一組LocationProviders。參數值為true表示只回傳目前可用的LocationProvider。
public Location getLastKnownLocation(String provider)-回傳provider最後得知的位置。 
public void requestLocationUpdates(String provider , long minTime , float minDistance , LocationListener listener)-註冊目前的activity定期接受provider的通知,隨著當前位置不同或是狀態更新定期地呼叫LocationLListener。它也許要花一些時間接收最近期的位置,如果需要立即接收位置,應用程式可以利用getLastKnownLocation(String)方法。用戶關閉provider的情況下,更新將停止,並且呼叫onProviderDisable(String)方法。當provider再次啟動,onProviderEnable(String)將被呼叫,且位置更新將再次啟動。利用minTime和minDistance參數控制通知的頻率。如果minTime參數值大於0,LocationManager有機會在位置更新之間休息minTime毫秒來保存電力;如果minDistance參數值大於0,裝置移動超過minDistance距離,廣播一個位置。想盡可能的獲得通知,就將兩個參數設為0。後台服務應該留意設定充分的minTime,如此裝置不會消耗太多電力在保持GPS或是無線電台,特別是,不建議minTime數值小於6000毫秒。
LocationProvider
Location provider提供有關裝置的地理位置的定期報告,每個提供器有一組標準,在標準之下也許可以使用。舉例,一些提供器需要GPS硬體設備及許多衛星的能見度;其他需要蜂巢式無線電,或是存取特定載體的網路,或是網路。它們也有不同的電池消耗特性或是成本。
LocationListener
利用於接收當位置改變時LocationManager的通知,利用reuqestLocationUpdates(String , long , float , LocationListener)方法將監聽器註冊到位置管理服務(LocationManager)。
public void onLocationChanged(Location location)-當位置改變時呼叫此方法。
public void onProviderEnable(String provider)-當提供器啟用時呼叫此方法。
public void onProviderDisable(String provider)-當提供器關閉時呼叫此方法。
public void onStatusChanged(String provider , int status , Bundle extras)-當provider狀態改變時呼叫此方法。