Java講義

Similar documents
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講義

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

Dynamic Layout in Android

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

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

Database_001

Microsoft PowerPoint - ch6 [相容模式]

實作SQLiteOpenHelper類別

投影片 1

Android Fragment

建立Android新專案

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

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

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

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

書面

ShareText

epub83-1

RecyclerView and CardVew

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

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

Microsoft Word - 02.目錄.doc

untitled

Android + NFC

幻灯片 1

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

untitled

Android Android Android SDK iv

Microsoft Word - template.doc

Windows XP

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

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

Microsoft Word - 01.DOC

AL-M200 Series

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

建立Android新專案

EJB-Programming-4-cn.doc

6-1 Table Column Data Type Row Record 1. DBMS 2. DBMS MySQL Microsoft Access SQL Server Oracle 3. ODBC SQL 1. Structured Query Language 2. IBM

Microsoft Word - 第3章.doc

概述

1.ai

K7VT2_QIG_v3

RunPC2_.doc

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

Microsoft Word zw

ltu

Android 编程基础 Android 开发教程 & 笔记 1

Guide to Install SATA Hard Disks

mvc

教育部補助資訊軟體人才培育先導計畫 100 年度課程發展專案計畫 實驗課程名稱 : IPC(Inter-Process Communication) 開發教師 : 張晉源老師 開發學生 : 林政揚 學校系所 : 樹德科技大學資訊工程學系

封面-12

CC213

Lorem ipsum dolor sit amet, consectetuer adipiscing elit

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

PPBSalesDB.doc

Oracle 4

建立Android新專案

Microsoft Word - ch04三校.doc

TX-NR3030_BAS_Cs_ indd

SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk" 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基

目 錄 壹 青 輔 會 結 案 附 件 貳 活 動 計 劃 書 參 執 行 內 容 一 教 學 內 容 二 與 當 地 教 師 教 學 交 流 三 服 務 執 行 進 度 肆 執 行 成 效 一 教 學 課 程 二 與 當 地 教 師 教 學 交 流 三 服 務 滿 意 度 調 查 伍 服 務 檢

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

Microsoft Word - 11月電子報1130.doc

<4D F736F F D C4EAC0EDB9A4C0E04142BCB6D4C4B6C1C5D0B6CFC0FDCCE2BEABD1A15F325F2E646F63>

Important Notice SUNPLUS TECHNOLOGY CO. reserves the right to change this documentation without prior notice. Information provided by SUNPLUS TECHNOLO

<ADB6ADB1C25EA8FAA6DB2D4D56432E706466>

INTRODUCTION TO COM.DOC

Spyder Anaconda Spyder Python Spyder Python Spyder Spyder Spyder 開始 \ 所有程式 \ Anaconda3 (64-bit) \ Spyder Spyder IPython Python IPython Sp

Java

Microsoft Office SharePoint Server MOSS Web SharePoint Web SharePoint 22 Web SharePoint Web Web SharePoint Web Web f Lists.asmx Web Web CAML f

27 :OPC 45 [4] (Automation Interface Standard), (Costom Interface Standard), OPC 2,,, VB Delphi OPC, OPC C++, OPC OPC OPC, [1] 1 OPC 1.1 OPC OPC(OLE f

Chapter 9: Objects and Classes

untitled

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

第六章

ebook140-9

使用手冊

untitled

建模与图形思考

PowerPoint 簡報

前言 C# C# C# C C# C# C# C# C# microservices C# More Effective C# More Effective C# C# C# C# Effective C# 50 C# C# 7 Effective vii

Transcription:

Android 講義 王振民 2012.07.10 目錄 第一章音樂播放程式...3 第一節最陽春的音樂播放程式...3 第一項建立空白的新專案...3 第二項加入 MediaPlayer 物件...3 第二節改善這個程式...5 第一項瞭解 Activity 的生命週期...5 第二項離開程式時也能停止音樂的播放...8 第三項按下播放按鈕才開始播放...8 第二章 google 地圖...12 第一節基本的...12 第一項經度緯度...12 第二項二種定位方式...12 第二節簡單的 GPS 專案...13 第一項 AndroidManifest.xml 檔案...13 第二項介面佈局檔...13 第三項主要程式...14 第三節加強一些的地圖...17 第一項 Main.xml...17 第二項主程式...18 第三章 SQLite 資料庫...23 第一節使用 SharedPreferences...23 第一項介面佈局檔...23 第二項建立主程式的內容 - 儲存偏好設定...24 第三項驗證儲存偏好的動作...25 第四項建立主程式的內容 - 提取偏好設定...26 第二節簡單使用 SQLite...27 第一項介面佈局檔...28 第二項建立 SQLiteOpenHelper 的子類別...28 第三項修改主程式...29 第四項驗證看看 -sqlite3 指令...32 第五項顯示資料表內容...32 Android 講義 v0.5 1 王振民

第四章 service...34 第一節建立 MediaPlayer Server...34 第一項修改 androidmanifest.xml 檔案...34 第二項建立 MediaPlayService.java...35 第三項建立主程式...35 Android 講義 v0.5 2 王振民

第一章 音樂播放程式 第一節最陽春的音樂播放程式 第一項 建立空白的新專案 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 動作, 如下 : Android 講義 v0.5 3 王振民

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()... 略 的方法 Android 講義 v0.5 4 王振民

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 的生命週期 Android 講義 v0.5 5 王振民

Figure. The activity lifecycle. 資料來源 : http://developer.android.com/guide/components/activities.html Android 講義 v0.5 6 王振民

Table. A summary of the activity lifecycle's callback methods. Method Description Killable after? Next oncreate() onrestart() onstart() onresume() onpause() onstop() ondestroy() 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 previous state, if that state was captured (see Saving Activity State, later). Always followed by onstart(). Called after the activity has been stopped, just prior to it being started again. Always followed by onstart() Called just before the activity becomes visible to the user. No Followed by onresume() if the activity comes to the foreground, or onstop() if it becomes hidden. Called just before the activity starts interacting with the user. At this point the activity is at the top of the activity stack, with user input going to it. Always followed by 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 the next activity will not be resumed until it returns. Followed either by onresume() if the activity returns back to the front, or by onstop() if it becomes invisible to the user. 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. Followed either by onrestart() if the activity is coming back to interact with the user, or by ondestroy() if this activity is going away. 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 destroying this instance of the activity to save space. You can distinguish between these two scenarios with the isfinishing() method. No No No Yes Yes Yes onstart() onstart() onresume() or onstop() onpause() onresume() or onstop() onrestart() or ondestroy() nothing 資料來源 : http://developer.android.com/guide/components/activities.html Android 講義 v0.5 7 王振民

第二項 離開程式時也能停止音樂的播放 剛剛我們所寫的程式, 如果還在播放的狀態, 我們就離開程式, 執行 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; Android 講義 v0.5 8 王振民

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; Android 講義 v0.5 9 王振民

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) { ; 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() 方法, 透過呼 Android 講義 v0.5 10 王振民

叫這個方法來取得我們 主要的 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(), mp01.start(); music01); ; 5. 執行程式試試看, 程式執行後, 必須等我們按 播放音樂 的按鈕後, 才會有音樂囉! 練習題 1: 目前有 播放音樂 的按鈕, 請自行建立 停止播放 的按鈕, 而且, 在 按下 停止播放 按鈕時, 要能停止音樂的播放動作 練習題 2: 試試看, 建立一個 暫停 / 播放 的按鈕, 按一下可以暫停音樂的播放, 再按一下, 可以繼續音樂的播放 Android 講義 v0.5 11 王振民

第二章 google 地圖 第一節基本的 第一項 經度緯度 緯度指的是水平的, 由赤道當做 0 度, 往北的方向稱為北緯, 一直到 90 度, 赤道往南, 稱為南緯, 一樣是到 90 度 經度是以倫敦格林威治天文台舊址的南北垂直線, 當做 0 度, 往東 ( 東經 ) 或往西 ( 西經 ) 到 180 度 經度與緯度再細分, 就稱為 分 秒, 概念和時間的分秒相同, 都是以 60 為一個單位, 每 1 度可以細分為 60 分, 每 1 分可以再細分為 60 秒 第二項 二種定位方式 android 提供二種定位方式, 一個是比較精細的 GPS 定位, 使用衛星訊號定位, 另一種是網 路定位, 是使用電信公司基地台, 這種方式比較不精確, 誤差可能的會在一公里左右 Android 講義 v0.5 12 王振民

第二節簡單的 GPS 專案 第一項 AndroidManifest.xml 檔案 這裡需要 android.permission.internet 的使用者授權 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="tw.a21" android:versioncode="1" android:versionname="1.0" > <uses-sdk android:minsdkversion="15" /> <uses-permission android:name="android.permission.internet"/> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:name=".a21activity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.main" /> <category android:name="android.intent.category.launcher" /> </intent-filter> </activity> <uses-library android:name="com.google.android.maps"/> </application> </manifest> 第二項 介面佈局檔 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > Android 講義 v0.5 13 王振民

<Spinner android:id="@+id/sp01" android:layout_width="match_parent" android:layout_height="wrap_content" android:text=" 請選擇地點 " /> <com.google.android.maps.mapview android:id="@+id/gm01" android:layout_width="match_parent" android:layout_height="wrap_content" android:apikey="0b3hivh5ujuvnk1mho5a-leznlg4qwaiqq4kxwg" /> </LinearLayout> 第三項 主要程式 * 之前的程式都是繼承 Activity, 不過, 在目前的 Google Maps API 這裡, 我們要繼承的類別是 MapActivity * 系統會要我們產生 isroutedisplayed() 的方法 public class A21Activity extends MapActivity { Called when the activity is first created. MapView gm01; // 宣告 MapView 的元件 MapController mc01; // 宣告 MapController 元件 Spinner sp01; // 使用二維陣列的方式, 定訂以下四所大學的座標 String[][] locations = { {" 台灣大學 ", "25.019943,121.542353", {" 清華大學 ", "24.795621,120.998153", {" 交通大學 ", "24.791704,121.003341", {" 成功大學 ", "23.000875,120.218017" ; public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); Android 講義 v0.5 14 王振民

setcontentview(r.layout.main); setupviewcomponent(); setmaplocation(); * 繼承 MapActivity 時, 會需要以下的方法 protected boolean isroutedisplayed() { return false; private void setupviewcomponent() { sp01 = (Spinner) findviewbyid(r.id.sp01); gm01 = (MapView) findviewbyid(r.id.gm01); // 由資源裡取得對應的元件 產生 mc01 的物件 mc01 = gm01.getcontroller(); // 由 gm01 的物件裡, 取得 Controller 的方法, mc01.setzoom(16); // 設定預設的放大倍率是 16 // 這個是要給 spinner 元件使用的字串陣列的中繼器 ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.r.layout.simple_spinner_item); // 以下分別將 spinner 裡分別註冊各個項目點選的 Listener for (int i = 0; i < locations.length; i++ ) { adapter.add(locations[i][0]); // 取得各個大學的名稱 adapter.setdropdownviewresource(android.r.layout.simple_dropdown_item_1line); sp01.setadapter(adapter); sp01.setonitemselectedlistener(sp01click); // double lat = 22.755797; // 台東巨匠的經度 // double lon = 121.144438; // 台東巨匠的緯度 // // int ilat = (int) (lat * 1e6); // 經緯度都乘於 10 的 6 次方 ( 一百萬 ) 的整數 Android 講義 v0.5 15 王振民

// int ilon = (int) (lon * 1e6); // 這是 Google Maps 所接收的值 // // GeoPoint gp01 = new GeoPoint(iLat, ilon); // 將經度緯度轉送給 GeoPoint 類別的 gp01 物件 // mc01.animateto(gp01); // 在地圖裡顯示座標指定的位置 OnItemSelectedListener sp01click = new OnItemSelectedListener() { arg2, public void onitemselected(adapterview<?> arg0, View arg1, int long arg3) { setmaplocation(); public void onnothingselected(adapterview<?> arg0) { ; public void setmaplocation() { int iselect = sp01.getselecteditemposition(); String[] s02 = locations[iselect][1].split(","); double lat = Double.parseDouble(s02[0]); // 緯度 double lon = Double.parseDouble(s02[1]); // 經度 int ilat = (int) (lat * 1e6); // 經緯度都乘於 10 的 6 次方 ( 一百萬 ) 的整數 int ilon = (int) (lon * 1e6); // 這是 Google Maps 所接收的值 GeoPoint gp01 = new GeoPoint(iLat, ilon); // 將經度緯度轉送給 GeoPoint 類別的 gp01 物件 mc01.animateto(gp01); // 在地圖裡顯示座標指定的位置 Android 講義 v0.5 16 王振民

第三節加強一些的地圖 第一項 Main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" > <Spinner android:id="@+id/sp01" android:layout_width="match_parent" android:layout_height="wrap_content" android:text=" 請選擇地點 " /> <Spinner android:id="@+id/sp02" android:layout_width="match_parent" android:layout_height="wrap_content" android:text=" 街道圖 " /> </LinearLayout> <com.google.android.maps.mapview android:id="@+id/gm01" android:layout_width="match_parent" android:layout_height="wrap_content" android:apikey="0c9ozd3a32aw Vd7Z70-wu5RJyQKwqux-wT6_Q" android:clickable="true" /> </LinearLayout> Android 講義 v0.5 17 王振民

第二項 主程式 * 之前的程式都是繼承 Activity, 不過, 在目前的 Google Maps API 這裡, 我們要繼承的類別是 MapActivity * 系統會要我們產生 isroutedisplayed() 的方法 * * 另外, 我們在 res/layout/main.xml 那裡, 要新增一個 <com.google.android.maps.mapview /> * public class A22Activity extends MapActivity { Called when the activity is first created. MapView gm01; // 宣告 MapView 的元件 MapController mc01; // 宣告 MapController 元件 Spinner sp01; Spinner sp02; // 這個是要加入定位系統, 所使用的類別 MyLocationOverlay mmylocation; // 使用二維陣列的方式, 定訂以下四所大學的座標 String[][] locations = { {" 台灣大學 ", "25.019943,121.542353", {" 清華大學 ", "24.795621,120.998153", {" 交通大學 ", "24.791704,121.003341", {" 成功大學 ", "23.000875,120.218017" ; String[] maptype = {" 街道圖 ", " 衛星圖 "; public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.main); setupviewcomponent(); setmaplocation(); Android 講義 v0.5 18 王振民

* 繼承 MapActivity 時, 會需要以下的方法 protected boolean isroutedisplayed() { return false; private void setupviewcomponent() { sp01 = (Spinner) findviewbyid(r.id.sp01); sp02 = (Spinner) findviewbyid(r.id.sp02); gm01 = (MapView) findviewbyid(r.id.gm01); // 由資源裡取得對應的元件 gm01.setbuiltinzoomcontrols(true); // 設定可以由使用者縮放 mc01 = gm01.getcontroller(); // 由 gm01 的物件裡, 取得 Controller 的方法, 產生 mc01 的物件 mc01.setzoom(16); // 設定預設的放大倍率是 16 * 以下程式要加入自己的定位系統. List<Overlay> mapoverlays = gm01.getoverlays(); mmylocation = new MyLocationOverlay(this, gm01); mmylocation.runonfirstfix(new Runnable() { public void run() { // 將自己的位置傳送到 MapController 元件. mc01.animateto(mmylocation.getmylocation()); ); mapoverlays.add(mmylocation); // 這個是要給 sp01 元件使用的字串陣列的中繼器 ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.r.layout.simple_spinner_item); // 取得各個大學的名稱 for (int i = 0; i < locations.length; i++ ) { adapter.add(locations[i][0]); // 以下註冊 sp01 項目點選的 Listener Android 講義 v0.5 19 王振民

adapter.setdropdownviewresource(android.r.layout.simple_dropdown_item_1line); sp01.setadapter(adapter); sp01.setonitemselectedlistener(sp01click); // 這個是要給 sp02 元件使用的字串陣列的中繼器 adapter = new ArrayAdapter<String>(this, android.r.layout.simple_spinner_item); // 取得各個地圖類型的名稱 for (int i = 0; i < maptype.length; i++ ) { adapter.add(maptype[i]); // 以下註冊 sp02 項目點選的 Listener adapter.setdropdownviewresource(android.r.layout.simple_dropdown_item_1line); sp02.setadapter(adapter); sp02.setonitemselectedlistener(sp02click); // double lat = 22.755797; // 台東巨匠的經度 // double lon = 121.144438; // 台東巨匠的緯度 // // int ilat = (int) (lat * 1e6); // 經緯度都乘於 10 的 6 次方 ( 一百萬 ) 的整數 // int ilon = (int) (lon * 1e6); // 這是 Google Maps 所接收的值 // // GeoPoint gp01 = new GeoPoint(iLat, ilon); // 將經度緯度轉送給 GeoPoint 類別的 gp01 // // 物件 // mc01.animateto(gp01); // 在地圖裡顯示座標指定的位置 public void setmaplocation() { int iselect = sp01.getselecteditemposition(); String[] s02 = locations[iselect][1].split(","); double lat = Double.parseDouble(s02[0]); // 緯度 double lon = Double.parseDouble(s02[1]); // 經度 int ilat = (int) (lat * 1e6); // 經緯度都乘於 10 的 6 次方 ( 一百萬 ) 的整數 int ilon = (int) (lon * 1e6); // 這是 Google Maps 所接收的值 Android 講義 v0.5 20 王振民

類別的 gp01 物件 GeoPoint gp01 = new GeoPoint(iLat, ilon); // 將經度緯度轉送給 GeoPoint mc01.animateto(gp01); // 在地圖裡顯示座標指定的位置 // OnItemSelectedListener sp01click = new OnItemSelectedListener() { arg2, public void onitemselected(adapterview<?> arg0, View arg1, int long arg3) { setmaplocation(); public void onnothingselected(adapterview<?> arg0) { ; OnItemSelectedListener sp02click = new OnItemSelectedListener() { arg2, public void onitemselected(adapterview<?> arg0, View arg1, int long arg3) { switch (arg2) { case 0: gm01.setsatellite(false); // 設定為道路圖 break; case 1: gm01.setsatellite(true); break; // 設定為衛星圖 default: break; Android 講義 v0.5 21 王振民

public void onnothingselected(adapterview<?> arg0) { ; public boolean onkeydown(int keycode, KeyEvent event) { int nextzoom=1, zoom=1; switch (keycode) { case KeyEvent.KEYCODE_I: * 如果按 I 的話, 表示要放大, 會將現在的倍率加 1 nextzoom = gm01.getzoomlevel() + 1; * if (nextzoom > gm01.getmaxzoomlevel()) { zoom = gm01.getmaxzoomlevel(); else { zoom = nextzoom; break; case KeyEvent.KEYCODE_O: * 如果按 O 的話, 表示要放大, 會將現在的倍率減 1 nextzoom = gm01.getzoomlevel() - 1; if (nextzoom < 1) { zoom = 1; else { zoom = nextzoom; break; default: break; Android 講義 v0.5 22 王振民

mc01.setzoom(zoom); return super.onkeydown(keycode, event); protected void onresume() { super.onresume(); mmylocation.enablemylocation(); protected void onstop() { mmylocation.disablemylocation(); super.onstop(); 第三章 SQLite 資料庫 在介紹 SQLite 之前, 我們先來認識 SharedPreferences( 存取偏好設定 ) 第一節使用 SharedPreferences 請建立新的專案, 分別再依以下動作進行 第一項 介面佈局檔 1. 建立 TextView, 顯示文字為 姓名 Android 講義 v0.5 23 王振民

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() { 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() { Android 講義 v0.5 24 王振民

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(), " 資料儲存完成 ", Toast.LENGTH_SHORT).show(); ; 3. 執行程式, 在二個欄位裡輸入資料, 再按一下 bt01, 使系統觸發事件, 執行 bt01click 的動作 第三項 驗證儲存偏好的動作 前項動作執行後, 我們可以驗證看看 驗證動作如下 : Android 講義 v0.5 25 王振民

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); bt01 = (Button) findviewbyid(r.id.bt01); bt01.setonclicklistener(bt01click); loadsharedprefs(); private void loadsharedprefs() { 2. 在 loadsharedprefs 方法裡, 使用 Android 講義 v0.5 26 王振民

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 的欄位裡 練習題 : 目前的偏好設定儲存, 必須按下 儲存偏好設定 的按鈕, 才會有作用, 請 將程式修改, 當使用者直接離開程式時, 也能由程式將資料儲存後再離開程式 第二節簡單使用 SQLite 我們要使用 SQLite 的話, 需要使用 SQLiteOpenHelper 以及 SQLiteDatabase 這二個類別來建立 以及存取資料庫, 其中的 SQLiteOpenHelper 是一個幫助類別 (Helper Class), 我們需要建立一個繼承自 SQLiteOpenHelper 的類別,SQLiteOpenHelper 主要的目的是協助我們建立資料表, 以及資料庫的版本管理 由 SQLiteOpenHelper 所建立出來的資料庫, 是一個 SQLiteDatabase 類別的物件, 因此, 我們可以透過 SQLiteDatabase 所提供的方法該行新增 刪除 更新資料表的內容 以下請建立新專案, 再依照底下的動作進行 Android 講義 v0.5 27 王振民

第一項 介面佈局檔 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) { public void onupgrade(sqlitedatabase arg0, int arg1, int arg2) { 7. 修改 oncreate() 的方法 ( 也就是覆寫父類別的方法 ), 我們要建立自己要使用的資料 Android 講義 v0.5 28 王振民

表, 程式碼參考如下, 其中的 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 方法, 參考如下 : public class MainActivity extends Activity { SQLiteDatabase db01; mydbhelper dbhelper01; String databasetable = "t05note"; EditText et01; TextView tv01; Button bt01; Android 講義 v0.5 29 王振民

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 的模擬器的系統 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, 勾選 Android 講義 v0.5 30 王振民

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) { ; 7. 建立 bt01click 裡的 onclick 事件, 參考如下 : Button.OnClickListener bt01click = new Button.OnClickListener() { public void onclick(view v) { long id; Android 講義 v0.5 31 王振民

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 的命令提示環境 第五項 顯示資料表內容 1. 在 findview 方法裡, 呼叫 showtables 方法, 參考如下 : private void findview() { et01 = (EditText) findviewbyid(r.id.et01); tv01 = (TextView) findviewbyid(r.id.tv01); bt01 = (Button) findviewbyid(r.id.bt01); Android 講義 v0.5 32 王振民

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 = 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. 執行程式看看, 應該可以列出所有的記錄 Android 講義 v0.5 33 王振民

第四章 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> </manifest> Android 講義 v0.5 34 王振民

第二項 建立 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. // 宣告一個 intent 的物件. 按 menu 功能鍵, 呼叫 service 時會使用. Intent i01; LinearLayout ll01; Android 講義 v0.5 35 王振民

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, 顯示的文字內容. 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 個功能項目 Android 講義 v0.5 36 王振民

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 = new Intent(A17Activity.this, MediaPlayService.class); startservice(i01); break; case MENU_STOP_PLAYING_MUSIC: * 停止 service i01 = new Intent(A17Activity.this, MediaPlayService.class); stopservice(i01); break; case MENU_ABOUT: * 建立一個 AlertDialog 對話框. new AlertDialog.Builder(A17Activity.this).setTitle(" 關於這個程式 ").setmessage(" 選單範例程式 ") Android 講義 v0.5 37 王振民

.setcancelable(false).seticon(android.r.drawable.star_big_on).setpositivebutton(" 確定 ", new DialogInterface.OnClickListener() { public void onclick(dialoginterface dialog, int which) { // TODO Auto-generated method stub break; ).show(); case MENU_EXIT: finish(); break; default: break; return super.onoptionsitemselected(item); public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.main); setupviewcomponent(); private void setupviewcomponent() { ll01 = (LinearLayout) findviewbyid(r.id.ll01); tv01 = (TextView) findviewbyid(r.id.tv01); * 所有需要使用 ContextMenu 的元件, 都需要先進行註冊的動作. * 執行 registerforcontextmenu 將元件註冊要進行 ContextMenu 的動作. registerforcontextmenu(ll01); Android 講義 v0.5 38 王振民

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 上長按, * 會先觸發上層 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 個子功能項目. Android 講義 v0.5 39 王振民

樂 "); 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, " 關於這個程式..."); Android 講義 v0.5 40 王振民

Android 講義 v0.5 41 王振民