Chapter 13 Android 實戰演練
線上匯率查詢
線上匯率查詢 本節範例將實作一個簡單的線上費率查詢, 利用 Url 查詢台灣銀行的即時匯率, 欲查詢的網址為 http://rate.bot.com.tw/pages/static/uip003.zh- TW.htm 此網頁中每隔幾分鐘會更新一次匯率, 所以範例程式在一開啟時會抓取此網頁並將網頁內容解析後將匯率資料取出
線上匯率查詢 台灣銀行線上即時匯率查詢
程式範例結果 : 線上匯率查詢
線上匯率查詢 res/values/arrays.xml <?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="money"> <item> 美金 </item> <item> 港幣 </item> <item> 英鎊 </item> <item> 澳幣 </item> <item> 加拿大幣 </item> <item> 新加坡幣 </item> <item> 瑞士法郎 </item> <item> 日圓 </item> <item> 南非幣 </item> <item> 瑞典幣 </item> <item> 紐元 </item> <item> 泰幣 </item> <item> 菲國比索 </item> <item> 印尼幣 </item> <item> 歐元 </item> <item> 韓元 </item> <item> 越南盾 </item> <item> 馬來幣 </item> <item> 人民幣 </item> </string-array> </resources>
線上匯率查詢 res/layout/main.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:text=" 台幣換 " android:id="@+id/textview01" android:textsize="30sp" android:layout_margintop="10px" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <Spinner android:id="@+id/spinner01" android:layout_torightof="@+id/textview01" android:layout_margintop="10px" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <Button android:layout_torightof="@+id/spinner01" android:text=" 匯率 " android:textsize="22sp" android:layout_margintop="10px" android:layout_height="wrap_content" android:layout_width="wrap_content" android:id="@+id/button01" /> </RelativeLayout>
線上匯率查詢 程式部分則是利用 HttpURLConnection 將台灣銀行網頁資料讀進來做分析, 抓取網頁的程式碼如下 : HttpURLConnection httpurlconnection = null; // Web URL 為上述台灣銀行匯率網址 URL url = new URL(WebURL); httpurlconnection = (HttpURLConnection)url.openConnection(); httpurlconnection.setrequestmethod("get"); httpurlconnection.setdoinput(true); httpurlconnection.setdooutput(true); httpurlconnection.connect();
線上匯率查詢 建立連線後, 程式必須將網頁資料讀進一個 Buffer 中, 以便後續分析, 程式如下 BufferedReader in = new BufferedReader( new InputStreamReader(httpUrlconnection.getInputStream())); String decodedstring; while ((decodedstring = in.readline())!= null) urldata += decodedstring; in.close();
擷取的網頁原始碼 線上匯率查詢
線上匯率查詢 分析網頁 start = urldata.indexof("<td class=\"decimal\">", end+1); end = urldata.indexof("</td>", start+1); temp = urldata.substring(start+20, end); if (!temp.equals("-") ) buy_cash.add(temp); else buy_cash.add(" 無資料 ");
擲骰子
擲骰子遊戲簡介 本節範例實作一擲骰子比大小遊戲, 使用的感應器為加速感應器, 經由程式計算出的加速度大於某一數值時就代表擲骰 遊戲者分別擲骰進行大小比較之遊戲, 骰子點數較大者勝, 如遇平手則重新擲骰 遊戲中也分成一顆骰子與兩顆骰子, 可由使用者自行選擇, 程式畫面如下頁圖所示
擲骰子遊戲畫面 -1
擲骰子遊戲畫面 -2
擲骰子遊戲程式碼 -1 程式一開始可選擇 : 1. 開始遊戲 2. 離開遊戲 3. 說明 啟動遊戲後, 使用者需先選擇玩法, 分別有一顆或兩顆骰子, 此處透過 Intent 方式去啟動另一個活動, 程式碼如下頁所示
擲骰子遊戲程式碼 -2 啟動遊戲程式碼 : btnnewgame.setonclicklistener(new OnClickListener() public void onclick(view v) setcontentview(r.layout.dicenumber); btnonedice = (Button) findviewbyid(r.id.btnonedice); btntwodice = (Button) findviewbyid(r.id.btntwodice); btnonedice.setonclicklistener(new OnClickListener() @Override public void onclick(view v) /* 設定一顆骰子的 Intent 並傳送 */ Intent intent1 = new Intent(); intent1.setclass(dicegameex.this,onedice.class); startactivity(intent1); ); btntwodice.setonclicklistener(new OnClickListener() @Override public void onclick(view v) /* 設定兩顆骰子的 Intent 並傳送 */ Intent intent1 = new Intent(); intent1.setclass(dicegameex.this,twodice.class); startactivity(intent1); ); );
擲骰子遊戲程式碼 -2 離開遊戲程式碼 : btnquitgame.setonclicklistener(new OnClickListener() public void onclick(view v) AlertDialog.Builder builder = new AlertDialog.Builder(DiceGameEX.this); builder.seticon(r.drawable.alert_dialog_icon); builder.settitle(" 離開程式 "); builder.setmessage(" 是否確定要離開?"); builder.setpositivebutton("yes", new DialogInterface.OnClickListener() public void onclick(dialoginterface dialog, int whichbutton) finish(); ); ); builder.setnegativebutton("no", new DialogInterface.OnClickListener() public void onclick(dialoginterface dialog, int whichbutton) ); builder.show();
擲骰子遊戲程式碼 -3 oncreate 程式碼 : /* 設定畫面不旋轉 */ setrequestedorientation(activityinfo.screen_orientation_nosensor); /* 初始化元件 */ btnonestart =(Button) findviewbyid(r.id.btnonestart); btnonestop = (Button) findviewbyid(r.id.btnonestop); btnonereturn = (Button) findviewbyid(r.id.btnonereturn); textplay = (TextView) findviewbyid(r.id.textplay); textwin = (TextView) findviewbyid(r.id.textwin); /* 使用 SensorManager 取得系統感應器 */ sensormanager = (SensorManager)getSystemService(Context.SENSOR_SERVICE); /* 設定為加速度感應器 */ sensor = sensormanager.getdefaultsensor(sensor.type_accelerometer); /* 設定骰子旋轉動畫 */ diceanimation = new RotateAnimation(0.0f, +350.0f, Animation.RELATIVE_TO_SELF, 2.0f, Animation.RELATIVE_TO_SELF, 2.0f);
擲骰子遊戲程式碼 -4 返回及停止程式碼 : protected void onresume() /* 重新設定遊戲參數 */ playerturn = 1; playerone = 0; playertwo = 0; count = 0; finish = false; textplay.settext(" 開始擲骰 "); textwin.settext(""); /* 向系統註冊感測器 */ sensormanager.registerlistener (lsn, sensor, SensorManager.SENSOR_DELAY_UI ); super.onresume(); @Override protected void onpause() /* 向系統註銷感測器 */ sensormanager.unregisterlistener(lsn); super.onpause();
擲骰子遊戲程式碼 -5 接著就是加速度感測器的部分, 在 onsensorchanged 中設定感測 Threshold 值為 800 及搖動偵測時間間隔為 1 秒, 利用 Math.abs 數學函式計算出加速度值 並將遊戲規則寫於此函式內, 使遊戲更為完整 因程式碼過多在此就不列出, 詳細考參考備註欄
來電黑名單
來電黑名單 本節範例實作一個來電黑名單, 只要在黑名單內的電話打來, 程式會自動將其轉為靜音模式, 而這些黑名單的資料會儲存在 SD 卡中的 BlackList 資料夾中 在程式中, 我們也將黑名單註冊為 Service, 這樣即使退出了黑名單的程式也可以繼續保持黑名單功能 程式總共分為兩部分, 第一部分為 Activity, 用來讀取電話連絡人資訊以及設定黑名單, 第二部分為 Service, 當有電話來電時會去檢查此來電是否為名單上的電話號碼, 若是則將此通電話鈴聲設為靜音
程式範例結果圖 : 來電黑名單
來電黑名單 程式一開始會抓取手機的連絡人資料並顯示在電話簿的 Tab 中, 程式碼如下 : public void oncreate(bundle savedinstancestate) super.oncreate(savedinstancestate); // 抓取通訊錄的聯絡人資料 GetContact(); // 建立 Tab CreateTab(); // 將連絡人資訊顯示在 Tab1 CreatePhoneContactTab(); // 抓取 SD 卡中的黑名單列表 GetBlackList(); // 將黑名單資訊顯示在 Tab2 CreateBlackListTab();
來電黑名單 利用 ContentResolver 來抓取系統中的連絡人資料 : ContentResolver cr = getcontentresolver(); Cursor c = cr.query(contacts.phones.content_uri, null, null, null, null); phoneinfo_name = new String[c.getCount()]; phoneinfo_number = new String[c.getCount()]; ContactInfo = new ArrayList<String>(); // 先看抓取之 cusor 是否有資料 if (c.movetofirst()) int namecolumn = c.getcolumnindex(phones.name); int phonecolumn = c.getcolumnindex(phones.number); int index = 0; do phoneinfo_name[index] = c.getstring(namecolumn); phoneinfo_number[index] = c.getstring(phonecolumn); ContactInfo.add((phoneInfo_Name[index] + " : " + phoneinfo_number[index])); index++; while (c.movetonext()); Collections.reverse(ContactInfo);
來電黑名單 接著顯示利用 Adapter 將 ContactInfo 顯示在電話簿的 Tab 中, 如下 : v_contact = (ListView)findViewById(R.id.contactList); adaptercontact = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, ContactInfo); lv_contact.setadapter(adaptercontact); // 設定 lv_contact 的 itemclick 事件 lv_contact.setonitemclicklistener(contact_listener);
來電黑名單 檢查是否有黑名單的資料夾 : String strdirectoy ="/sdcard/blacklist"; // 檢查 SDCard 中是否有 BlackList 資料夾, 若無則建立資料夾 boolean success = (new File(strDirectoy)).mkdir(); if (success) // Log
來電黑名單 檢查 blacklist.txt 是否存在 : // 檢查 SDCard 中的 BlackList 資料夾內是否有 blacklist.txt 檔案, 若無則建立新檔案 File f; f = new File("/sdcard/BlackList/blackList.txt"); if(!f.exists() ) f.createnewfile(); // 將檔案中的黑名單讀取至 file_blacklist 中 FileReader fr = new FileReader( "/sdcard/blacklist/blacklist.txt" ); BufferedReader br = new BufferedReader( fr ); String temp = br.readline(); while( temp!= null ) file_blacklist.add(temp); temp = br.readline();
來電黑名單 加入和移除黑名單 : OnItemClickListener contact_listener = new OnItemClickListener() @Override public void onitemclick(adapterview<?> arg0, View arg1, int arg2, long arg3) boolean hasremoved = false; Iterator iterator = file_blacklist.iterator(); while(iterator.hasnext()) if ( ContactInfo.get(arg2).equals(iterator.next().toString()) ) now_remove = arg2; showdialog(remove_blacklist); hasremoved = true; break; if (!hasremoved ) now_add = arg2; showdialog(add_blacklist); ;
來電黑名單 加入和移除黑名單 : OnItemClickListener blacklist_listener = new OnItemClickListener() @Override public void onitemclick(adapterview<?> arg0, View arg1, int arg2, long arg3) // TODO Auto-generated method stub TextView temp = (TextView)arg1; String removedate = temp.gettext().tostring(); int i = 0; Iterator iterator = ContactInfo.iterator(); while(iterator.hasnext()) if ( removedate.equals(iterator.next().tostring())) now_remove = i; showdialog(remove_blacklist); break; i++; ;
來電黑名單 加入和移除黑名單 : @Override protected Dialog oncreatedialog(int id) switch (id) case ADD_BLACKLIST: return new AlertDialog.Builder(BlackList.this).setIcon(android.R.drawable.stat_sys_warning).setTitle(" 是否將此號碼加入黑名單 ").setpositivebutton(" 確定 ", new DialogInterface.OnClickListener() public void onclick(dialoginterface dialog, int whichbutton) file_blacklist.add(contactinfo.get(now_add)); UpdateBlackListFile(); ).setnegativebutton(" 取消 ", new DialogInterface.OnClickListener() public void onclick(dialoginterface dialog, int whichbutton) ).create(); case REMOVE_BLACKLIST: return new AlertDialog.Builder(BlackList.this).setIcon(android.R.drawable.stat_sys_warning).setTitle(" 是否將此號碼移除黑名單 ").setpositivebutton(" 確定 ", new DialogInterface.OnClickListener() public void onclick(dialoginterface dialog, int whichbutton) file_blacklist.remove(contactinfo.get(now_remove)); UpdateBlackListFile(); ).setnegativebutton(" 取消 ", new DialogInterface.OnClickListener() public void onclick(dialoginterface dialog, int whichbutton) ).create(); return null;
來電黑名單 更新黑名單狀態 public void UpdateBlackListFile() // 將黑名單依照字母排序 Collections.sort(file_BlackList, String.CASE_INSENSITIVE_ORDER); // 更新黑名單的 adapter adapterblacklist.notifydatasetchanged(); try FileWriter fw = new FileWriter( "/sdcard/blacklist/blacklist.txt", false ); BufferedWriter bw = new BufferedWriter( fw ); Iterator iterator = file_blacklist.iterator(); while(iterator.hasnext()) bw.write(iterator.next().tostring()); bw.newline(); bw.close(); th.clearfocus(); catch (IOException e) // TODO Auto-generated catch block e.printstacktrace();
來電黑名單 Service 部份 public class PhoneCallListener extends PhoneStateListener public void oncallstatechanged(int state, String incomingnumber) super.oncallstatechanged(state, incomingnumber); AudioManager am = (AudioManager) getsystemservice(context.audio_service); Log.i("INCOMING", incomingnumber); switch (state) case TelephonyManager.CALL_STATE_IDLE: if ( am!= null ) am.setringermode(audiomanager.ringer_mode_normal); break; case TelephonyManager.CALL_STATE_RINGING: Log.i("INCOMING", incomingnumber); if ( am!= null ) if ( IsInBlackList(incomingNumber) ) am.setringermode(audiomanager.ringer_mode_silent); Context context1 = getapplicationcontext(); CharSequence text1 = " 黑名單狀態 "; int duration1 = Toast.LENGTH_LONG; // 設定停留長短 Toast.makeText(context1, text1, duration1).show(); break; default: break;
Q&A