Java講義

Similar documents
第 2 節 介面佈局檔 第 1 項 說明 第 2 項 原始碼 第 3 節 主程式開發 第 1 項 主程式 - 基本設定 第 2 項 主程式 - 產生亂數 第 3 項 主程式 - 數字靠邊 數字加總 第 4 節 加入手

Java講義

Android Service

多媒體應用 13 新增專案並完成版面配置 <ExMusic01> <activity_main.xml> ImageView ID imgplay ImageView ID imgstop ImageView ID imgfront TextView ID txtsong TextView ID t

主程式 : public class Main3Activity extends AppCompatActivity { ListView listview; // 先整理資料來源,listitem.xml 需要傳入三種資料 : 圖片 狗狗名字 狗狗生日 // 狗狗圖片 int[] pic =new

Java講義

單步除錯 (1/10) 打開 Android Studio, 點選 Start a new Android Studio project 建立專案 Application name 輸入 BMI 點下 Next 2 P a g e

Dynamic Layout in Android

res/layout 目录下的 main.xml 源码 : <?xml version="1.0" encoding="utf 8"?> <TabHost android:layout_height="fill_parent" xml

Android Robert C.C. Huang Oscar F.Y. Liu Peter C.L. Hsieh 2011/03/21

TPM BIOS Infineon TPM Smart TPM Infineon TPM Smart TPM TPM Smart TPM TPM Advanced Mode...8

投影片 1

Microsoft Word zw

Microsoft Word - 第1章 Android基本概念.docx

Database_001


用手機直接傳值不透過網頁連接, 來當作搖控器控制家電 ( 電視遙控器 ) 按下按鍵發送同時會回傳值來確定是否有送出 問題 :1. 應該是使用了太多 thread 導致在傳值上有問題 2. 一次按很多次按鈕沒辦法即時反應

Android Fragment

epub83-1

e-Submission System Quick Reference Guide for Publication Related Matters (Chinese version)

0511-Android程式之GPS應用_專題週記4

目 錄 項 目 內 容 頁 數 1 手 機 要 求 3 2 登 記 程 序 3 3 登 入 程 序 4 4 輸 入 買 賣 指 示 6 5 更 改 指 示 14 6 取 消 指 示 18 7 查 詢 股 票 結 存 21 8 查 詢 買 賣 指 示 23 9 更 改 密 碼 查 詢 股

證 券 簡 易 下 單 :2121 證 券 簡 易 下 單 1. 主 工 具 列 的 視 窗 搜 尋 器 直 接 輸 入 點 擊 主 選 單 證 券 專 區 下 單 特 殊 下 單 2121 證 券 簡 易 下 單 畫 面 說 明 1. 下 單 區 2. 個 股 行 情 資 訊 與

實作SQLiteOpenHelper類別

目 錄 版 次 變 更 記 錄... 2 原 始 程 式 碼 類 型 之 使 用 手 冊... 3 一 安 裝 軟 體 套 件 事 前 準 備... 3 二 編 譯 流 程 說 明

ShareText

Microsoft PowerPoint - ch6 [相容模式]

(Microsoft Word - wes _\246p\246\363\250\317\245\316LED\277O\305\343\245\334\252\254\272A.doc)

建立Android新專案

任務二 : 產生 20 個有炸彈的磚塊, 放在隨機的位置編輯 Block 類別的程式碼 import greenfoot.; // (World, Actor, GreenfootImage, Greenfoot and MouseInfo) Write a description of class

(Microsoft Word - MOODLE990201\266i\266\245\244\342\245U )

建立Android新專案

目 錄 頁 1. 歡 迎 使 用 網 上 預 約 面 談 訪 問 系 統 新 用 戶 新 用 戶 登 入 帳 戶 程 序 啟 動 網 上 預 約 面 談 訪 問 帳 戶 核 對 帳 戶 的 地 址 資 料

IBM Rational ClearQuest Client for Eclipse 1/ IBM Rational ClearQuest Client for Ecl

PART 2 系 統 篇 仔 細 檢 查 記 憶 體 和 顯 示 卡 AIDA64 Everest 操 作 : 使 用 AIDA64 檢 測 主 機 溫 度 AIDA64 DirectX AIDA

<4D F736F F D20BBF9D3DA416E64726F6964C6BDCCA8B5C4B5E7D7D3C5C4C2F4CFB5CDB32E646F63>

预览图 : (2) 在 SelectCity.java 中增加控件, 用于绑定 select_city 文件的 ListView, TextView,EditTest 等控件 代码和注释如下 :

WebSphere Studio Application Developer IBM Portal Toolkit... 2/21 1. WebSphere Portal Portal WebSphere Application Server stopserver.bat -configfile..

書面

目 錄 壹 題 目 1: 新 增 商 品 ( 商 品 名 稱 為 玉 井 芒 果 乾 禮 盒 )... 3 貳 題 目 2: 新 增 商 品 ( 商 品 名 稱 為 紅 磚 布 丁 精 選 禮 盒 )... 5 參 題 目 3: 新 增 商 品 ( 商 品 名 稱 為 晶 鑽 XO 醬 禮 盒 ).

Microsoft Word - 02.目錄.doc

The golden pins of the PCI card can be oxidized after months or years

實德證券網上交易系統示範

ContextMenu

PowerPoint 簡報

Microsoft Word - ASM SDK 說明文件

目 錄 一 系 統 登 入... 2 ( 一 ) 系 統 登 入 畫 面... 2 ( 二 ) 首 次 登 入 請 先 註 冊... 3 ( 三 ) 忘 記 單 位 帳 號... 8 ( 四 ) 忘 記 密 碼 ( 五 ) 健 保 卡 更 換 ( 六 ) 重 寄 確 認 信.

3. 給 定 一 整 數 陣 列 a[0] a[1] a[99] 且 a[k]=3k+1, 以 value=100 呼 叫 以 下 兩 函 式, 假 設 函 式 f1 及 f2 之 while 迴 圈 主 體 分 別 執 行 n1 與 n2 次 (i.e, 計 算 if 敘 述 執 行 次 數, 不

1.JasperReport ireport JasperReport ireport JDK JDK JDK JDK ant ant...6

附录J:Eclipse教程

Microsoft Word - template03.docx

AL-M200 Series

128 提 示 樞 紐 分 析 表 的 用 途 樞 紐 分 析 表 是 指 可 以 用 來 快 速 合 併 和 比 較 大 量 資 料 的 互 動 式 表 格, 透 過 它 可 以 詳 細 分 析 數 值 資 料, 特 別 適 用 於 下 列 情 況 : 需 要 從 含 有 大 量 資 料 的 清

<4D F736F F D20BEC7B2DFB3D0B379A741AABAB2C4A440ADD3A6E6B0CA617070BEDEA740A4E2A555>

Windows XP

RecyclerView and CardVew

Microsoft Word - template.doc

pico說明書繁體new

Microsoft PowerPoint - 資料庫正規化(ccchen).ppt

NCKU elearning Manual

101年度社會福利方案 網路線上操作手冊

Android Android Android SDK iv

Acronis Backup & Recovery 11 進階版本

图 6-1 主界面 MainActivity 界面对应的布局文件 (activity_main.xml) 如下所示 : <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="

1.ai

投影片 1

Fun Time (1) What happens in memory? 1 i n t i ; 2 s h o r t j ; 3 double k ; 4 char c = a ; 5 i = 3; j = 2; 6 k = i j ; H.-T. Lin (NTU CSIE) Referenc

ASP.NET MVC Visual Studio MVC MVC 範例 1-1 建立第一個 MVC 專案 Visual Studio MVC step 01 Visual Studio Web ASP.NET Web (.NET Framework) step 02 C:\M

6-1-1極限的概念

目 錄 一 ANDROID 開發系統需求 作業系統 開發工具... 1 二 安裝 ANDROID 開發工具 安裝 JDK 使用 APT-GET 安裝 使用套件管理程式安裝... 9 三 ANDROID 程式撰寫... 1

Microsoft Word - 第3章.doc

1. 安 裝 1.1 手 機 端 安 裝 檔 (cab 檔 ) 請 您 將 下 載 的 cab 檔 案 複 製 到 手 機 內 任 一 資 料 夾, 在 手 機 上 點 擊 cab 檔 案 後 即 可 開 始 安 裝 點 擊 本 檔 案 即 可 開 始 安 裝 請 於 您 的 手 機 上 繼 續 安

新・解きながら学ぶJava

EJB-Programming-3.PDF

Microsoft Word doc

Lecture01_Android介绍

iziggi

Cadence SPB 15.2 VOICE Cadence SPB 15.2 PC Cadence 3 (1) CD1 1of 2 (2) CD2 2of 2 (3) CD3 Concept HDL 1of 1

BSP 烤箱 - 封面-2

untitled

第二組掃描器規範書

詞 彙 表 編 號 詞 彙 描 述 1 預 約 人 資 料 中 文 姓 名 英 文 姓 名 身 份 證 字 號 預 約 人 電 話 性 別 2 付 款 資 料 信 用 卡 別 信 用 卡 號 信 用 卡 有 效 日 期 3 住 房 條 件 入 住 日 期 退 房 日 期 人 數 房 間 數 量 入

Android 开发教程

Internet Explorer Internet Explorer Internet Explorer Internet Explorer

關 於 教 育 部 學 習 拍 立 得 教 育 部 於 (103) 年 度 整 合 各 縣 市 政 府 部 屬 機 構 大 學 及 民 間 的 數 位 資 源 與 服 務, 依 不 同 類 型, 分 別 匯 集 於 教 育 大 市 集 教 育 百 科 教 育 媒 體 影 音 教 育 部 學 習 拍

Eclipse C C++, or

AL-MX200 Series

内 容 提 要 将 JAVA 开 发 环 境 迁 移 到 Linux 系 统 上 是 现 在 很 多 公 司 的 现 实 想 法, 而 在 Linux 上 配 置 JAVA 开 发 环 境 是 步 入 Linux 下 JAVA 程 序 开 发 的 第 一 步, 本 文 图 文 并 茂 地 全 程 指

Symantec™ Sygate Enterprise Protection 防护代理安装使用指南

基于UML建模的管理管理信息系统项目案例导航——VB篇

Android + NFC

PowerPoint 簡報

瑞興銀行

K7VT2_QIG_v3

Microsoft PowerPoint - 03 开发入门.ppt [兼容模式]


計 算 機 概 論 Computer Siene ))) 8- 啟 動 與 認 識 PowerPoint [ 開 始 ] \ [ 所 有 程 式 ] \ [Mirosoft Offie] \ [Mirosoft Offie PowerPoint 200] PowerPoint [ 新 增 ] \ [

PPBSalesDB.doc

Guide to Install SATA Hard Disks

Transcription:

Android 講義 2012.11.11 目錄 第一章 android 的第一次接觸...3 第一節 Windows 7 安裝 Android SDK 開發環境...3 第一項安裝 jdk...3 第二項設定 jdk 的環境變數...4 第三項安裝 Android SDK...8 第四項安裝 eclipse...11 第五項在 eclipse 安裝 ADT plugin...13 第二節建立 AVD 模擬環境...17 第三節 eclipse 環境設定...22 第四節建立第一個 android 專案...25 第五節擷取 android 裝置的畫面...34 第二章猜數字比大小...37 第一項建立專案...37 第二項建立介面佈面檔...37 第三項主程式...38 第三章使用 WebView 建立程式...41 第一項修改 AndroidManifest.xml 檔案...41 第二項修改 main.xml...42 第三項建立 mainwebview.xml...43 第四項建立 Activity 主程式...43 第五項建立 golink01 程式...45 第六項建立 golink02...46 第四章音樂播放程式...47 第一節最陽春的音樂播放程式...47 第一項建立空白的新專案...47 第二項加入 MediaPlayer 物件...47 第二節改善這個程式...49 第一項瞭解 Activity 的生命週期...49 第二項離開程式時也能停止音樂的播放...52 第三項按下播放按鈕才開始播放...52 第五章 SQLite 資料庫...56 1

第一節使用 SharedPreferences...56 第一項介面佈局檔...56 第二項建立主程式的內容 儲存偏好設定...56 第三項驗證儲存偏好的動作...58 第四項建立主程式的內容 提取偏好設定...58 第二節簡單使用 SQLite...60 第一項介面佈局檔...60 第二項建立 SQLiteOpenHelper 的子類別...60 第三項修改主程式...61 第四項驗證看看 sqlite3 指令...64 第五項顯示資料表內容...65 第六章 GPS 服務...67 第一節設定 manifest 的使用授權項目...67 第二節建立介面佈局檔...68 第三節建立連結資料庫的 dbhelper...73 第四節建立主程式...74 第五節建立第二個程式 列出歷史資料...80 第一項佈景主題...80 第二項主程式...81 第七章 service...84 第一節建立 MediaPlayer Server...84 第一項修改 androidmanifest.xml 檔案...84 第二項建立 MediaPlayService.java...85 第三項建立主程式...85 2

第一章 andr oid 的第一次接觸 android 的開發環境 建議使用 jdk eclipse android sdk 的整合開發環境 以下 就分別 來安裝這三個環境 開始 android 的程式設計 第一節 Windows 7 安裝 Android SDK 開發環境 第一項 安裝 jdk 1. 首先 請分別下載 jdk eclipse android-sdk 以下範例統一放置於 D:\apps 目錄裡 2. 請先雙按 jdk 程式 開始安裝動作 安裝過程請按 Next 繼續即可 3

3. 安裝完成後 請按 Close 關閉 jdk 第二項 設定 jdk 的環境變數 4. 開啟 Windows 檔案總管 找到 jdk 的安裝目錄 以現有的例子來看 由 C:\Program Files\ 目錄下會找到 Java 的資料夾 底下會有 jdk 與 jre 二個資料夾 請點 選開啟 jdk 的資料夾 再點開其中的 bin 資料夾 這個位置 就是 java 與 javac 執行檔所存放的位置 請將上方網址列選取 按右鍵複製下來 以這個例子來看 複製的位置是 C:\Program Files\Java\jdk1.7.0_07\bin 4

5. 在 電腦 / 右鍵 / 內容 6. 點選左方的 進階系統設定 5

7. 點選到 進階 標籤頁 再按 環境變數 8. 在下方的 系統變數 這裡 點選 Path 按 編輯 6

9. 在 變數值 的最後面 先輸入 ; 半形的分號 再按 Ctrl + V 貼上 將我們前 面所複製的 C:\Program Files\Java\jdk1.7.0_07\bin 位置貼到這裡 完成後 按 確 定 關閉對話框 10. 按下 系統變數 下方的 新增 在對話框的 變數名稱 的欄位裡輸入 JAVA_HOME 在 變數值 的欄位裡輸入 C:\Program Files\Java\jdk1.7.0_07 這個位置是 jdk 的安裝位置 和我們剛才貼到 path 的位置相 比較 只差在 bin 的目錄 如果沒有做這個動作 接下來的 android SDK 就無法安裝哦 7

11. 開始 命令提示字元 後 可以分別執行 java -version javac -version 這裡 要能正常顯示版本號碼 第三項 安裝 Android SDK 12. 接下來要安裝 android SDK 在該壓縮檔上按 右鍵 / 7-Zip / 解壓縮至此 8

13. 進入解壓縮的 android-sdk-windows 資料夾 雙按執行 SDK Manager.exe 程式 14. 執行這個動作時 請儘量以有線網路連線 勾選要安裝的 android SDK 以這裡為例 最上方的 Tools 一定要勾選 再來就選最 新的版本 我通常還會再勾選 Android 2.1 或 Android 2.3.3 的版本 勾選完成後 請按右下方的 Install xx packages 按鈕 9

15. 選擇 Accept All 按 Install 開始安裝 依網路環境連線速率不同 請耐心等待一 些時間 16. 大致的動作和前項說明相同 分別將 C:\android-sdk-windows\tools C:\androidsdk-windows\platform-tools 這二個路徑加到系統環境變數的 Path 項目裡 10

第四項 安裝 eclipse 17. 前項 android SDK 安裝完成後 我們要來進行 eclipse 的設定動作 首先 在 eclipse 按 右鍵 / 7-Zip / 解壓縮至此 18. 進行 eclipse 的目錄 雙按執行 eclipse.exe 程式 11

19. 指定 eclipse 的工作目錄 我是將它指向到 D:\eclipseWorkspace 如果再勾選 Use this as the default and do not ask again 的話 之後開啟 eclipse 就不會再問我 們這個問題了 按 OK 繼續 20. 這是 eclipse 開啟後的畫面 12

第五項 在 eclipse 安裝 ADT plugin 21. 執行 Help / Install New Software 22. 按下右方的 Add 13

23. 分別在 Name 輸入 ADT Plugin 在 Location 輸入 https://dlssl.google.com/android/eclipse/ 24. 勾選這二個選項 按 Next 繼續 14

25. 按 Next 繼續 15

26. 這裡選擇 I accept the terms of the license agreements 按 Finish 開始安裝動作 27. 按 OK 完成安裝動作 28. 可以開始我們的 android 程式開發工作囉 16

第二節 建立 AVD 模擬環境 29. android 程式設計的初期 還不需要實際的裝置 我們可以使用模擬環境來測試 執行 Window / AVD Manager 30. 在這個對話框的標題 就知道 AVD 表示 Android Virtual Device 按右方的 New... 17

31. 對話框裡請輸入以下內容 Name 欄位請輸入 AVD2.1 這裡可以自行修正 主要能知道它的版本即可 Target 欄位請選擇 Android 2.1 API Level 7 由於我們前面只安裝 4.0.3 與 2.1 版本的 API 因此這裡應該也只會有這二種類型 如果要使用 4.0.3 版本所提供的 API 這裡就必須選擇相對應的項目 這裡還會看到有 google API 這在後面的例子 會用到 有需要時再建立新的 AVD 即可 SD Card 欄位我設定 256 MB 即可 Skin 欄位請選擇 Built-in 的 HVGA 這個解析度暫時就夠了 其它幾個的解 析度比較高 暫時還不需要 各欄位都設定好之後 按 Create AVD 建立 18

32. 只要能在這裡看到我們剛才所建立的 AVD2.1 基本上就表示己經建立完成 我們可以來 測試看看 請點選我們剛才建立的 AVD2.1 再按 Start... 33. 按 Launch 繼續 19

34. 啟動 AVD 需要一些時間 看到這個視窗 表示我們有一個模擬的 android 裝置可以使用 使用滑鼠按住 AVD 裡的桌面 左右拖曳就可以切換不同的視景 35. 操作上就和真的很類似 用滑鼠將底下的頁籤拉上來 就可以看到各個應用程式 20

36. 如果要將 AVD 轉成橫向 可以按 Ctrl + F11 切換 再按一次又可以切換為直向 21

第三節 eclipse 環境設定 在正式開發之前 我們先做幾個簡單的環境設定 37. 執行 Window / Preferences 38. 展開 General / Editors / Text Editors 勾選右方的 Show line numbers 可以使 程式碼編輯器顯示行號 22

39. 選擇 General / Workspace 在 Text file encoding 這裡 選擇 Other 的 UTF8 可以將 eclipse 裡的程式碼 預設為 utf-8 編碼 將來程式碼移植到不同的系統 可 以正常顯示而不會變成亂碼 23

40. 另外 如果將來撰寫程式碼 覺得文字太小 可以在 General / Appearance / Colors and Fonts 這裡設定字型和字型大小 24

第四節 建立第一個 android 專案 41. 在 eclipse 裡的程式 大多以專案的型式處理 因此 我們要先建立一個專案 才能在專 案裡再建立程式 請先點選 File / New / Project 42. 選擇 Android / Android Project 按 Next 25

43. 在上方的 Project Name 欄位輸入 android001 這是專案名稱 你可以自己設定 專 案名稱的制定有一些共通的規定 建議使用英文 由於我們在練習過程 因此我可能會 再加個流水號 按 Next 繼續 26

44. 選擇 Android 2.1 再按 Next 繼續 這裡必須配合 AVD 的環境 因此暫時先使用 Android 2.1 做為開發環境 這個動作 請依你自己的需求選擇 一般來說 選擇 Android 2.1 的話 將近 98% 以上的 android 裝置是可以執行我們的程式的 如果選擇比較新的版本 提供的功 能可能比較多 介面比較華麗 但也比較佔用系統資源 如果你的電腦效率不算很 好的話 建議選擇 Android 2.1 的版本即可 27

45. 這裡的各個欄位 請分別填入資料如下 Application Name 欄位應該會預設顯示 Android001 這是我們剛才輸入的專案 名稱 Package Name 欄 位 可 以 自 行 輸 入 這 裡 的 例 子 是 輸 入 為 tw.idv.kingbig.android.test001 這是依建議將網域名稱倒過來輸入 這種方式 很像網域名稱的管理方式 主要的目的是希望全世界 android 開發人員所建立的套 件是唯一的 不會和其他人建立的套件重覆 如果沒有的話 就自行虛擬一個也可 以 勾 選 的 Create Activity 欄 位 就 用 預 設 值 即 可 這 裡 是 用 [Application Name] + Activity 的方式產生的 如果要自行修改也可以 Min SDK Versin 欄位也使用預設值即可 這裡選擇的 7 表示最基本的執行需 求是 Android 2.1 的版本 各欄位設定完成 按 Finish 即可 28

46. 新增專案之後 在左方會顯示剛才所新增的專案資料夾 雙按可以將它展開 47. 在專案資料夾底下的 src 資料夾 會有一個 Package Name 欄位所輸入的資料夾 再展 開後 就會看到主程式 在 android 裡的程式 我們稱為 Activity 它還是和 java 一樣 是一個純文字檔案 按 Ctrl + F11 可以執行程式 讓我們試試看 執行第一個專案 29

48. 每一個專案 第一次執行時 都會顯示以下視窗 以 android 專案來說 選最上方的 Android Application 再按 OK 鈕繼續 49. 啟動 AVD 需要一些時間 顯示以下視窗的話 將有鎖的圖案拖曳到右方 就可以看到 android 桌面 30

50. 顯示第一個專案的執行結果 它在跟我們 say hello 31

51. 在 eclipse 的左方 是一個 Package Explorer 以下的視窗內容 我將幾個比較重要 常 用的資料夾展開 分別說明如下 A. src 資料夾 在這個資料夾底下還會有一個 Package Name 的 資 料 夾 在 Package Name 資料夾之下 就是原始程式 也就是 android 的 Activity 目前只有一個 Activity 隨著我們所撰寫的程式功能增加 Activity 的 數量也會越來越多 B. bin 資 料夾 當 我們 按 Ctrl + F11 執 行程 式 eclipse 會將程式編譯為可以在 android 執行 的 apk 檔案 也就是說 只要我們將這個 apk 檔案存放到 android 狀置 就可以執行囉 C. res 資料夾 這是資源存放的資料夾 可以當 作專案裡所有 Activity 可以調用資源的資源池 這裡又可以細分為幾個 以下分別獨立說明 D. res / values 資料夾 就是一個定義 宣告字 串變數的檔案 我們可以將程式裡會使用到 的字串 全部放在這裡宣告 這種做法有個 好處 像是多國語系 或是我們要修改語句 表達的內容 只要來這裡修改就可以 將來 程式的維護更新的工作會方便很多 E. res / layout 資料夾 這是專問負責版面排版 控制的功能 每個 Activity 都有需要在 android 裝置上顯示文字框 訊息框 按鈕...等 都需要控制這些元件擺放的位置 就需要在這裡透過一個 xml 檔案負責各個元件位置的管理 F. res / drawable 資料夾 這裡是存放圖像檔案的 實際上會看到這裡細分為三個資料 夾 分別表示高解析度 中等解析度 低解析度的圖像檔案資源池 如果有圖檔 影像需要跟著程式一起打包的 就放在這裡 G. AndroidManifest.xml 檔案 這不是資料夾 是一個 xml 檔案 這個檔案很重要 前 面說明過 src 資料夾裡是存放 Activity 檔案 但是在這裡專案裡 有那些 Activity 是 可 以 執 行 的 必 須 在 AndroidManifest.xml 檔 案 裡 宣 告 過 的 才 算 數 沒 有 在 AndroidManifest.xml 裡宣告的 Activity 是無法執行的 另外 我們使用 Android 程式 可能都會先說明會需要使用到裝置的網路 GPS 記憶卡...等 也都必須在這裡先 宣告過 Android 裝置才會允許 Activity 存取裝置上的功能 以上的說明很重要 可以讓我們對整個 android 專案結構有個概念上的認識 如果 可以 請再重頭閱讀一篇 相信後續開發 android 程式時 會變的簡單許多 32

52. 前項簡單的說明了在 eclipse 環境 所看到各個資料夾的作用 應該還記得 我們將 eclipse 的工作目錄設定在 D:\eclipseWorkspace 資料夾 在這裡 我們和檔案總管 裡的 D:\eclipseWorkspace 實際資料夾的結構互相對照 會發現大部份的架構是相同 的 只有 Package Name 在檔案總管理 會建立為多層的資料夾結構 這也是為了將來 開發多個專案後 能夠有條理 而且方便管理的方式 瞭解 eclipse 與 Windows 檔案總 管的資料夾對照的關係 要存放資源檔案 也可以從這裡著手囉 33

第五節 擷取 android 裝置的畫面 不論是實際的 android 裝置 或是 AVD 的虛擬裝置 如果我們需要擷取影像 都可以依照以 下的方式處理 53. 連 結 android 裝 置 或 是 啟 動 AVD 可 以 執 行 Window / Open Perspective / DDMS 切換 eclipse 的操作視景 如 果 在 Window / Open Perspective 沒 有 直 接 看 到 DDMS 視 景 的 話 請 按 Window / Open Perspective / Other 再由對話框選擇 DDMS 視景即可 34

54. 在左方的 Devices 頁籤 會看到一個照相機的 icon 點按一下 55. 系統會顯示 Device Screen Capture 對話框 按 Refresh 鈕可以將 android 裝置上的畫面 重新擷取更新過來 按 Save 就可以將擷取的畫面存檔 35

56. 我在 AVD 上按退出鈕 退出了應用程式回到 android 的桌面 我又按了 Refresh 鈕 重 新擷取 AVD 桌面的圖案 如果擷取畫面的動作完成 可以按 Done 關閉對話框 57. 要 從 DDMS 的 視 景 回 到 android 開 發 環 境 的 視 景 也 就 是 java 的 視 景 請 執 行 Window / Open Perspective / Java 58. 也可以直接按最右上方的 DDMS 與 Java 直接切換不同的視景 36

第二章 猜數字比大小 這個程式是個簡單的遊戲 目要是由電腦亂數產生一個 1~99 之間的數字 由我們來猜猜這 個數字是多少 我們猜數字時 電腦會回應我們 要再大一些 或者是再小一些 藉此提示 我們猜到最後的那個數字 第一項 建立專案 請依前面介紹的動作 建立一個新的 Android 專案 專案名稱就隨便設定為 a01 第二項 建立介面佈面檔 我們使用最基本的介面就可以 建立以下幾個元件 1. 一個輸入文字框(EditText) 提供使用者可以輸入數字 2. 一個按鈕(Button) 在前一個 EditText 欄位輸入數字之後 按下按鈕 由系統判斷數 是否正確 或者是顯示提示文字 3. 三個文字顯示框(TextView) 輔助使用者測猜數字使用 一個要顯示使用者猜測數字 區間的最小值 另一個是顯示最大值 另一個顯示是否猜中數字 參考如下 <?xml version="1.0" encoding="utf 8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center_horizontal" android:orientation="vertical" > <EditText android:id="@+id/et01" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputtype="number" android:text="50" android:textsize="20sp" /> <Button android:id="@+id/bt01" 37

android:layout_width="match_parent" android:layout_height="wrap_content" android:text="比大小" /> <TextView android:id="@+id/tv01" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="最小值" android:textsize="20sp" /> <TextView android:id="@+id/tv02" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="最大值" android:textsize="20sp" /> <TextView android:id="@+id/tv03" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="繼續加油" android:textsize="20sp" /> </LinearLayout> 第三項 主程式 參考如下 package tw.a01; import android.app.activity; import android.os.bundle; import android.view.view; import android.widget.button; import android.widget.edittext; 38

import android.widget.textview; public class A01GuessNumber extends Activity { EditText et01; Button bt01; TextView tv01; TextView tv02; TextView tv03; Integer pcnum; Integer a02=0; //計算猜了幾次 public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.mainguessnumber); setupviewcomponent(); private void setupviewcomponent() { et01 = (EditText) findviewbyid(r.id.et01); bt01 = (Button) findviewbyid(r.id.bt01); tv01 = (TextView) findviewbyid(r.id.tv01); tv02 = (TextView) findviewbyid(r.id.tv02); tv03 = (TextView) findviewbyid(r.id.tv03); // pcnum=(int) (Math.random()*99+1); tv03.settext(tv03.gettext() + pcnum.tostring()); tv01.settext("0"); tv02.settext("100"); bt01.setonclicklistener(bt01click); Button.OnClickListener bt01click = new Button.OnClickListener() { public void onclick(view v) { 39

int a01; String s01=""; a02=a02+1; a01=integer.parseint(et01.gettext().tostring()); if (a01>pcnum) { s01="再小一些"; tv02.settext(et01.gettext().tostring()); else if (a01<pcnum) { s01="再大一些"; tv01.settext(et01.gettext().tostring()); else if (a01==pcnum) { s01="恭禧你猜到了~~ 總共猜了 " + a02 + " 次! 再重玩一 次!!"; a02=0; setupviewcomponent(); tv03.settext(s01); ; 40

使用 WebV iew 建立程式 第三章 請先安裝好 Android 的開發環境 建立一個專案 接下來看看我們使用簡單的 WebView 就 能建立一個很實用的程式哦 第一項 修改 AndroidManifest.xml 檔案 <?xml version="1.0" encoding="utf 8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="tw.idv.kingbig.browserintent" android:versioncode="1" android:versionname="1.0" > <uses sdk android:minsdkversion="7" /> <uses permission android:name="android.permission.internet" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:label="@string/app_name" android:name=".browserintentactivity" > <intent filter > <action android:name="android.intent.action.main" /> <category android:name="android.intent.category.launcher" /> </intent filter> </activity> <activity android:name=".golink01" android:label="@string/app_name_link01"> </activity> <activity 41

android:name=".golink02" android:label="@string/app_name_link02"> </activity> </application> </manifest> 第二項 修改 main.xml <?xml version="1.0" encoding="utf 8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <Button android:id="@+id/golink01_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="文字 1" /> <Button android:id="@+id/golink02_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="文字 2" /> </LinearLayout> </LinearLayout> 42

第三項 建立 mainwebview.xml <?xml version="1.0" encoding="utf 8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal" > <WebView android:id="@+id/web_view" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1.0" /> </LinearLayout> 第四項 建立 Activity 主程式 package tw.idv.kingbig.browserintent; import android.app.activity; import android.content.intent; import android.os.bundle; import android.view.view; import android.widget.button; public class BrowserIntentActivity extends Activity android.view.view.onclicklistener { /** Called when the activity is first created. */ private Button golink01button; private Button golink02button; implements public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.main); findviews(); 43

private void findviews() { golink01button = (Button)findViewById(R.id.golink01_button); golink01button.setonclicklistener(this); golink02button = (Button)findViewById(R.id.golink02_button); golink02button.setonclicklistener(this); ; public void onclick(view v) { switch (v.getid()) { case R.id.golink01_button: Intent igolink01 = new Intent(this, golink01.class); startactivity(igolink01); break; case R.id.golink02_button: Intent igolink02 = new Intent(this, golink02.class); startactivity(igolink02); break; 44

建立 golink01 程式 第五項 package tw.idv.kingbig.browserintent; import android.app.activity; import android.os.bundle; import android.view.view; import android.webkit.webview; public class golink01 extends Activity android.view.view.onclicklistener { /** Called when the activity is first created. */ private WebView webview; implements public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.mainwebview); findviews(); private void findviews() { webview=(webview) findviewbyid(r.id.web_view); openbrowser(); ; private void openbrowser() { String s01=new String("http://www.kingbig.idv.tw/indexAndroid.php? Act=2300&MP=24"); webview.getsettings().setjavascriptenabled(true); webview.loadurl(s01); public void onclick(view v) { 45

建立 golink02 第六項 package tw.idv.kingbig.browserintent; import android.app.activity; import android.os.bundle; import android.view.view; import android.webkit.webview; public class golink02 extends Activity android.view.view.onclicklistener { /** Called when the activity is first created. */ private WebView webview; implements public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.mainwebview); findviews(); private void findviews() { webview=(webview) findviewbyid(r.id.web_view); openbrowser(); ; private void openbrowser() { String s01=new String("http://www.kingbig.idv.tw/indexAndroid.php? Act=3100&MP=40"); webview.getsettings().setjavascriptenabled(true); webview.loadurl(s01); public void onclick(view v) { 46

第四章 音樂播放程式 第一節 最陽春的音樂播放程式 第一項 建立空白的新專案 1. 請執行 File / New / Project 選擇 Android / Android Application Project 建 立一個空白的專案 2. 開 啟 layout 的 介 面 佈 局 檔 案 建 立 一 個 按 鈕 將 它 命 名 為 bt01 android:id="@+id/bt01" 將它的顯示文字改為 播放音樂 android:text="播 放音樂" 3. 在 res 右鍵 / New / Folder 建立一個 raw 資料夾 4. 請將一個 mp3 檔案複製到 /res/raw/ 底下 請注意檔案名稱必須符合 res 的命名限 制 第二項 加入 MediaPlayer 物件 1. 開啟主程式 也許是 MainActivity.java 一開始 它的內容可能如下 package com.example.t01music; import android.os.bundle;...略 public class MainActivity extends Activity { public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); 2. 加入 MediaPlayer 物件的宣告 請依程式的建議進行相關的 import 動作 如下 47

package com.example.t01music; import android.media.mediaplayer;...略 public class MainActivity extends Activity { MediaPlayer mp01 = null; public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); 3. 宣告 mp3 的音樂物件 如下 package com.example.t01music; import android.media.mediaplayer;...略 public class MainActivity extends Activity { MediaPlayer mp01 = null; int music01 = R.raw.fir02; public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); 4. 在 oncreate()輸入 findview(); 的敘述 並依建議動作處理 產生一個 findview() 的方法...略 48

public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); findview(); private void findview() { 5. 連結 mp3 檔案 進行播放動作 參考程式如下...略 private void findview() { mp01 = new MediaPlayer(); mp01 = MediaPlayer.create(this, music01); mp01.start(); 6. 執行程式吧 聽聽看 是否有音樂播放出來 第二節 改善這個程式 第一項 瞭解 Activity 的生命週期 以下的流程圖 以及表格 有助我們瞭解 Activity 的生命週期 49

Figure. The activity lifecycle. 資料來源 http://developer.android.com/guide/components/activities.html 50

Table. A summary of the activity lifecycle's callback methods. Method Killable after? Description oncreate() Called when the activity is first created. This is where you should do all of your normal static set up create views, bind data to lists, and so on. This method is passed a Bundle object containing the activity's No previous state, if that state was captured (see Saving Activity State, later). Next onstart() Always followed by onstart(). onrestart() Called after the activity has been stopped, just prior to it being started again. No onstart() Always followed by onstart() Called just before the activity becomes visible to the user. onstart() Followed by onresume() if the activity comes to the No foreground, or onstop() if it becomes hidden. onresume() Called just before the activity starts interacting with the user. At this point the activity is at the top of the activity No stack, with user input going to it. onresume() or onstop() onpause() Always followed by onpause(). onpause() Called when the system is about to start resuming another activity. This method is typically used to commit unsaved changes to persistent data, stop animations and other things that may be consuming CPU, and so on. It should do whatever it does very quickly, because Yes the next activity will not be resumed until it returns. Followed either by onresume() if the activity returns onresume() or onstop() back to the front, or by onstop() if it becomes invisible to the user. onstop() Called when the activity is no longer visible to the user. This may happen because it is being destroyed, or because another activity (either an existing one or a new one) has been resumed and is covering it. Yes Followed either by onrestart() if the activity is coming back to interact with the user, or by ondestroy() if this activity is going away. ondestroy() Called before the activity is destroyed. This is the final call that the activity will receive. It could be called either because the activity is finishing (someone called finish() on it), or because the system is temporarily Yes destroying this instance of the activity to save space. You can distinguish between these two scenarios with the isfinishing() method. onrestart() or ondestroy() nothing 資料來源 http://developer.android.com/guide/components/activities.html 51

第二項 離開程式時也能停止音樂的播放 剛剛我們所寫的程式 如果還在播放的狀態 我們就離開程式 執行 android 的其它程式 有沒有注意到 音樂還在播放 我們要改善這個狀況 請依以下動作執行 1. 在程式碼的空白處按 右鍵 / Source / Override/Implement Methods 2. 在這裡找一找 勾選 onpause() 按 OK 就會發現在程式碼裡頭 多出以下 的程式區塊 protected void onpause() { super.onpause(); 3. 請加入以下二行程式 protected void onpause() { super.onpause(); mp01.stop(); mp01.release(); 4. 再重新執行程式 在音樂尚未播放完畢前 離開程式 如果音樂也就停止播放 表示 這個動作完成了 第三項 按下播放按鈕才開始播放 目前的程式 會在執行時就直接播放音樂 我們要修改一下 在按下 播放音樂 時 才開 始播放 請依以下動作操作 1. 先宣告 Button 類別的 bt01 物件 再由 R 取出相對應的資源 指定給 bt01 物件 再宣 告 bt01 的傾聽程式 參考如下...略 public class MainActivity extends Activity { MediaPlayer mp01 = null; 52

int music01 = R.raw.fir02; Button bt01; public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); findview(); @SuppressLint("ParserError") private void findview() { bt01 = (Button) findviewbyid(r.id.bt01); bt01.setonclicklistener(bt01click); mp01 = MediaPlayer.create(this, music01); mp01.start(); protected void onpause() { super.onpause(); mp01.stop(); mp01.release(); 2. 在我們使用 setonclicklistener()宣告傾聽程式後 會顯示錯誤訊息 我們必須手動 輸入程式 建立 bt01click 請特別注意的是 請將 bt01click 當做是一個物件 它是 經由 Button.OnClickListener 的宣告 所產生的一個物件 因此 最後的大括弧結束 時 必須再加一個 ; 結束 程式碼參考如下...略 public class MainActivity extends Activity { MediaPlayer mp01 = null; int music01 = R.raw.fir02; 53

Button bt01;...略 private void findview() { bt01 = (Button) findviewbyid(r.id.bt01); bt01.setonclicklistener(bt01click); mp01 = MediaPlayer.create(this, music01); mp01.start(); Button.OnClickListener bt01click = new Button.OnClickListener() { ;...略 3. 系統會提示我們 bt01click 的物件還需要 Add unimplemented methods 請依 程式的建議處理 會在 bt01click 物件裡 再宣告 onclick()的事件 這個區塊的程式 碼如下 Button.OnClickListener bt01click = new Button.OnClickListener() { public void onclick(view v) { // TODO Auto-generated method stub ; 4. 將 mp01 指定物件與 mp01 播放的二行程式 移到 bt01click 的 onclick()方法裡 同 時 再稍微修改一下程式 主要是將 MediaPlayer.create(this, music01) 改 為 MediaPlayer.create(getApplicationContext(), music01) 將 this 改 為 getapplicationcontext() 的原因 是原本的 MediaPlayer.create()方法 是在主要 的 Activity 裡執行 因此只要使用 this 關鍵字就可以取得 這個 Activity 的物件 當我們將 MediaPlayer.create()方法移到 bt01click 的物件時 this 所參考的物件 可能會不正確 因此 我們必須將它改為 getapplicationcontext() 方法 透過呼 54

叫這個方法來取得我們 主要的 Activity 是那一個物件 這樣一來 mp01 還是可 以正確的取得播放的音樂資源 進行後續播放的動作 程式碼參考如下...略 public class MainActivity extends Activity {...略 private void findview() { bt01 = (Button) findviewbyid(r.id.bt01); bt01.setonclicklistener(bt01click);...略 Button.OnClickListener bt01click = new Button.OnClickListener() { public void onclick(view v) { mp01 = MediaPlayer.create( getapplicationcontext(), music01); mp01.start(); ; 5. 執行程式試試看 程式執行後 必須等我們按 播放音樂 的按鈕後 才會有音樂囉 練習題 1 目前有 播放音樂 的按鈕 請自行建立 停止播放 的按鈕 而且 在 按下 停止播放 按鈕時 要能停止音樂的播放動作 練習題 2 試試看 建立一個 暫停 播放 的按鈕 按一下可以暫停音樂的播放 再按一下 可以繼續音樂的播放 55

SQLite 資料庫 第五章 在介紹 SQLite 之前 我們先來認識 SharedPreferences 存取偏好設定 第一節 使用 SharedPreferences 請建立新的專案 分別再依以下動作進行 第一項 介面佈局檔 1. 建立 TextView 顯示文字為 姓名 2. 建立 EditText 設定 id 為 et01 3. 建立 TextView 顯示文字為 興趣 4. 建立 EditText 設定 id 為 et02 5. 建立 Button 設定 id 為 bt01 顯示文字為 儲存偏好設定 6. 執行程式 看看是否可以正常顯示介面佈局檔的內容 第二項 建立主程式的內容 儲存偏好設定 1. 請開啟主程式 進行 et01 et02 bt01 等物件的宣告 物件的實體建立 並且將 bt01 設定傾聽程式 參考程式碼如下 public class MainActivity extends Activity { EditText et01; EditText et02; Button bt01; public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); findview(); private void findview() { 56

et01 = (EditText) findviewbyid(r.id.et01); et02 = (EditText) findviewbyid(r.id.et02); bt01 = (Button) findviewbyid(r.id.bt01); bt01.setonclicklistener(bt01click); Button.OnClickListener bt01click = new Button.OnClickListener() { public void onclick(view v) { ; 2. 在 bt01click 方法裡輸入相關程式 參考範例程式如下 Button.OnClickListener bt01click = new Button.OnClickListener() { public void onclick(view v) { //將資料儲存到 SharedPreferences 的 sp01 物件. SharedPreferences sp01 = getsharedpreferences("t04shareprefs", 0); sp01.edit().putstring("et01text", et01.gettext().tostring()).putstring("et02text", et02.gettext().tostring()).commit(); //顯示一個 Toast, 一秒鐘. Toast.makeText(getApplicationContext(), "資料儲存完成", 57

Toast.LENGTH_SHORT).show(); ; 3. 執 行 程 式 在 二 個 欄 位 裡 輸 入 資 料 再 按 一 下 bt01 使 系 統 觸 發 事 件 執 行 bt01click 的動作 第三項 驗證儲存偏好的動作 前項動作執行後 我們可以驗證看看 驗證動作如下 1. 開啟命令提示字元 2. 執行 adb shell 如果沒有執行 顯示找不到命令的話 表示系統的 path 路徑沒 有 指 定 到 adb 的 位 置 adb 的 程 式 是 放 在 android-sdk 目 錄 下 的 platformtools 的目錄裡 可以手動切換路徑 也可以考慮將它的路徑加入到 path 環境變數 裡 3. 進入到 adb shell 後 可以執行 ls -l 顯示目錄裡的內容 使用 cd 執行切換工作 目錄 以我的例子來看 我需要先執行 cd /data/data 在這裡就會看到系統所安 裝的所有資料夾 一個程式會有一個資料夾 資料夾的名稱就是 package name 4. 我的 package name 是 com.example.t04sharepreference 因此 我就需要再輸 入 cd com.example.t04sharepreference 再使用 ls -l 顯示目錄裡的內容 會 看到有一個 shared_prefs 目錄 裡頭有一個 t04shareprefs.xml 的檔案 這個 檔案就是我們所儲存的偏好設定 它是一個標準 xml 格式的檔案 5. 我們可以執行 cat t04shareprefs.xml 看看裡頭的內容 其實就是我們在 android 的程式裡所輸入的內容 第四項 建立主程式的內容 提取偏好設定 我們會希望程式每次執行時 都能先將前次所儲存的偏好設定 主動的讀取出來 程式撰寫 的動作如下 1. 我們在 findview 方法裡 呼叫一個 loadsharedprefs 的方法 參考程式碼如下 private void findview() { et01 = (EditText) findviewbyid(r.id.et01); et02 = (EditText) findviewbyid(r.id.et02); 58

bt01 = (Button) findviewbyid(r.id.bt01); bt01.setonclicklistener(bt01click); loadsharedprefs(); private void loadsharedprefs() { 2. 在 loadsharedprefs 方法裡 使用 private void loadsharedprefs() { /** * 第 1 個參數設定我們的偏好設定的檔案名稱是 t04shareprefs, * 第 2 個參數表示只允許程式本身開啟, 不允許其它程式使用. */ SharedPreferences sp01 = getsharedpreferences("t04shareprefs", 0); /** * 取得之前儲存的資料, 如果沒有的話, 預設傳回 "請輸入資料" 的字串 * 這裡為了簡單及方便理解 因此另外宣告二個字串變數儲存資料 */ String s01 = sp01.getstring("et01text", "請輸入資料"); String s02 = sp01.getstring("et02text", "請輸入資料"); et01.settext(s01.tostring()); et02.settext(s02.tostring()); 3. 請先離開程式 再重新執行程式 應該會發現前次輸入的資料會自動填入到 et01 與 et02 的欄位裡 練習題 目前的偏好設定儲存 必須按下 儲存偏好設定 的按鈕 才會有作用 請 將程式修改 當使用者直接離開程式時 也能由程式將資料儲存後再離開程式 59

第二節 簡單使用 SQLite 我們要使用 SQLite 的話 需要使用 SQLiteOpenHelper 以及 SQLiteDatabase 這二個類別來 建立 以及存取資料庫 其中的 SQLiteOpenHelper 是一個幫助類別 Helper Class 我 們需要建立一個繼承自 SQLiteOpenHelper 的類別 SQLiteOpenHelper 主要的目的是協助 我們建立資料表 以及資料庫的版本管理 由 SQLiteOpenHelper 所建立出來的資料庫 是 一個 SQLiteDatabase 類別的物件 因此 我們可以透過 SQLiteDatabase 所提供的方法該 行新增 刪除 更新資料表的內容 以下請建立新專案 再依照底下的動作進行 第一項 介面佈局檔 1. 建立一個 TextView 顯示文字為 只存記事本 2. 建立一個 EditText 設定 id 為 et01 顯示文字為空的 3. 建立一個 Button 設定 id 為 bt01 顯示文字為 儲存記事 4. 建立一個 TextView 設定 id 為 tv01 第二項 建立 SQLiteOpenHelper 的子類別 1. 在 src / 套件名稱 按 右鍵 / New / Class 2. 在 Name 的欄位輸入 mydbhelper 做為類別的名稱 3. 按 Superclass 右方的 Browse... 4. 在上方的 Choose a type 欄位輸入 SQLiteOpenHelper 底下的 Matching items 會顯示符合的項目 點選該項目 按 OK 5. 按 Finish 建立類別 同時 依系統的建議 修正錯誤的訊息 6. 目前為止 程式碼類似以下內容 public class mydbhelper extends SQLiteOpenHelper { public dbhelper(context context, String name, CursorFactory factory, int version) { super(context, name, factory, version); // TODO Auto generated constructor stub public void oncreate(sqlitedatabase arg0) { 60

public void onupgrade(sqlitedatabase arg0, int arg1, int arg2) { 7. 修改 oncreate()的方法 也就是覆寫父類別的方法 我們要建立自己要使用的資料 表 程式碼參考如下 其中的 arg0 是系統在 oncreate 方法裡自行宣告的一個 SQLiteDatabase 物件 我是直接使用這個名稱 也可以修改物件的名稱 例如改為 db 使物件名稱比較具有意義 public void oncreate(sqlitedatabase arg0) { arg0.execsql( "Create Table t05note (" + "_id integer primary key autoincrement, " + "tnote text)" ); 8. 修改 onupgrade 方法 內容參考如下 public void onupgrade(sqlitedatabase arg0, int arg1, int arg2) { arg0.execsql("drop Table if exists t05note"); oncreate(arg0); 9. 這個檔案完成了 第三項 修改主程式 1. 宣告各個物件 以及建立 findview 方法 參考如下 61

public class MainActivity extends Activity { SQLiteDatabase db01; mydbhelper dbhelper01; String databasetable = "t05note"; EditText et01; TextView tv01; Button bt01; public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); findview(); private void findview() { 2. 建立 findview 方法裡的各個物件的實體 參考程式碼如下 private void findview() { et01 = (EditText) findviewbyid(r.id.et01); tv01 = (TextView) findviewbyid(r.id.tv01); bt01 = (Button) findviewbyid(r.id.bt01); dbhelper01 = new mydbhelper(this, databasetable, null, 1); db01 = dbhelper01.getwritabledatabase(); 3. 執行程式看看 應該能正常執行 而且 我們可以開啟命令提示字元視窗 驗證看看 資料庫是否己經建立完成 指令參考如下 A. 執行 adb shell 進入 android 的模擬器的系統 62

B. 再執行 cd /data/data/ C. 輸入 ls -l 查看應該有一個和 package name 相同的目錄 以我的為例 我會看 到 com.example.t05sqlite 的目錄 D. 執 行 cd com.example.t05sqlite 再 輸 入 ls -l 查 看 應 該 會 產 生 一 個 databases 的資料夾 而且 裡頭會有個 t05note 的檔案 E. 看到有 databases 的資料夾 而且裡頭有個 t05note 的檔案 就表示有呼 叫 SQLite 建立資料庫 也建立好了資料表 4. 在 程 式 碼 的 空 白 處 按 右 鍵 / Source / Override/Implement Methods 勾 選 onstop() 按 OK 5. 在 onstop 的方法裡 我們要關閉資料庫 釋放資源 參考程式碼如下 protected void onstop() { super.onstop(); db01.close(); 6. 建立 bt01click 事件 參考如下 private void findview() { et01 = (EditText) findviewbyid(r.id.et01); tv01 = (TextView) findviewbyid(r.id.tv01); bt01 = (Button) findviewbyid(r.id.bt01); dbhelper01 = new mydbhelper(this, databasetable, null, 1); db01 = dbhelper01.getwritabledatabase(); bt01.setonclicklistener(bt01click); Button.OnClickListener bt01click = new Button.OnClickListener() { public void onclick(view v) { 63

; 7. 建立 bt01click 裡的 onclick 事件 參考如下 Button.OnClickListener bt01click = new Button.OnClickListener() { public void onclick(view v) { long id; ContentValues cv01 = new ContentValues(); cv01.put("tnote", et01.gettext().tostring()); id = db01.insert(databasetable, null, cv01); Toast.makeText(getApplicationContext(), "記錄新增完成 " + id, Toast.LENGTH_SHORT).show(); ; 8. 執行程式 輸入一些文字 再按 儲存記事 應該會顯示 記錄新增完成 x 的 toast 第四項 驗證看看 sqlite3 指令 前項動作 我們使用命令提示字元模式 查看 databases 目錄與 t05note 檔案 從這個狀態 可以再做更細的驗證動作 請依以下動作操作 1. 輸入 sqlite3 t05note 會進入 sqlite 的命令提示的環境 2. 畫面顯示 可以輸入.help 取得一些協助 試試看 3. 輸入.databases 可以查看我們目前取用的資料庫 4. 輸入.tables 可以得知我們目前有那些資料表 5. 一般的 sql 指令 例如新增 刪除 在這裡是可以通用的 例如輸入 select * from t05note; 就可以顯示所有記錄 6. 輸入.quit 可以離開 sqlite3 的命令提示環境 64

第五項 顯示資料表內容 1. 在 findview 方法裡 呼叫 showtables 方法 參考如下 private void findview() { et01 = (EditText) findviewbyid(r.id.et01); tv01 = (TextView) findviewbyid(r.id.tv01); bt01 = (Button) findviewbyid(r.id.bt01); dbhelper01 = new mydbhelper(this, databasetable, null, 1); db01 = dbhelper01.getwritabledatabase(); bt01.setonclicklistener(bt01click); showtables(); private void showtables() { 2. 建立 showtables 方法裡的程式碼 參考如下 private void showtables() { String[] colnames = new String[] {"_id", "tnote"; String s01 = ""; Cursor c01 = db01.query(databasetable, colnames, null, null, null, null, null); for (int i=0; i<colnames.length; i++) { s01 = s01 + colnames[i] + "\t"; s01 = s01 + "\n"; c01.movetofirst(); // for (int i=0; i<c01.getcount(); i++) { s01 = 65 s01 +

c01.getstring( c01.getcolumnindex( colnames[0] ) ) + "\t"; s01 = s01 + c01.getstring(0) + "\t"; s01 = s01 + c01.getstring(1) + "\n"; c01.movetonext(); tv01.settext(s01.tostring()); 3. 執行程式看看 應該可以列出所有的記錄 66

第六章 GPS 服務 這個程式範例 在 Android 2.1 的環境就可以正常執行 第一節 設定 manifest 的使用授權項目 1. 請開啟 AndroidManifest.xml 檔案 請加入以下四行 users-permission 這四行 uses-permission 分別代表允許取得 GPS 的精細座標位置 允許使用者所輸 入的模擬位置 允許使用 3g 或 wifi 的方式取得的概略位置 允許存取網際網路 前三項的 uses-permission 是抓取座標位置要用的 而第四項則是要由網路傳回 Google Maps 時 會需要使用網路連線 傳回資料 <uses sdk android:minsdkversion="7" android:targetsdkversion="7" /> <uses permission android:name="android.permission.access_fine_location" /> <uses permission android:name="android.permission.access_mock_location" /> <uses permission android:name="android.permission.access_coarse_location" /> <uses-permission android:name="android.permission.internet" /> 這個檔案還有其他的設定要做 等稍後我們再回來這裡設定 目前暫時先設定這四 項使用授權即可 記得存檔 67

第二節 建立介面佈局檔 1. 請先開啟介面佈局檔 拖拉元件如下圖 2. 直接瀏覽 xml 檔案的話 參考內容如下 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:id="@+id/txtlabel01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparentleft="true" android:layout_alignparenttop="true" android:text = " 緯度 " tools:context=".mainactivity" /> 68

<TextView android:id="@+id/txttext01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparenttop="true" android:layout_torightof="@+id/txtlabel01" android:text = "TextView" /> <TextView android:id="@+id/txtlabel02" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparentleft="true" android:layout_below="@+id/txtlabel01" android:text = " 經度 " /> <TextView android:id="@+id/txttext02" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignbaseline="@+id/txtlabel02" android:layout_alignbottom="@+id/txtlabel02" android:layout_torightof="@+id/txtlabel02" android:text = "TextView" /> <TextView android:id="@+id/txtlabel03" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparentleft="true" android:layout_below="@+id/txtlabel02" android:text = " 精確度 " /> <TextView android:id="@+id/txttext03" 69

android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignbaseline="@+id/txtlabel03" android:layout_alignbottom="@+id/txtlabel03" android:layout_torightof="@+id/txtlabel03" android:text = "TextView" /> <TextView android:id="@+id/txtlabel04" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparentleft="true" android:layout_below="@+id/txtlabel03" android:text = " 高度 " /> <TextView android:id="@+id/txttext04" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignbaseline="@+id/txtlabel04" android:layout_alignbottom="@+id/txtlabel04" android:layout_torightof="@+id/txtlabel04" android:text = "TextView" /> <TextView android:id="@+id/txtlabel05" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparentleft="true" android:layout_below="@+id/txtlabel04" android:text = " 時間 " /> <TextView android:id="@+id/txttext05" android:layout_width="wrap_content" android:layout_height="wrap_content" 70

android:layout_alignbaseline="@+id/txtlabel05" android:layout_alignbottom="@+id/txtlabel05" android:layout_torightof="@+id/txtlabel05" android:text = "TextView" /> <TextView android:id="@+id/txtlabel06" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparentleft="true" android:layout_below="@+id/txtlabel05" android:text = " 速度 " /> <TextView android:id="@+id/txttext06" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignbaseline="@+id/txtlabel06" android:layout_alignbottom="@+id/txtlabel06" android:layout_torightof="@+id/txtlabel06" android:text = "TextView" /> <TextView android:id="@+id/txtlabel07" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparentleft="true" android:layout_below="@+id/txtlabel06" android:text = " 方位 " /> <TextView android:id="@+id/txttext07" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignbaseline="@+id/txtlabel07" android:layout_alignbottom="@+id/txtlabel07" 71

android:layout_torightof="@+id/txtlabel07" android:text = "TextView" /> <Button android:id="@+id/btnhistorylist" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparentleft="true" android:layout_below="@+id/txtlabel07" android:text = " 歷史記錄 " /> <WebView android:id="@+id/webview1" android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_alignparentleft="true" android:layout_alignparentright="true" android:layout_below="@+id/btnhistorylist" /> </RelativeLayout> 72

第三節 建立連結資料庫的 dbhelper public class mydbhelper extends SQLiteOpenHelper { public mydbhelper(context context, String name, CursorFactory factory, int version) { super(context, name, factory, version); // TODO Auto generated constructor stub public void oncreate(sqlitedatabase arg0) { //這個是資料表的結構 //其中的 gtdate datetime 有問題 請暫時忽略 arg0.execsql( "create table gpstracer (" + "_id integer primary key autoincrement, " + "gtdate datetime, " + "gtlatitude long, " + "gtlongitude long, " + "gtaccuracy long, " + "gtaltitude long, " + "gttime long, " + "gtspeed long, " + "gtbearing long" + ")" ); public void onupgrade(sqlitedatabase arg0, int arg1, int arg2) { arg0.execsql("drop table if exists gpstracer"); oncreate(arg0); 73

第四節 建立主程式 public class MainActivity extends Activity { TextView txtlabel01; TextView txtlabel02; TextView txtlabel03; TextView txtlabel04; TextView txtlabel05; TextView txtlabel06; TextView txtlabel07; TextView txttext01; TextView txttext02; TextView txttext03; TextView txttext04; TextView txttext05; TextView txttext06; TextView txttext07; Button btnhistorylist; WebView wv01; //宣告資料庫相關的物件 mydbhelper dbhelper01; //使用繼承自 SQLiteOpenHelper 類別所產生的物件 協 助我們建立資料庫連結的動作 SQLiteDatabase gpstracerdb; //連結資料庫進行查詢 新增資料的動作 String databasetable = "gpstracer"; //宣告資料表的名稱 這行可以不用 LocationManager lm01; //宣告一個 LocationManager 類別的 lm01 物件 //宣告一個 LocationListener 類別的 lm01listener 物件 //在 new LocationListener() 產生物件時 會同時建立其中的幾個 method public LocationListener lm01listener = new LocationListener() { //gps 的狀態改變時 會呼叫這個 method public void onstatuschanged(string provider, int status, Bundle extras) { 74

switch (status) { case LocationProvider.AVAILABLE: Log.v("status", "AVAILABLE"); break; case LocationProvider.OUT_OF_SERVICE: Log.v("status", "OUT_OF_SERVICE"); break; case LocationProvider.TEMPORARILY_UNAVAILABLE: Log.v("status", "TEMPORARILY_UNAVAILABLE"); break; public void onproviderenabled(string provider) { public void onproviderdisabled(string provider) { //當座標改變時 會呼叫這個 method public void onlocationchanged(location location) { txttext01.settext(string.valueof(location.getlatitude())); txttext02.settext(string.valueof(location.getlongitude())); txttext03.settext(string.valueof(location.getaccuracy())); txttext04.settext(string.valueof(location.getaltitude())); txttext05.settext(string.valueof(location.gettime())); txttext06.settext(string.valueof(location.getspeed())); txttext07.settext(string.valueof(location.getbearing())); wv01.loadurl("http://maps.google.com/maps/api/staticmap? center=" + Double.toString(location.getLatitude()) +"," + Double.toString(location.getLongitude()) + "&zoom=16&size="+ 75

"360x400&sensor=false&markers=color:blue%7Clabel:S%7C"+ Double.toString(location.getLatitude()) + "," + Double.toString(location.getLongitude())); //以下動作是要將資料存到資料庫 long id; //使用 ContentValues 以陣列 key value 的方式儲存 //其中的 key 就是欄位名稱 value 就是儲存的值 要轉換為字串 ContentValues cv01 = new ContentValues(); cv01.put("gtdate", "current_timestamp"); cv01.put("gtlatitude", String.valueOf(location.getLatitude())); cv01.put("gtlongitude", String.valueOf(location.getLongitude())); cv01.put("gtaccuracy", String.valueOf(location.getAccuracy())); cv01.put("gtaltitude", String.valueOf(location.getAltitude())); cv01.put("gttime", String.valueOf(location.getTime())); cv01.put("gtspeed", String.valueOf(location.getSpeed())); cv01.put("gtbearing", String.valueOf(location.getBearing())); //進行 insert 到資料表的動作 id=gpstracerdb.insert(databasetable, null, cv01); Toast.makeText(getApplicationContext(), "記錄新增完成:" + id, Toast.LENGTH_SHORT).show(); ; public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); findview(); //自己建立的程式寫在這裡 76

private void findview() { txtlabel01=(textview) findviewbyid(r.id.txtlabel01); txtlabel02=(textview) findviewbyid(r.id.txtlabel02); txtlabel03=(textview) findviewbyid(r.id.txtlabel03); txtlabel04=(textview) findviewbyid(r.id.txtlabel04); txtlabel05=(textview) findviewbyid(r.id.txtlabel05); txtlabel06=(textview) findviewbyid(r.id.txtlabel06); txtlabel07=(textview) findviewbyid(r.id.txtlabel07); txttext01=(textview) findviewbyid(r.id.txttext01); txttext02=(textview) findviewbyid(r.id.txttext02); txttext03=(textview) findviewbyid(r.id.txttext03); txttext04=(textview) findviewbyid(r.id.txttext04); txttext05=(textview) findviewbyid(r.id.txttext05); txttext06=(textview) findviewbyid(r.id.txttext06); txttext07=(textview) findviewbyid(r.id.txttext07); btnhistorylist=(button) findviewbyid(r.id.btnhistorylist); wv01=(webview) findviewbyid(r.id.webview1); // 透 過 getsystemservice 去 呼 叫 LOCATION_SERVICE 建 立 一 個 LocationManager 的服務 //LOCATION_SERVICE 的 android.content.context.location_service 完 整 服 務 是 //由 LOCATION_SERVICE 服務就可以取得系統提供的座標 高度 方位等各項服務 lm01=(locationmanager) getsystemservice(location_service); //以下動作在設定 LocationListener lm01listener 物件 的最小變動時機 //每 2 秒(2000)更新一次 //每 5 公尺更新一次 // lm01.requestlocationupdates(locationmanager.network_provider, 77

2000, 5, lm01listener); lm01.requestlocationupdates(locationmanager.gps_provider, 2000, 5, lm01listener); //連結資料庫的動作 dbhelper01 = new mydbhelper(this, databasetable, null, 1); gpstracerdb = dbhelper01.getwritabledatabase(); //註冊一個按下 歷史記錄 的按鈕傾聽程式 btnhistorylist.setonclicklistener(btnhistorylistclick); //程式如果關閉時 要釋放 SQLiteDatabase 資源 protected void onstop() { super.onstop(); gpstracerdb.close(); //程式如果暫停 也要停止更新的動作 protected void onpause() { if (lm01!= null) { lm01.removeupdates(lm01listener); super.onpause(); //程式如果由停止或暫停的狀態 恢復為執行的狀態 //必須要重新記錄更新的動作 protected void onresume() { 78

if (lm01!= null) { lm01.requestlocationupdates(locationmanager.gps_provider, 2000, 5, lm01listener); lm01.requestlocationupdates(locationmanager.network_provider, 2000, 5, lm01listener); super.onresume(); public boolean oncreateoptionsmenu(menu menu) { getmenuinflater().inflate(r.menu.activity_main, menu); return true; //按下 歷史記錄 的按鈕時 要呼叫另一個程式出來 Button.OnClickListener btnhistorylistclick Button.OnClickListener() { = new public void onclick(view arg0) { Intent i01 = gpshistorylist.class); startactivity(i01); new Intent(getApplication(), ; 79

第五節 建立第二個程式 列出歷史資料 第一項 佈景主題 <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" > <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height = "fill_parent" > <Button android:id="@+id/btnreturn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparentleft="true" android:layout_alignparenttop="true" android:text = " 返回 " /> <TextView android:id="@+id/txtlist01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparentleft="true" android:layout_below="@+id/btnreturn" android:text="" /> </RelativeLayout> </ScrollView> 80

第二項 主程式 public class gpshistorylist extends Activity { TextView txtlist01; Button btnreturn; //宣告資料庫相關的物件 mydbhelper dbhelper01; //使用繼承自 SQLiteOpenHelper 類別所產生的物件 協 助我們建立資料庫連結的動作 SQLiteDatabase gpstracerdb; //連結資料庫進行查詢 新增資料的動作 String databasetable = "gpstracer"; //宣告資料表的名稱 這行可以不用 public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); //呼叫版面配置 這裡只有一個 返回鍵 以及 文字框 顯示歷史資料使用的 setcontentview(r.layout.activity_gpshistorylist); findview(); //自己建立的程式寫在這裡 private void findview() { txtlist01=(textview) findviewbyid(r.id.txtlist01); btnreturn=(button) findviewbyid(r.id.btnreturn); //返回鍵 要關閉自身的 activity btnreturn.setonclicklistener(btnreturnclick); //連結資料庫 81

dbhelper01 = new mydbhelper(this, databasetable, null, 1); gpstracerdb = dbhelper01.getwritabledatabase(); String[] colnames = new String[] {"_id", "gtdate", "gtlatitude", "gtlongitude", "gtaccuracy", "gtaltitude", "gttime", "gtspeed", "gtbearing"; String s01=""; Cursor c01 = gpstracerdb.query(databasetable, colnames, null, null, null, null, "_id desc"); //將內容以一個簡單的格式輸出 c01.movetofirst(); for (int i=0; i<c01.getcount(); i++) { s01 = s01 + "No." + c01.getstring(0) + ",\t\t\t\t"; //顯示自動增加的編號 s01 = s01 + "Time:" + c01.getstring(6) + "\n"; // 顯 示 第 6 欄的日期 換下一行 s01 = s01 + "Location:" + c01.getstring(2) + ",\t"; //顯示經度 s01 = s01 + c01.getstring(3) + "\n"; //顯示緯度 換下一行 s01 = s01 + "Accuracy:" + c01.getstring(4) + ",\t"; //顯示精確度 s01 = s01 + "Altitude:" + c01.getstring(5) + "\n"; // 顯 示 高度 換下一行 s01 = s01 + "Speed:" + c01.getstring(7) + ",\t\t\t"; //顯示速度 s01 = s01 + "Bearing:" + c01.getstring(8) + "\n\n"; //顯示方位 c01.movetonext(); txtlist01.settext(s01.tostring()); //程式如果關閉時 要釋放 SQLiteDatabase 資源 protected void onstop() { super.onstop(); 82

gpstracerdb.close(); Button.OnClickListener Button.OnClickListener() { btnreturnclick = new public void onclick(view arg0) { finish(); ; 83

ser vice 第七章 第一節 建立 MediaPlayer Server 第一項 修改 androidmanifest.xml 檔案 <?xml version="1.0" encoding="utf 8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="tw.a17" android:versioncode="1" android:versionname="1.0" > <uses sdk android:minsdkversion="15" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:name=".a17activity" android:label="@string/app_name" > <intent filter> <action android:name="android.intent.action.main" /> <category android:name="android.intent.category.launcher" /> </intent filter> </activity> <service android:name="mediaplayservice" android:enabled="true" > </service> </application> 84

</manifest> 建立 MediaPlayService.java 第二項 public class MediaPlayService extends Service { private MediaPlayer player; public void ondestroy() { super.ondestroy(); player.stop(); public int onstartcommand(intent intent, int flags, int startid) { File file = new File("/sdcard/londonkaleb.mp3"); player = MediaPlayer.create(this, Uri.fromFile(file)); player.start(); return super.onstartcommand(intent, flags, startid); public IBinder onbind(intent arg0) { return null; 第三項 建立主程式 public class A17Activity extends Activity { /** Called when the activity is first created. */ 85

//宣告一個 intent 的物件. 按 menu 功能鍵, 呼叫 service 時會使用. Intent i01; LinearLayout ll01; TextView tv01; /** * 這裡設定的動作, 其實就是在指定它的 數值. * 其中, Menu.FIRST 等於 1, 其餘繼續遞增. */ private static final int MENU_MUSIC = Menu.FIRST, MENU_PLAY_MUSIC = Menu.FIRST + 1, MENU_STOP_PLAYING_MUSIC = Menu.FIRST + 2, MENU_ABOUT = Menu.FIRST + 3, MENU_EXIT = Menu.FIRST + 4; public boolean oncreateoptionsmenu(menu menu) { /** * 在 oncreateoptionsmenu(menu menu) 這 裡, 已 經 幫 我 們 建 立 了 一 個 menu 的物件. * 所以這裡就是使用 menu 物件來新增 功能表. */ /** * 如果要新增子功能表的話, 必須使用 SubMenu 的物件, * 再某一個功能項目下, 再新增子功能表. */ SubMenu submenu; /** * 在 menu.addsubmenu() 這裡, 先登錄一個 功能項目 為 背景音樂, * 同時也設定這個功能項目, 是具有子功能項目的. * 括弧裡共有四個參數, 分別表示如下: * int groupid, 透過這裡建立功能表的群組, 這裡統一設定為 0 * int itemid, 這是它的 ID 號碼, 必須是唯一的. * int order, 顯示功能表的順序. * CharSequence title, 顯示的文字內容. */ 86

submenu = menu.addsubmenu(0, MENU_MUSIC, 0, " 背 景 音 樂").setIcon(android.R.drawable.ic_media_ff); //以下分別增加第 1, 2 個子功能項目. submenu.add(0, MENU_PLAY_MUSIC, 0, "播放背景音樂"); submenu.add(0, MENU_STOP_PLAYING_MUSIC, 1, "停止播放背景音樂"); //以下分別增加第 2, 3 個功能項目 menu.add(0, MENU_ABOUT, 1, 關 " 於 這 個 程 式...").setIcon(android.R.drawable.ic_dialog_info); menu.add(0, MENU_EXIT, 2, " 結 束").setIcon(android.R.drawable.ic_menu_close_clear_cancel); /** * 將剛才所建立的 menu 物件回傳. */ return super.oncreateoptionsmenu(menu); public boolean onoptionsitemselected(menuitem item) { /** * 當選擇功能項目時, 會到這裡執行. * 依我們點選的 項目 ID, 這裡會執行不同的程式. */ switch (item.getitemid()) { case MENU_PLAY_MUSIC: /** * 啟動 MediaPlayService 的 service. * 因此, 不要忘了要在 androidmanifest 這裡加入 service 的宣告. */ i01 = MediaPlayService.class); startservice(i01); break; new Intent(A17Activity.this, case MENU_STOP_PLAYING_MUSIC: /** * 停止 service 87

*/ i01 = MediaPlayService.class); stopservice(i01); break; new Intent(A17Activity.this, case MENU_ABOUT: /** * 建立一個 AlertDialog 對話框. */ new AlertDialog.Builder(A17Activity.this).setTitle("關於這個程式").setMessage("選單範例程式").setCancelable(false).setIcon(android.R.drawable.star_big_on).setPositiveButton("確定", new DialogInterface.OnClickListener() { public onclick(dialoginterface dialog, void int which) { // TODO Auto generated method stub ).show(); break; case MENU_EXIT: finish(); break; default: break; return super.onoptionsitemselected(item); public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.main); setupviewcomponent(); 88

private void setupviewcomponent() { ll01 = (LinearLayout) findviewbyid(r.id.ll01); tv01 = (TextView) findviewbyid(r.id.tv01); /** * 所有需要使用 ContextMenu 的元件, 都需要先進行註冊的動作. * 執行 registerforcontextmenu 將元件註冊要進行 ContextMenu 的動 作. */ registerforcontextmenu(ll01); registerforcontextmenu(tv01); public boolean oncontextitemselected(menuitem item) { /** * 由於功能表做的事情相同, 因此, 這裡就省略不做判斷的動作, * 直接呼叫前面的 onoptionsitemselected 方法, * 再將這裡的 item 物件傳給它, 由它來處理~~ */ onoptionsitemselected(item); return super.oncontextitemselected(item); public void oncreatecontextmenu(contextmenu menu, View v, ContextMenuInfo menuinfo) { super.oncreatecontextmenu(menu, v, menuinfo); if (v == ll01) { /** * 就整個介面佈局來看, LinearLayout 是最底層的, * 再上來是 TextView 的元件, 因此, 當我們在 TextView 上長按, 89

* 會先 觸發 上層 TextView 的動作, * 再往下傳遞 觸發 底層的 LinearLayout 的動作. */ if (menu.size() == 0) { /** * 以下的動作, 其實和最上方的 oncreateoptionsmenu 的動作 是相同的. */ SubMenu submenu; //建立第 1 個功能項目, 並設定具有子功能表 submenu = menu.addsubmenu(0, MENU_MUSIC, 0, "背景音 樂").setIcon(android.R.drawable.ic_media_ff); //以下分別增加第 1, 2 個子功能項目. submenu.add(0, MENU_PLAY_MUSIC, 0, "播放背景音樂"); submenu.add(0, MENU_STOP_PLAYING_MUSIC, 1, "停止播放 背景音樂"); //以下分別增加第 2, 3 個功能項目 menu.add(0, MENU_ABOUT, 1, " 關 於 這 個 程 式...").setIcon(android.R.drawable.ic_dialog_info); menu.add(0, MENU_EXIT, 2, " 結 束").setIcon(android.R.drawable.ic_menu_close_clear_cancel); else if (v == tv01) { menu.add(0, MENU_ABOUT, 1, "關於這個程式..."); 90