Chapter 9 Services of the Mobile and Use of Communication Network 本投影片(下稱教用資源)僅授權給採用教用資源相關之旗標書籍為教科書之授課老師(下稱老師)專用,老師為教學使用之目的,得摘錄、編輯、重製教用資 源(但使用量不得超過各該教用資源內容之80%)以製作為輔助教學之教學投影片,並於授課時搭配旗標書籍公開播放,但不得為網際網路公開傳輸之遠距教學、 網路教學等之使用;除此之外,老師不得再授權予任何第三人使用,並不得將依此授權所製作之教學投影片之相關著作物移作他用。 著作權所有 © 旗標出版股份有限公司 Intent Introduction on Intent Android應用程式中的活動、服務或廣播接收器可經由 訊息啟動,然而包含這些資訊的訊息稱為Intent。 Intent是一種runtime binding機制,可以在兩個元件之間 進行連接。 例如說:有一個活動要開啟網頁瀏覽器查看網頁,那 此活動只需發出WEB_SEARCH_ACTION請求給 Android,Android會根據Intent的請求內容,查詢各元 件註冊時的IntentFilter,找到網頁瀏覽器活動來瀏覽網 頁。 Component Name Attribute of Intent 元件名稱是指Intent目標元件的名稱或是一個元件名稱對象。 這種對象名稱是目標元件類別名稱和目標元件所在應用程式 套件名稱的組合。 元件中封包名稱不一定要和manifest文件中的封包名稱完全符 合。 元件名稱通常是一個選項,如果Intent訊息中指定了目標元件 的名稱,這就稱為顯式訊息,Intent會傳送給指定的元件。 如果目標元件名稱並沒有指定,這就稱為隱式訊息,Android 會透過Intent內的其他訊息和已註冊的IntentFilter比較來選擇 合適的目標元件。 Action Attribute of Intent 動作是描述Intent所觸發動作名稱的字串常數,對 於BroadcastIntent來說,動作所指的是被廣播出去 的動作。 理論上動作可以為任何字串,而與Android系統應 用有關的動作,通常是以靜態字串常數的方式定 義在了Intent類別當中。 下頁表列出目前Android系統中常見的Activity Action Intent的動作,其餘可參照Android SDK。 Action Attribute of Intent Activity Action Intent: Activity Action Intent Constant Description ACTION_CALL 撥出Data中指定的電話號碼 ACTION_EDIT 開啟編輯Data中指定資料對應的應用程式 ACTION_MAIN 主程式入口,不接收資料,結束後也不回傳資料 ACTION_SYNC 在Android與Server之間同步資料 ACTION_VIEW 根據Data類型的不同,開啟相對應的應用程式並 顯示資料 啟動系統撥號程式或其他撥號程式,並顯示Data 中的號碼 像Data中描述的目標發送資料 ACTION_DIAL ACTION_SENDTO Action Attribute of Intent Broadcast Intent: BroadcastIntent Constant ACTION_TIME_TICK ACTION_TIME_CHANGED ACTION_TIMEZONE_CHANGED ACTION_BOOT_COMPLETED ACTION_PACKAGE_ADDED ACTION_PACKAGE_CHANGED ACTION_PACKAGE_REMOVED ACTION_UID_REMOVED Description 系統時間每過一分鐘發出的廣播訊息 系統時間透過設定發生變化 改變時區 系統重新啟動完成 新的apk封包安裝完成 現存的apk封包改變 現存的apk封包被刪除 使用者id被移除 Data Attribute of Intent Data描述Intent要操作的資料URI和資料類型。有的動作需 要對相應的Data進行處理。 – 例如說:對於動作ACTION_EDIT來說,它的Data可以是聯絡人、 簡訊等等可編輯的URI。而對於ACTION_CALL來說,它的Data 可以是一個tel://格式的電話號碼URI。 正確設定Intent的Data對於Android尋找系統中符合Intent要 求的元件是非常重要的。 – 如果你使用了ACTION_CALL,但是Data卻設定為mailto://格式 的URI,那麼原本想執行「啟動撥打電話」的動作,會因沒有與 之相對應的應用程式而不會被執行。所以每次使用Intent時,都 應注意與設置Action相關的資料類型和格式。 Category Attribute of Intent Category是對被請求元件的額外描述訊息。 Android也在Intent類別中定義了一些Category字串常 數,下表列出了常見的Category字串常數。 Category Constant Description CATEGORY_BROWSABLE 目標活動能透過在網頁瀏覽器中點擊連結啟動 (e.g. 瀏覽器中的圖片連結) CATEGORY_GADGET 表示目標活動可以被嵌入其他活動中 CATEGORY_HOME 目標活動為主要活動,就是手機開機後顯示的活動 或按下HOME鍵後顯示的活動 CATEGORY_LAUNCHER 表示目標活動是應用程式中最優先被執行的 CATEGORY_PREFERENCE 表示目標活動是一個有偏好設定的活動 Extra Attribute of Intent Extra屬性為使用Intent連接不同的元件時,有 時需要在Intent中附加額外的訊息,以便將資 料傳送給目標。 舉例來說:ACTION_TIMEZONE_CHANGED 需要帶有附加訊息以表示新的時區。 Extra Attribute of Intent Extra屬性用鍵值關聯結構保存在Intent當中, Intent透過呼叫putExtras()和getExtras()方法來儲存 和取得Extra。 Extra是以Bundle物件的形式來保存的,Bundle物 件提供了一系列put和get方法來設定、取得相應 鍵值訊息。 在Intent類別中也為Android系統應用的一些Exrta 的鍵值定義了靜態的字串常數。下頁表列出常見 的Extra常數。 Extra Attribute of Intent Extra Constant EXTRA_BCC EXTRA_CC EXTRA_EMAIL EXTRA_INTENT EXTRA_KEY_EVENT EXTRA_PHONE_NUMBER Description 附加郵件密送地址的字串 附加郵件副本地址的字串 附加郵件傳送地址的字串 使用ACTION_PICK_ACTIVITY動作時附加Intent選項的鍵值 觸發Intent按鍵的KeyEvent對象 使用撥打電話相關的Action時,附加電話號碼的鍵值,類型為 String EXTRA_SHORTCUT_ICON 使用ACTION_CREATE_SHORTCUT在主要活動建立快捷鍵時, EXTRA_SHORTCUT_ICON_RESOURCE 對快捷鍵的描述訊息。其中ICON與ICON_RESOURCE描述快 捷鍵圖示,類型分別為Bitmap和ShortcutIconResource。 EXTRA_SHORTCUT_INTENT EXTRA_SHORTCUT_NAME EXTRA_SUBJECT EXTRA_TEXT 描述快捷鍵相對應的Intent對象 描述快捷鍵的名稱 描述訊息主題的鍵值 使用ACTION_SEND動作時,用於描述欲發送的本文訊息,類 型為CharSequence EXTRA_TITLE 使用ACTION_CHOOSER動作時,描述對話框標題,類型為 CharSequence EXTRA_UID 使用ACTION_UID_REMOVED動作時,描述刪除的使用者id鍵 值,類型為int Introduction on Intent 在前面第三章有介紹到Android有活動、服務和廣 播接收器,分別也有不同的Intent傳送方式。 要啟動一個新的活動,或讓現有的活動執行新的 操作,可以透過呼叫Context.startActivity()或 Activity.startActivityForResult()方法。 – 這兩個方法需要傳入的Intent參數稱為活動行為意圖 (Activity Action Intent),根據Intent對目標活動描述的 不同,來啟動與Intent符合的活動或傳遞信息。 Introduction on Intent 要啟動一個新的服務,或者向一個已有的服務傳送新指令,呼叫 Context.startService()或Context.bindService()兩個方法,將啟動此方 法的上下文對象與Service連結。 透過Context.sendBroadcast()、Context.sendOrderBroadcast()和 Context.send-StickBroadcast()這三個方法可以發送BroadcastIntent。 – BroadcastIntent發送後,經系統比對後,擁有與BroadcastIntent相符合 的IntentFilter會通知它的BroadcastReceiver啟動。 這種機制被廣泛運用於設備或系統狀態變化的通知。 – 舉例來說,當Android的電池電量過低時,系統會發送Action為 BATTERY_LOW的廣播,接著任何符合該Action的IntentFilter所註冊的 BroadcastReceiver都會啟動自訂處理程序,例如說:關閉手機的Wi-FI 與GPS以節省電池耗損。 Introduction on Intent 當Intent送出後,Android都會準確找到相符合 的一個或多個活動、服務或廣播接收器作為回 應。因此不同類型的Intent訊息不會出現重複 的。 BroadcastIntent訊息只會傳送給廣播接收器, 不會發送給活動或服務。 – 由startActivity()傳送的Intent也只會送給活動 – 由startService()傳送的Intent只會發送給服務。 Introduction on Intent Intent abstractly describes 要執行的動作 including: – 元件名稱(Component name) – 動作(Action) – 資料(Data) – 類別(Category) – 附加訊息(Extra) – 標號(Flag) We will have detailed introduction in next page。 How to Use IntentFilter 應用程式的元件為了告訴Android本身能對應、處理 哪些隱式Intent的請求,可以定義一個或多個 IntentFilter。 每個IntentFilter描述該元件所能對應的Intent請求能力 及接收何種類型的請求行為、資料。 舉例來說,網頁瀏覽器的IntentFilter應定義它所希望 接收的Intent Action是WEB_SEARCH_ACTION,以 及相關的請求資料是網址URI格式。 How to Use IntentFilter 一般來說,最常定義IntentFilter的方法是在 AndroidManifest.xml文件中用標籤<Intent-Filter>描述元件 的IntentFilter。 隱式Intent和IntentFilter進行比較時的三個條件是Intent的 Action、Data以及Category。 實際上,一個隱式Intent要求要能夠傳送給目標元件,必 要透過這三個條件的檢查,如果任何一個條件不符合, Android都不會將隱式Intent傳送給目標元件。 How to Use IntentFilter 1.動作驗證 <intent-filter>標籤中可以包括<action>子標籤, 範例如下: <intent-filter> <action android:name="com.example.project.SHOW_CURRENT" /> <action android:name="com.example.project.SHOW_RECENT" /> <action android:name="com.example.project.SHOW_PENDING" /> </intent-filter> 一個<intent-filter>標籤至少包含一個<action>標籤,否則任何Intent 請求都無法與該<intent-filter>相符合。 如果Intent請求的Action和<intent-filter>中個某一個<action>相符, 該Intent就符合了這個<intent-filter>的動作驗證。 如果Intent請求或<intent-filter>中沒有說明具體的Action類型,那麼 會出現下面兩種情況。 How to Use IntentFilter 2.類別驗證 <intent-filter>標籤中可以包括<category>子標籤, 範例如下: <intent-filter . . . > <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> </intent-filter> 只有當Intent請求中所有的Category與元件中某一個 IntentFilter的<category>完全相符時,才會讓該Intent請求 通過驗證,IntentFilter中多餘的<category>聲明並不會導 致比對失敗。 一個沒有指定任何類別驗證的IntentFilter只會匹配沒有設 置類別的Intent請求。 How to Use IntentFilter 3.資料驗證 資料在<intent-filter>中的範例如下: <intent-filter . . . > <data android:type="video/mpeg" android:scheme="http" . . . /> <data android:type="audio/mpeg" android:scheme="http" . . . /> </intent-filter> <data>標籤指定了希望接受Intent請求的資料URI和資料類型,URI被分成 三部分來比對:scheme、authority和path。 其中,用setData()設定Intent請求的URI資料類型和scheme必須與 IntentFilter中所指定的一致。若IntentFilter中還指定了authority或path,它 們也需要相符合才會通過驗證。 講解完Intent基本概念之後,接下來就透過使用Intent啟動Android本身的電 話撥號程式,來驗證上述所講述的概念。 Intent Practice Exercise The former content introduces implication of to the readers. Here we will introduces how to use Intent in applications through an example. 在這個範例中使用一個Intent啟動電話撥號程 式,其中Intent的行為是ACTION_DIAL,同時 在Intent中傳送聯絡人的電話號碼,範例如下 頁圖所示。 Intent Practice Exercise Diagram of the example: Intent Practice Exercise Layout.xml (res/layout/main.xml): <?xml version="1.0" encoding="utf-8"?> <LinearLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/androi d" > <EditText android:id = "@+id/phoneNumber" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <Button android:id = "@+id/btnDial" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/dial" /> </LinearLayout> Intent Practice Exercise Codes (IntentEX.java): public class IntentEX extends Activity { private String strNumber; private Button btnDial; private EditText phoneNumber; /** Called when the Activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); btnDial = (Button)findViewById(R.id.btnDial); phoneNumber = (EditText)findViewById(R.id.phoneNumber); btnDial.setOnClickListener(new Button.OnClickListener() { @Override public void onClick(View v) { strNumber = phoneNumber.getText().toString(); /* 建立Intent */ Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel://" + strNumber)); /* 啟動活動 */ startActivity(intent); } }); } } Intent Practice Exercise 此範例使用EditText與Button,在EditText中輸 入號碼,在點選撥號鍵,就會呼叫內建的撥號 程式進行撥打。 上述的範例是使用Android內建的撥號程式, 想必讀者一定會想知道如何不使用內建的撥號 程式進行撥打,其實這部分就是需要使用到 IntentFilter。 Intent Practice Exercise Originally, there is only one <intent-filter> in AndroidManifest.xml: <intent-filter> <action android:name="android.Intent.action.MAIN" /> <category android:name="android.Intent.category.LAUNCHER" /> <intent-filter> At present, there is only one IntentFilter. Its action name is Action.MAIN; its category name is Category.LAUNCHER。 With this IntentFilter, IntentEX 圖示will appear in application menu Intent Practice Exercise Insert the codes below into AndroidManifest.xml: <intent-filter> <action android:name="android.intent.action.CALL_BUTTON"/ <category android:name="android.intent.category.DEFAULT" /> <intent-filter> Intent Practice Exercise 更改後的效果如下頁圖所示,當按下模擬器右側鍵盤 的綠色撥號鍵時,系統會彈出一個視窗,可以選擇啟 動IntentEX或Android內建的撥號程式。 這個範例說明了隱式Intent的用法,IntentEX定義本身 的IntentFilter行為是ACTION.CALL_BUTTON,每次使 用者按下撥號鍵時,Android系統都會將撥號鍵的Intent 和所有定義過ACTION.CALL_BUTTON的IntentFilter進 行比較,然後將符合的元件提供給使用者選擇。 Intent Practice Exercise Diagram of the example: Hardware-Related Application Camera 關於Android上的相機應用,可分為兩部分: 取景和拍攝照片的功能,一般來說拍照功能相 對於取景來說是較簡單的,以下這個範例將會 講解如何實作這兩部分。範例程式如圖所示。 Camera First, insert permission of camera into Androidmanifest.xml: <uses-feature android:name="android.hardware.camera" /> <uses-permission android:name="android.permission.CAMERA" /> Then insert and write permission of SDCard : <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> Camera Layout.xml (res/layout/main.xml): <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/layout"> <TextView android:text="CameraEX" android:textSize="22sp" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <FrameLayout android:id="@+id/wPreview" android:layout_weight="1" android:layout_width="fill_parent" android:layout_height="fill_parent" /> <Button android:id="@+id/btnClick" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Click" android:layout_gravity="center" /> </LinearLayout> Camera Codes-1(Preview.java): Preview(Context context) { super(context); /* 取得holder */ surfaceHolder = getHolder(); surfaceHolder.addCallback(this); /* 設定預覽Buffer Type */ surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_P USH_BUFFERS); } public void surfaceCreated(SurfaceHolder holder) { /* 若相機非在預覽模式,則開啟相機 */ camera = Camera.open(); try { /* setPreviewDisplay唯一的參數為SurfaceHolder */ camera.setPreviewDisplay(holder); camera.setPreviewCallback(new PreviewCallback() { public void onPreviewFrame(byte[] data, Camera arg1) { /* 在此可針對預覽圖像作一些優化 */ } }); } catch (IOException e) { e.printStackTrace(); } } public void surfaceDestroyed(SurfaceHolder holder) { /* 停止Preview */ camera.stopPreview(); camera = null; } public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { /* 建立Camera.Parameters物件 */ Camera.Parameters parameters = camera.getParameters(); /* 設定預覽畫面大小 */ parameters.setPreviewSize(320, 240); /* 設定圖像格式 */ parameters.setPictureFormat(PixelFormat.JPEG); /* 將上述設定之參數給Camera */ camera.setParameters(parameters); /* 立即執行Preview */ camera.startPreview(); } Owing to the codes are numerous, please refer to the reference disc to find the complete codes of CameraEX.java and Preview.java Sensor About development of sensors on mobiles, Android platform integrates hardware devices and make them more convenient to use. We have firstly understand what sensor constants Android provides to applications. Types of Sensors – Direction, accelerometer, light, magnetic field, distance, temperature, etc. Sampling Rate – 最快、遊戲、普通、使用者界面。當應用程式請求特定的 取樣率時,只是對感測器系統的一個建議,並不保證特定 的取樣率可用。 Accuracy – High, low, medium, unreliable Sensor SensorEventListener is 入口of sensor application. It includes two approaches: – onSensorChanged(SensorEvent e)方法在感測器值變更 時呼叫。 • 該方法只對受此應用程式監視的感測器呼叫。 • 每種感測器所提供的資料不一定一樣多,像是方向和加速表 傳感器都提供三個資料。 – 當感測器的準確性變更時,將會呼叫 onAccuracyChanged(Sensor s, int accuracy) 方法。 • 參數包括兩個參數:一個表示感測器,另一個表示該感測器 的新準確值。 Sensor 當需要與感測器互動時,應用程式必須向系統註冊, 藉此監視一個或多個與感測器相關的活動。 關於註冊的方法是使用 SensorManager 類別中的 registerListener 方法。 不過在此需要注意的是,並非所有 Android 的設備都支 援 SDK 中所定義的感測器。 假設某種感測器無法在特定的設備上使用,系統會自 動降級。 Sensor The example tests G-sensor as shown below: Sensor Layout.xml (res/layout/main.xml): <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TextView android:id="@+id/output" android:layout_width="fill_parent" android:text="@string/hello" android:textSize="24sp" android:layout_height="fill_parent" android:layout_margin="30dp" /> </LinearLayout> Sensor Codes-1(SensorEX.java): public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); /* 取得感測器服務 */ mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE); /* 註冊加速度監聽器 */ mSensorManager.registerListener(mSensorListener, mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_FASTEST); textView = new TextView(this); setContentView(textView); } Sensor Codes-2(SensorEX.java): private final SensorEventListener mSensorListener = new SensorEventListener() { public void onSensorChanged(SensorEvent se) { /* 取得x,y,z加速度值 */ x = se.values[0]; y = se.values[1]; z = se.values[2]; textView.setText("x: "+ x +", y: "+ y +", z: " + z); } public void onAccuracyChanged(Sensor sensor, int accuracy) { } }; Sensor Codes-3(SensorEX.java): protected void onResume() { super.onResume(); mSensorManager.registerListener(mSensorListener, mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_FASTEST); } protected void onStop() { /* 註銷監聽器 */ mSensorManager.unregisterListener(mSensorListener); super.onStop(); } Please refer to the reference disc to find the complete codes of SensorEX.java Mobile Control/Management Introduction Android many API which is useful for mobile control and management. Generally speaking, SIM card information, directory, phone mode, call records and so on can be controlled and managed by Android API. Through introduction of this chapter, the readers are allowed to how convenient it is to use mobile control and management. PhoneNumberUtils PhoneNumberUtils顧名思義就是與電話號碼有 關的工具集,因此裡面包含了許多對於電話格 式的一些方法。 此範例延伸前面章節所使用的Intent程式,範 例如圖所示。 PhoneNumberUtils Layout.xml (res/layout/main.xml): <?xml version="1.0" encoding="utf-8"?> <LinearLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android " > <EditText android:id = "@+id/phoneNumber" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <Button android:id = "@+id/btnDial" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/dial" /> </LinearLayout> PhoneNumberUtils Codes (PhoneNumberUtilsEX.java): public void onClick(View v) { strNumber = phoneNumber.getText().toString(); /* 判斷電話號碼是否為正確 */ if ( PhoneNumberUtils.isGlobalPhoneNumber(strNumber) ) { Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel://" + strNumber)); startActivity(intent); } else { Toast.makeText(PhoneNumberUtilsEX.this, R.string.message, Toast.LENGTH_LONG).show(); } } Please refer to the reference disc to find the complete codes of PhoneNumberUtilsEX.java PhoneNumberUtils Codes (PhoneNumberUtilsEX.java): public void onClick(View v) { strNumber = phoneNumber.getText().toString(); /* 判斷電話號碼是否為正確 */ if ( PhoneNumberUtils.isGlobalPhoneNumber(strNumber) ) { Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel://" + strNumber)); startActivity(intent); } else { Toast.makeText(PhoneNumberUtilsEX.this, R.string.message, Toast.LENGTH_LONG).show(); } } Please refer to the reference disc to find the complete codes of PhoneNumberUtilsEX.java ServiceState ServiceState includes information related to phone state and services provided similar to TelephonyManager. The example is shown below: ServiceState ServiceState includes the following information: – 服務狀態: • • • • IN_SERVICE OUT_OF_SERVICE EMERGENCY_ONLY POWER_OFF – 漫遊指示器 – 營運商名稱、縮寫、編號 – 選擇網路模式(手動、自動) ServiceState Layout.xml (res/layout/main.xml): <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:id="@+id/serviceInfo" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout> ServiceState Codes (ServiceStateEX.java): public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); phoneInfo = (TextView)findViewById(R.id.serviceInfo); serState = new ServiceState(); strBdr = new StringBuilder(); /* 透過ServiceState取得各類資訊 */ strBdr.append("\n 服務業者名稱 = " + serState.getOperatorAlphaLong()); strBdr.append("\n 服務業者編號 = " + serState.getOperatorNumeric()); strBdr.append("\n 服務狀態 = " + serState.getState()); strBdr.append("\n 是否處於漫遊狀態 = " + (serState.getRoaming()?"yes":"no")); phoneInfo.setText(strBdr.toString()); } Please refer to the reference disc to find the complete codes of ServiceStateEX.java TelephonyManager TelephonyManager is used to get information in SIM or telecom network, e.g. telecom company name, network type, IMEI code in mobile, etc. The example is shown below: TelephonyManager To get information from the mobile, we have to insert the permission below: <uses-permission android:name="android.permission.READ_PHONE_STATE" /> TelephonyManager Layout.xml (res/layout/main.xml): <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TextView android:id="@+id/phoneInfo" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout> TelephonyManager Codes (TelephonyManagerEX.java): public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); phoneInfo = (TextView)findViewById(R.id.phoneInfo); telMgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); strBdr = new StringBuilder(); /* 透過TelephonyManager取得手機各類資訊 */ strBdr.append("\n 設備編號(IMEI) = " + telMgr.getDeviceId()); strBdr.append("\n 設備軟體版本 = " + telMgr.getDeviceSoftwareVersion()); strBdr.append("\n 線路1號碼 = " + telMgr.getLine1Number()); strBdr.append("\n 服務業者所在國碼 = " + telMgr.getNetworkCountryIso()); strBdr.append("\n 服務業者 = " + telMgr.getNetworkOperator()); strBdr.append("\n 服務業者名稱 = " + telMgr.getNetworkOperatorName()); strBdr.append("\n 網路類型 = " + telMgr.getNetworkType()); strBdr.append("\n 手機類型 = " + telMgr.getPhoneType()); strBdr.append("\n Sim卡所在國碼 = " + telMgr.getSimOperatorName()); strBdr.append("\n Sim卡營運商 = " + telMgr.getSimOperator()); strBdr.append("\n Sim卡營運商名稱 = " + telMgr.getSimOperatorName()); strBdr.append("\n Sim卡序號 = " + telMgr.getSimSerialNumber()); strBdr.append("\n Sim卡狀態 = " + telMgr.getSimState()); strBdr.append("\n 訂閱者編號(IMSI) = " + telMgr.getSubscriberId()); strBdr.append("\n 音效郵件號碼 = " + telMgr.getVoiceMailNumber()); phoneInfo.setText(strBdr.toString()); } PhoneStateListener PhoneStateListener 提供了監聽來電、收發簡訊或 Email…等等這些事件的方法,因此想要監控手機狀 態,就需透過PhoneStateListener。The example is shown below︰ PhoneStateListener Layout.xml (res/layout/main.xml): <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TextView android:id="@+id/signal" android:layout_width="fill_parent" android:text="@string/hello" android:textSize="24sp" android:layout_height="fill_parent" android:layout_margin="30dp" /> </LinearLayout> PhoneStateListener Codes-1(PhoneStateListenerEX.java): protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); /* 透過getSystemService取得TELEPHONY_SERVICE */ TelephonyManager telMgr = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE); /* 加入通話監聽器 */ telMgr.listen(new PhoneCallListener(), PhoneStateListener.LISTEN_CALL_STATE); } PhoneStateListener Codes-2(PhoneStateListenerEX.java): /* 當狀態改變時發生 */ public void onCallStateChanged(int state, String incomingNumber) { super.onCallStateChanged(state, incomingNumber); /* 判斷目前狀態 */ switch (state) { /* 透過TelephonyManager取得目前狀態,CALL_STATE_IDLE 為閒置 */ case TelephonyManager.CALL_STATE_IDLE: Context context1 = getApplicationContext(); CharSequence text1 = "閒置狀態"; int duration1 = Toast.LENGTH_LONG; // 設定停留長短 Toast.makeText(context1, text1, duration1).show(); break; /* 透過TelephonyManager取得目前狀態, CALL_STATE_OFFHOOK為通話中 */ case TelephonyManager.CALL_STATE_OFFHOOK: Context context2 = getApplicationContext(); CharSequence text2 = "通話中..."; int duration2 = Toast.LENGTH_LONG; // 設定停留長短 Toast.makeText(context2, text2, duration2).show(); break; /* 透過TelephonyManager取得目前狀態, CALL_STATE_RINGING為響鈴中 */ case TelephonyManager.CALL_STATE_RINGING: Context context3 = getApplicationContext(); CharSequence text3 = "響鈴中..."; int duration3 = Toast.LENGTH_LONG; // 設定停留長短 Toast.makeText(context3, text3, duration3).show(); break; default: break; } } PhoneStateListener 此範例會針對來電時的各種不同的狀態顯示Toast, 像是震鈴時或通話時,在Android系統中都有定義不 同的常數。呼叫狀態如下表所示: Call_State Constant CALL_STATE_IDLE Mode 閒置狀態 CALL_STATE_RINGING 震鈴/等待 CALL_STATE_OFFHOOK 撥號/通話 PhoneStateListener Finally, we list and explain some commonly used permission parameter AndroidManifest.xml: PERMISSION_NAME FUNCTION of PERMISSION ACCESS_COARSE_LOCATION 透過CellID或WiFi來取得大約的位置 ACCESS_FINE_LOCATION 獲得精確位置(例如說:GPS) ACCESS_COARSE_UPDATES 允許獲得位置更新 READ_PHONE_STATE 讀取手機狀態 SEND_SMS 允許發送簡訊 CALL_PHONE 允許撥打電話 Q&A