2010年11月25日 星期四

Android筆記_離開Activity時詢問是否離開

1. 建一個點連結還是保持在原程式的網頁瀏覽,並於讀取時顯示載入中。
2. 攔截點擊"返回鍵"事件,給予相對的反應。
3. 離開程式時,詢問是否離開。

-------------------------------------------
接下來第三部份,當使用者離開程式時,詢問是否離開。

也就是在需要離開程式時,跳出附有Button的AlertDialog,讓使用者選擇是否離開。

上圖的case1就是跳出的確認視窗,當使用者確定要離開時,則執行OlaTeach_WebView.this.finish()來離開Activity。case2就是該篇所顯示的ProgressDialog。

執行結果:


最後貼上三篇所有程式碼:

package ola.OlaTeach_WebView;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.KeyEvent;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.TextView;

public class OlaTeach_WebView extends Activity {
/** Called when the activity is first created. */

private WebView OlaWebView;
private TextView lab1;
private ProgressDialog Pd;

public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
boolean CloseYN;
if (OlaWebView.canGoBack())
{
CloseYN = false;
OlaWebView.goBack();
}
else
{
show(1);
CloseYN = true;
}

event.startTracking();
return CloseYN;
}
return super.onKeyDown(keyCode, event);
}

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

String strURI = "http://10.172.50.2/SSCenter_Web_C/SSCenterMain.aspx";
//String strURI = "http://tinyurl.com/yz3j7sc";
OlaWebView = (WebView) findViewById(R.id.myWebView1);
lab1 =(TextView) findViewById(R.id.TextView01);

OlaWebView.setWebViewClient(new WebViewClient(){
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
// TODO Auto-generated method stub
lab1.setText("努力中");
show(2);
super.onPageStarted(view, url, favicon);
}
@Override
public void onPageFinished(WebView view, String url) {
// TODO Auto-generated method stub
lab1.setText("呼~~~完成");
Pd.hide();
super.onPageFinished(view, url);
}
});
OlaWebView.loadUrl(strURI);
}

public void show(int id) {
switch(id){
case 1:
new AlertDialog.Builder(OlaTeach_WebView.this)
.setTitle("你確定?")
.setMessage("要離開我了? T.T")
.setPositiveButton("沒錯",new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog, int which)
{
OlaTeach_WebView.this.finish();
}
})
.setNegativeButton("再留一下",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which)
{
}
})
.show();
break;
case 2:
Pd=new ProgressDialog(OlaTeach_WebView.this);
Pd.setTitle("我在讀取、別催我");
Pd.setMessage("努力中....");
Pd.show();
break;
default:
break;
}
}
}

Android筆記_攔截按鍵點擊事件(以返回鍵點擊回到WebView上一頁為例)

1. 建一個點連結還是保持在原程式的網頁瀏覽,並於讀取時顯示載入中。
2. 攔截點擊"返回鍵"事件,給予相對的反應。
3. 離開程式時,詢問是否離開。

----------------------------------------
接下來第二部份,要攔截使用者點選按鍵後的事件。以本例來說,原本使用者點選"返回鍵"後,會直接回到上一個Activity,這跟我們一般在操作網頁的感覺不同,所以應該在點擊返回鍵後,進行回到上一頁的動作。

所以首先我們要攔截按鍵點擊事件,直接看程式碼:

由上圖可知:
1. 可以利用onKeyDown中,以不同的keyCode來判斷使用者點擊的按鈕,以本例來說,就以keyCode == KeyEvent.KEYCODE_BACK可以判斷使用者是否按下返回鍵。

2. 再利用WebView本身附帶的canGoBack(判斷是否有上一頁)及goBack(移置上一頁)來完成回上頁的功能。

3. onKeyDown最後會返回一個boolean,來看使用者的點擊是否生效,所以若是還有上一頁則返回false,讓程式不要回到上一個Activity

Android筆記_WebView讀取網頁顯示讀取中

課程來到第四天,因為剛好碰到假日,老師也就理所當然出了很多作業。

其中一個作業是:利用WebView建立一個按下連結不會自動開啟內建瀏覽器的網頁瀏覽程式,並且在讀取網頁時顯示載入中,完成後顯示讀取完成;案下"返回鍵"時回到上一頁,若是為打開的第一頁則詢問是否離開?

所以這個作業要達到幾件事情:
1. 建一個點連結還是保持在原程式的網頁瀏覽,並於讀取時顯示載入中。
2. 攔截點擊"返回鍵"事件,給予相對的反應。
3. 離開程式時,詢問是否離開。

----------------------------------------------
先來看看第一項要如何達成:
1. 點選連結,不開啟手機內建的瀏覽器,而直接出現於原Activity的WebView。
方法:對WebView進行WebViewClient的設定。

2. 在WebView讀取網頁時,攔截開始讀取與讀取完成的事件。
方法:於設定WebViewClient時(也就是前1點),覆寫onPageStarted與onPageFinished方法,於內容中加入對應的動作。

3. 讀取網頁時,顯示讀取中。
方法:於第2點之onPageStarted時顯示ProgressDialog(ProgressDialog.show()),於onPageFinished時隱藏ProgressDialog(ProgressDialog.hide())。

語法:

上圖中的show()為ProgressDialog的呼叫。

最後,看一下執行結果

2010年11月24日 星期三

外包 VS 自己來

一件事情交在你手上,你該自己做?還是請別人做?
「事必躬親」、「學有專攻」、「萬夫莫敵、不下呂布」、「運籌帷幄、決勝千里」,不管決定是什麼,我想都可以有一個很漂亮的說法。

近半年也常常聽到:
「一個人力量有限、尋求資源是必要的」
「我們掌握關鍵,次要的交出去」
「規劃、溝通、統整、協調才是大器的工程師」

聽起來都好有道理,也確實很多事情好像不應該自己做,交代出去是一個好的方法,

所以,怎麼樣你會想外包?想尋求外面廠商的協助?

不會做:這東西公司沒人會外包吧
很會做:這東西以前做太多了外包吧
沒時間做:這數量太大了,沒時間做外包吧
太多時間:時間珍貴,你可以管更多的案子,這個外包吧
沒人力:沒人可以負責這部分,外包吧
有人力:人多的案子問題都很多,自動就外包了
沒經費:這自己做要花很多錢,請專業的做咖好
有經費:這案子經費多,這部分就請別人做吧

這一年來也大概聽了很多類似上面的話,所以怎麼樣的案子應該自己做?
就是,有點會但是又不常做,有時間但又不太空,
有人做但又要加班、不賠錢又不賺錢的案子嗎?

約莫半年前有人說:外包這件事情是要訓練的
兩周前有人說:我說真的,你這樣認真寫又能怎麼樣

其實,我也覺得他們說的都好對,但根本上覺得自己沒這能力。

今天聽到一個我認為很厲害的人說:我們都是外包的
「那為什麼你們還要看新技術?」
他回:因為我們不想被唬,我們提供更好的的做法跟架構給外包廠商。
更好的架構跟做法?意味著他自大,抑或是他們所知遠凌駕於其他人,
但我相信是後者。

這就回到公司或是部門的定位,
是一個轉手賺錢、不顧未來的外包機器人,
還是希望前瞻規劃、永續經營的開創者,

若是後者,那更龐大的知識、更多實際執行的經驗、更堅強的團隊向心力,才是支援你"可以外包"的力量,

浮木可以救急,但上岸踏實的實現才是一切的根本。

2010年11月23日 星期二

asp.net_callback機制_實作簡單計算機

前陣子有稍微研究了一下Callback機制,來紀錄一下。

直接進入正題,如果要在asp.net網頁上實作Callback機制到底需要具備什麼?
1. 讓你的網頁具備Callback能力,也就是要告訴編譯器,本頁面有實作ICallbackEventHandler介面。

2. 而ICallbackEventHandler要動作,必須要實作兩個方法在頁面中,可以直接利用VS的功能讓他幫你實作。

3. 當你按下精靈時,他就會幫你實作兩個方法:RaiseCallbackEvent與GetCallbackResult。

4. 加上第三步所實作的RaiseCallbackEvent與GetCallbackResult外,要完成一個CallBack流程還需要另外兩個JavaScript,所以整體程式的架構是:

說明:
A. 完成一個CallBack功能必需具備上圖4個區塊。
B. 在頁面上面註冊啟動CallBack機制的JavaScript(語法:Page.ClientScript.GetCallbackEventReference),後面帶有四個參數,第一個為處理前端回呼的人,看起來通常是下this,也就是本頁;第二個為前端傳回的字串;第三個為CallBack結束後要呼叫的前端JavaScript;第四個類似一個標記,並不會參與邏輯處理,但回傳前端時會帶入,用於判斷何人傳回(不確定實際運用方法)。
C. 在上圖中,將B點的JavaScript註冊在按鈕事件,故按下鈕起動CallBack後,將會執行RaiseCallbackEvent方法內的邏輯,完成後會執行GetCallbackResult方法。因為上述流程,通常我們會使用一個全域變數,記載於RaiseCallbackEvent執行後的內容,於GetCallbackResult直接返回該變數。(全域變數為上圖第一區塊之AnswerCallback)
D. 執行GetCallbackResult後,將執行GetCallbackEventReference所註冊的前端JavaScript。(上圖ReceiveServerData)。
E. 而D點所提之JavaScript會收到兩個參數,第一個為CallBack的返回值,第二個為GetCallbackEventReference第四個參數。

所以,整理一次跑的流程:
1. 於Page_Load註冊一個CallBack的JavaScript於按鈕上。
2. 按下按鈕後,執行RaiseCallbackEvent,並將資訊存入全域變數AnswerCallback。
3. 完成RaiseCallbackEvent後,執行GetCallbackResult返回CallBack運算結果。
4. 執行前端JavaScript,顯示資訊於頁面上。

接下來進行實作,需求是,希望作一個簡單的計算程式,可以從頁面上輸入數字及計算符號(+-*/),經過CallBack機制返回計算結果。
頁面配置:

步驟1:宣告一個全域變數、組傳入字串、註冊GetCallbackEventReference於按鈕點擊事件上。

步驟2:拆解傳入字串,並將結果儲存於步驟1的全域變數中。

步驟3:將步驟2計算結果返回。

步驟4:依照步驟1GetCallbackEventReference第三參數之設定,執行前端相對應之JavaScript。


執行結果:


延伸:
有時候使用CallBack機制不是因為我們想要用,而是使用的元件需要用CallBack機制去呼叫,可以參考piggy:於ArcGIS Server實作ICallbackEventHandler,該篇以CallBack去呼叫ESRI ADF的地圖元件進行定位。

參考資料:
馬小玲點部落:ASP.NET AJAX(6)-CallBack
MIS2000:PostBack(回傳)與CallBack(回呼)的差別
AJAX魔法工廠:Client-CallBack非同步
My Program:ASP.NET CallBack實作

2010年11月22日 星期一

新人的Training與現任的交流

今晚,

師:像這些東西,我們就有整理起來Training新人用。
我:老師,你們都有對新人做Training喔?特別上一些課嗎?
師:對呀!對新人都有,還有另一個分享。
我:分享?
師:每個星期三跟五下午會做分享,每個人要準備課題來說。
師:而且都是直接用code來講,都要實做出範例,每次講完以後就會被說明的範例分享給大家。
師:然後會把這些東西都整理起來,放在一個函式庫,可以隨時取用。
我:......

約莫半年前,部門大概也有這類的構想,當然不是很奢侈的一星期兩次,光是一個月一次就很難做到,當然影響的層面有很多,從上至下,從長官到諸如我的小嫩咖都有問題,這件事情很快就失敗了,有人完全不支持、有人支持隨意的分享、有人支持要充分準備的認真分享;總之,風氣很難起來,或許很多人的心中覺得這是一件"麻煩的事情",長官更是冷眼旁觀。

騎車回家時覺得有些事情很奇妙,有時候我們花時間在一些正面但與工作無關的事情上,卻莫名其妙的讓工作產值增加了,就像是研究所花時間去運動,去研修有趣的課程,做論文的時間被壓縮,卻有著不可思議的進度。

之前看天下雜誌內「管理大師說的話」,裡面提到『葛史密斯:管理專業員工。專業人員主要是看領導者能提供什麼才能,而不是具備什麼才能:1.鼓舞工作熱忱、2.提供學習機會、3.珍惜員工時間、4.協助建立人脈。』,現在想想這句話很有意思,四點幾乎都跟學習、正面、開闊有關。

新人的訓練、現任員工的交流、內部外部的教育訓練,每件對員工成長的事情都會蔓延一種氣氛;閉上眼睛感受那個氛圍,有!恭喜你請追尋著他;沒有!就從保持自己、緩步前進開始吧~隨著往低流不會有心靈的踏實,甚或登峰的喜悅。

在污堙裡光還是會發亮,強弱罷了。

JQuery_呼叫後端服務(WebService)

前一陣子因為討論asp.net2.0的callback機制,就讓正巧對jQuery有興趣的我很好奇jQuery要怎麼樣跟後端連結,所以目標是:利用jQuery呼叫後端的WebService,並將回傳的資料結果顯示於頁面上。

先來看看要被呼叫的WebService作了哪些事情?

內容非常少,傳入兩個字串,延遲四秒後將傳入字串組起來,回傳UsrID說:SAY的字串回去。

接下來看看怎麼樣在jQuery呼叫WebSerivce?

1. 當然,要使用jQuery當然要先引入jQuery,這邊是使用1.4.3版。
2. 在頁面只放上一個按鈕(id="btn1"),以jQuery註冊按鈕的事件。
3. 接下來就是接服務的程式碼:

$('#btn1').click(function () {
$.ajax({
type: "POST",
dataType: "json",
url: "../WebService/WebService.asmx/myTest1",
contentType: "application/json; charset=utf-8",
data: "{UsrID:'ola', SAY:'jQuery接服務成功!好耶~'}",
success: function (response) {
alert(response.d); //檢視回傳的結果 DeBug用
},
error: function (xhr, ajaxOptions, thrownError) {
alert(xhr.status);
alert(thrownError);
}
});
});

需要注意的參數有三個:
1. url:輸入WebService的位置,並在後面加上要呼叫的方法名稱(本例方法名稱為myTest1)
2. data:本例使用Json的資料形式傳輸,注意文字須加單引號。
3. success:服務呼叫成功後,會執行的程式內容。
4. error:服務呼叫失敗會執行的程式內容。

執行結果就是當按下按鈕時,等待約略4秒會有一個alert。


為什麼測試要等待四秒?其實這跟最近作的專案有關,裡面有一個功能需要去搜尋需要檔案後,進行檔案壓縮打包的動作,所以目前的作法是,將打包成zip檔的動作寫成一個服務,利用jQuery去呼叫他,送出時會暫時不讓使用者再次點擊該鈕,等到打包服務完成後才會恢復該按鈕為可按。

2010年11月21日 星期日

Android筆記_文字方塊(EditText)檢查電子郵件(Email)

第二次課程的作業總共有三個:
1. 不同Package切換Activity(可參考ola文piggy詳細步驟文)
2. 使用Thread實作倒數機制(可參考)
3. 製作輸入方塊Email檢查器(也就是本篇)

需求是:
1. 在文字方塊(EditText),輸入文字。
2. 若是符合電子郵件格式就顯示輸入正確。
3. 若不符合則顯示請輸入正確格式。

來看看程式碼:
1. 若要在EditText輸入過程中去監看每次輸入的內容,要使用txt1.setOnKeyListener。
2. 判斷Email可以使用Linkify.addLinks(文字內容,Linkify.EMAIL_ADDRESSES)←boolean。
3. 若Linkify.EMAIL_ADDRESSES傳回true則顯示"輸入正確",並將mail資訊顯示在lab2讓使用者方便點選。
4. 若Linkify.EMAIL_ADDRESSES為false,則顯示"請完整輸入Mail"。

運作畫面:

程式碼:

package ola.OlaTeach_emailcheck;

import android.app.Activity;
import android.os.Bundle;
import android.text.util.Linkify;
import android.view.KeyEvent;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

public class OlaTeach_emailcheck extends Activity {
/** Called when the activity is first created. */

EditText txt1;
TextView lab1;
TextView lab2;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

txt1 = (EditText) OlaTeach_emailcheck.this.findViewById(R.id.txt1);
lab1 = (TextView) OlaTeach_emailcheck.this.findViewById(R.id.lab1);
lab2 = (TextView) OlaTeach_emailcheck.this.findViewById(R.id.lab2);

txt1.setOnKeyListener(new EditText.OnKeyListener(){

@Override
public boolean onKey(View arg0, int arg1, KeyEvent arg2) {
// TODO Auto-generated method stub
if (Linkify.addLinks(txt1.getText(), Linkify.EMAIL_ADDRESSES))
{
lab1.setText("輸入正確");
lab2.setText(txt1.getText());
}
else
{
lab1.setText("請完整輸入Mail");
}
return false;
}
});
}
}


另外,Linkify.addLinks判斷電子郵件是:Linkify.EMAIL_ADDRESSESLinkify
網址則是:WEB_URLS
電話則是:Linkify.PHONE_NUMBERS
若要同時判斷可以使用破折號分開。

又如果只是需要自動判斷TextView的內容是否是電子郵件、電話或網址,則可於layout定義android:autoLink="webphoneemail"

2010年11月19日 星期五

Android筆記_Thread的使用

Thread?Thread是什麼?之前沒有使用過,問問維基百科,他說:線程是計算機科學中的一個術語。指運行中的程序的調度單位。一個線程指的是進程中一個單一順序的控制流。也被稱為輕量進程(lightweight processes)。它是系統獨立調度和分派的基本單位。同一進程中的多個線程將共享該進程中的全部系統資源,比如文件描述符和信號處理等等。 一個進程可以有很多線程,每個線程并行執行不同的任務。

所以意思就是當主程式在進行時,同時又需要去執行別的任務,就可以另起一個Thread(線程),將要執行的內容在背後運作,等到執行完成後,再把結果秀出來。

而在網路上有提到於Android於Thread有一個重要的限制「Android為了考量安全性和執行效能,不允許副執行緒直接更改主畫面的資料」,也就是說在我們另起的Thread都沒辦法做出如:將畫面變色與改變文字內容等畫面上的行為,而解決方法就是利用"Handler"來做溝通的橋樑。所以整個流程是:
1. 主執行緒開始執行。
2. 需要Thread(副執行緒)運行比較久的程序,開始執行Thread。
3. Thread於背景執行(通常附帶時間控管,如Thread.sleep(1000);)
4. Thread完成,傳送訊息告知Handler。
5. 執行Handler內的邏輯程式,改變畫面內容。



接下來就實作Android課程的作業,題目是:在畫面上安排一個文字方塊(TextView)與按鈕(Button),當按下按鈕後,會進行倒數,並且將按鈕設定為不可按(setEnabled(false)),最後倒數結束後恢復按鈕,並且顯示"時間到"。

老師提示這個功能要利用Thread來進行,所以最後完成的程式流程是:
1. 定義全域變數。
2. 在onCreate()內,註冊按鈕按下的監聽(btn0.setOnClickListener)。
3. 在onClick()中,執行副執行緒(thread.start();),並將按鈕設定為不可按(btn0.setEnabled(false);)。
4. 執行thread的run()函式。

5. run()函式執行完畢後,送出訊息(handler.sendEmptyMessage),主程序若有Handler,則會攔截到該訊息(可於Handler內由Message判斷哪一個Thread送出,以執行不同的內容)。
6. 進行時間倒數的邏輯程式,並將倒數結果放置到畫面中(lab1.setText)。
7. 若是尚未倒數到零,則再次執行thread,若小於零則將按鈕改為可按,並顯示"時間到"。


在第4步驟發送訊息也可以定義Message的what來傳送:
Message message=new Message();
message.what=1;
handler.sendMessage(message);//發送消息

最後看一下執行畫面:

完整程式碼:

package ola.OlaTeach_RunThread;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class OlaTeach_RunThread extends Activity implements Runnable {
/** Called when the activity is first created. */

public int Count_i;
Thread thread;
Button btn0;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

OlaTeach_RunThread.this.setContentView(R.layout.main);
btn0 = (Button) OlaTeach_RunThread.this.findViewById(R.id.btn1);

btn0.setOnClickListener(new Button.OnClickListener(){
@Override
public void onClick(View v) {
btn0.setEnabled(false);
EditText txt1 = (EditText) OlaTeach_RunThread.this.findViewById(R.id.txt1);
Count_i=Integer.parseInt(txt1.getText().toString());
thread = new Thread(OlaTeach_RunThread.this);
thread.start();
}
});
}

private Handler handler = new Handler(){

@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
TextView lab1 = (TextView) OlaTeach_RunThread.this.findViewById(R.id.lab1);
Count_i--;
lab1.setText(String.valueOf(Count_i));
Button btn0 = (Button) OlaTeach_RunThread.this.findViewById(R.id.btn1);

if (Count_i<=0)
{
lab1.setText("時間到");
btn0.setEnabled(true);
}
else
{
thread = new Thread(OlaTeach_RunThread.this);
thread.start();
}
}
};

@Override
public void run() {
// TODO Auto-generated method stub
try {
Thread.sleep(1000);

Message message=new Message();
message.what=1;
handler.sendMessage(message);//發送消息


//handler.sendEmptyMessage(0);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

2010年11月18日 星期四

Android筆記_Activity切換頁面

我們的程式應該不太可能只由一個Activity就完成,所以就必須要學會Activity的相互切換,要達到頁面切換的方式有兩種:
1. 直接換原本Activity的layout
2. 利用intent.setClass,並執行這個intent來達成兩個Activity的切換
* 除了呼叫同一Package的Activity以外,也有可能呼叫不同Package的Activity。

所以開啟專案,來看看這三種狀況怎麼做!

先來看看專案的架構,因為要做三種狀況,所以總共開啟了3隻繼承Activity的Class,並將其中一隻放到不同的Package中;而在Layout方面則準備四個Layout。

所以要達成的功能是:
1. OlaTeach_Activity1擺上三顆按鈕,先使用main.xml Layout。
2. 第一顆鈕將OlaTeach_Activity1的Layout換成main2.xml。
3. 第二顆鈕將OlaTeach_Activity1轉到同Package的OlaTeach_Activity2。
4. 第四顆鈕將OlaTeach_Activity1轉到不同Package的OlaTeach_Activity3。
先來看主要的程式碼:

1. 利用findViewById將三顆按鈕抓到,並都去監聽OnClickListener事件。
2. 第一個按鈕利用setContentView(R.layout.main2);將layout轉到main2。
3. 第二個按鈕利用intent.setClass後,執行startActivity(intent),呼叫另一個Activity
4. 第二個按鈕也利用intent.setClass後,執行startActivity(intent),呼叫另一個Activity,但此處因需呼叫不同Package的Activity,所以setClass的參數有點點不一樣,必須要給包含Package的class全名。


最後來看一下AndroidManifest.xml的配置:

可以看出來,因為使用了三個Activity,所以檔案中有三個Activity的定義,需要注意的是,OlaTeach_Activity3為不同Package的Activity,所以android:name必須給全名,也就是android:name="ola.Package2.OlaTeach_Activity3",這樣才可以正常呼叫到。

註:第一種轉換頁面的方法,原本以為只是向CSS一樣套上另一個皮,裡面寫的方法應該都可以在變換Layout後使用,後來發現當換了Layout之後,必須重新再去取得按鈕物件,並加入OnClickListener才可以正常使用。

如果需要操作步驟,可以參考piggy的文章,寫的非常詳細!

Android筆記_Activity生命週期

Android的應用程式有四大區塊:
1. Activity
2. Service
3. Broadcast receiver
4. Content provider

在課程的前兩堂都在說明"Activity",某個老師曾經說過:「大廠不會亂取名字」,所以Activity[活動]意思是處理與使用者"活動"相關的部份,也就是互動方面,所以就是「UI介面的處理」。

所以若是希望使用者可以"看到"並與其"互動"的功能,就必須要實作一個繼承Acticity的Class。而Activity最先必須要了解的就是生命週期。

有幾點必須要記載的:
1. 在Activity啟動時,會有三個方法被執行OnCreate()→OnStart()→OnResume(),到OnResume()執行完成後,Activity即會依照配置呈現在手機上面。
2. 當Activity被關閉時,也會有三個方法執行OnPause()→OnStop()→OnDestroy()。
3. 手機畫面一次只會呈現一個Activity,當有其他的Actvity被呼叫,目前的將會失焦(執行OnPause());所以若是自己開發的程式,必須要在OnPause()做處理(比如說遊戲程式失焦時先暫停遊戲),避免像是電話打來時遊戲角色失敗的窘境。

當我們開啟新的專案,Eclipse會將一些基本的檔案準備好,開啟Class.java檔案,就可以看到以下程式碼:

程式碼的意思是:
1. OlaTeach_Activity1這個Class繼承Activity,並且覆寫了onCreate這個方法
2. 在onCreate()這個方法裡面,使用setContentView(R.layout.main)指定這個Class的ContentView要依照res/layout/main.xml呈現。

依照剛剛所說明的生命週期,所以在這裡我們把setContentView這句移到OnStart()或是OnResume()都可以正確的顯示出View;但如果我們放在OnResume()內,就會變成每次失焦(OnPause)又取得焦點(OnResume)時,都會不斷的設定該Activity的ContentView。

Android筆記_GO

遙想今年6月4日發了一篇願望,前陣子也自己跑去報了一個Android的入門課,雖然聽完是懵懵懂懂、腦袋白白,但又好像暨之前的MapGuide+Flex的圖台開發後,又有一件有趣的事情。這次在同事勇敢闖關下,終獲"擬同意"三字,也有了逼迫自己跟手機說聲HI的機會。

說起來很窘,之前去上課多多少少有著一些底子,而這次真的就是嶄新的開始,老師課程安排的相當充實,還不斷的出回家作業,國小老師跟我們說:「上課預習、下課複習、勤作筆記、確實實作」真是到了現在還是非常需要。

所以,開始寫Android的實作筆記吧~~~

2010年11月16日 星期二

JAVA_一些非常基本的字串操作與轉型語法記載

字串比較:IDstring.equals("ola") (IDstring是否等於ola)

轉型為字串:String Value = String.valueOf(intnum);

字串轉整數:int intValue = Integer.parseInt("123");

字串轉浮點:float floatValue = Float.parseFloat("123.123");

字串轉雙浮點:double doubleValue = Double.parseDouble(SDouble);

浮點轉整數:(int)(Double.parseDouble(Answer[0]));

切割字串:String.substring(0, 2) [abcd→ab]

split:String[] Answer = 要分的字串.split(",");

只有一個想法,實在是太弱了。 orz

2010年11月13日 星期六

玩SC2 想專案

加了好久的班,今天偷閒玩了一下午的星海爭霸二,打來打去都不順,沒偵查好、沒轉兵、沒集火、開礦也不順,這也沒什麼,就是苦了隊友...趕快下一場吧~~~

之前覺得魔獸就像是一個公司,裡面充滿了許許多多跟公司相同的事情,像是有沒有把正確的職業分他做正確的工作、有沒有公平的分裝(紅)制度之類這種公會治理、帶團打副本的事情,總是可以在平常生活中找到類似的事情。

所以剛剛休息之際,想起近來執行的案子,就覺得如果說魔獸像公司,而星海就像是一個個專案,操作固定的三種種族,玩出不同的打法,每一場都會有不同的結果;同樣的功能,同樣的需求、同樣的呈現方式,業主給你的反應也是大不相同,有的業主要好看、有的要功能強、有的只專注在枝微末節的小地方。

所以我們理應在各個時期做好偵查,生出對應的兵種,適時的開出分礦調整我們的火力,給對手重重一擊;知道業主希望頁面好看,就要花時間在美編上,知道業主著重功能動態且互動良好,就要花時間在程式邏輯上;如果你執行的案子,功能繁多、邏輯複雜、頁面要好看,而且一次要應付三種不同需求的承辦,那就代表你必須點點地圖,呼叫你的同伴。

而你的玩伴,就像是你的同事、你的長官,適時的援手可以讓你多活一下,有時候就順著推過去了,但是往往大家不是一條心,通常都是戰到一兵一卒,很狐疑的將地圖移到隊友家,才發現他在龜戰巡艦、虛空艇、航空母艦,他有可能以拯救者之姿橫掃整個地圖,最後讓你很幹的獲得勝利,或是?很快的被滅掉,然後跟你說都是你的錯?

我有一段時間常常聽到一句話「當我出手的時候,就怎麼樣怎麼樣...」,我想他在龜戰巡艦吧,只是不希望他奢望一隻就想打倒排山倒海的陸戰隊。

--------------------------------------------------------

星海有一個非常有趣的事情,就是當開始打團戰的時候,如果有人離開遊戲,這個戰績不論輸贏都還是會算在跳離的人身上,這點也很專案非常類似,打開服務建議書,很好!有25個隊友,一進入遊戲,「官等24個人離開遊戲」;戰勝!當然,我們25個人齊心協力,戰敗!離開的也被記上一筆,但他們會說「都是玩的人太弱~~~~」(笑)


那現在處於什麼情況?我跟我的隊友選了人類,在玩一場以前是12個人玩的遊戲,現在主堡飛在空中,下面滿滿的小狗跟蟑螂,遠遠的看到對手建立了飛螳塔。(攤手)

2010年11月9日 星期二

人生在追趕倒數與等待倒數中輪動

「這是預產期,記得平常要做呼吸運動喔~~」
「等到上幼稚園就有很多新朋友囉」
「生日蛋糕要生日那天才可以買喔」
「剩1分鐘,好~~~停筆,從後面收上來」
「明天放榜,有把握嗎?」
「電影5分鐘後開始囉,趕快進場」
「1分鐘後,著整齊服裝,帶水壺、椅子,集合場上成講話隊形...55..54」
「明天退伍了,工作找了嗎?」
「打卡差一秒.....」
「這案子剩1個月,期程都OK嗎?」
「(發呆~~~)」
「剩50秒可以拍,拍到29秒耶,快收起來要綠燈了~~」

太多的追趕與等待,不要矇蔽你的心;願,等待美好的事物,追趕心中的踏實。

2010年11月7日 星期日

Oracle_資料匯出及匯入(以使用Oracle Spatial的專案說明)

雖然是基本功,但之前也是搞了好久才匯好,趁著今天又做一次紀錄一下。

如果你的系統所讀取的空間資料也是存在Oracle Spatial內,而在資料一值更改的情況下,我們就有可能要一值重複去業主那邊匯資料的步驟。在之前剛剛就是在說明這些步驟的流程,所以综合來說從原始資料取得到系統更新上線,"匯資料"這件事情要做什麼:

1. 確認圖資的資料型態符合欲匯入資料庫的格式(可參考)
2. 將所得到的SHP檔案,利用Autodesk Map 3D匯入Oracle Spatial(可參考)
3. 將已匯入Oracle的空間資料匯出成.DMP檔案。(本篇下述)
4. 將DMP攜至業主機器匯入。

所以本篇的重點就是資料匯出、匯入的操作流程:
1. 於cmd.exe底下輸入 "exp 帳號@服務名稱"(帳號即為具有匯出資料權限之使用者帳號,服務名稱則為NetManage內所取之服務識別)
2. 輸入密碼後會出現以下畫面:

A. 緩衝區(4096)
B. 匯出檔案:自行變更(檔名.DMP)
C. 選擇要匯出使用者(U)還是表格(T) (預設值為使用者[U])
D. 匯出授權(Yes)
E. 匯出表格資料(Yes)
F. 壓縮擴充區塊(Yes)
G. 要匯出的使用者:自行輸入
也就是問你匯出的內容與一些基本設定,要變更的只有兩個地方,第一個是C項(如果要匯出該使用者的全部表格就不變,特定表格就選T),第二個是G項(如果C項選使用者就輸入要匯出的使用者名稱,如果選表格則輸入表格名稱),完成後程式即會匯出需要的表格資料。
3. 如果cmd是在C:底下輸入,就可以在C槽根目錄找到你的.DMP檔案。

接下來就是至業主的匯入工作。
1. 於cmd.exe底下輸入 "imp 帳號@服務名稱"
2. 輸入密碼後會出現以下畫面:

A. 緩衝區大小不動(30720)
B. 僅列出匯入檔內容(NO)
C. 物件已存在,建立的物件錯誤被略過不予處理(NO)
D. 匯入授權(Yes)
E. 匯入表格資料(Yes)
F. 匯入整個匯出檔(NO)
G. 使用者名稱:(自行輸入)
H. 輸入表格名稱:(自行輸入)
要輸入的也是兩個地方,G項與H項,一個是輸入要匯出的使用者名稱,另一個是輸入要匯入的表格(要指定匯入特定表格於F項應輸入NO)。

當然,以上的方式對於整批更新相當方便,但如果業主已經對資料編修了,就要小心覆蓋了。

ArcMap_如何將圖資屬性套入新的資料類型

當我們想把SHP檔匯入Oracle Spatial時,有可能會發生一個問題:「為什麼匯進去的資料進位有問題?」,明明在SHP顯示0.95,到了Oracle Spatial的時候卻變成了9?

如果你也發生一樣的問題,我想你應該是使用Autodesk Map 3D 2009進行資料匯入Oracle Spatial吧?總之,原因是資料型態的問題,如果使用float在轉換過程中會出現進位問題(忘記是Map 3D讀進來就錯了?還是轉出去才錯),而解決方法就是必須要將該欄的資料格式轉成可以正確轉換的格式,例如double。

除了以上狀況,或許還有很多時候,你必須要大量的改變資料型態,如果只是需要做一次也就算了,但是資料匯入這種工作,總是不斷的不斷的要做,所以在原始產出資料無法改變的情況下,我們要如何快速的把多個欄位的資料類型進行改變呢?

流程:
0. 準備好一個空的且欄位資料型態皆正確的SHP檔(以下稱空框架)。

1. 打開你的ArcMap,開啟ArcToolBox,搜尋Merge指令。

2.開啟該功能,在Input Datasets先選擇你的空框架,再選擇你要轉入的檔案。

3. 比對在各欄所對應的資料是否符合?

4. 例如你想將Float改為Double(可以看到圖上,就是以Double去接Float的值)

5. 去注意那些只有一項資料的欄位,確認應該刪除還是保留(刪除即在完成的資料中不會有該欄,保留即創見該欄並保留資料。)

6. 按下OK,就可以獲得一份資料格式符合的檔案。

當然,你也可以把這個流程寫成一個Model。

2010年11月5日 星期五

jQuery_抓取下拉式選單的值(asp.net DropDownList)

jQuery有很棒的Selectors可以很快速的抓到頁面上的東西,那要怎麼抓取下拉式選單的值呢?網路上有很多文章在說明抓取的方法,也就是:

var selected = $("#ddl_City option:selected");
alert(selected.val());

所以當我們有一個下拉選單,希望按鈕以後alert選單的值,就是:

function GetValue() {
$(function () {
var selected = $("#ddl_City option:selected");
alert(selected.val());
});
}
<input id="btn" type="button" onclick="GetValue()">

但如果是asp.net的使用者,通常都會使用主版頁面,這樣就會導致我們的ID為ddl_City的下拉式選單輸出到頁面上以後變成類似"ctl00_ContentPlaceHolder1_ddl_City"的ID,簡單的解法有兩個,一個就是不管他,直接用輸出的長ID來抓:

var selected = $("#ctl00_ContentPlaceHolder1_ddl_City option:selected");

或是改為使用JS的方法抓:

document.getElementById('<% =ddl_City.ClientID%>').value;

如果你覺得非得徹底解決,可以參考黑暗執行緒blog的文章

2010年11月2日 星期二

asp.net_DataView怎麼取值?(使用index或欄位名稱)

DataView是在撰寫asp.net與資料庫連結時很常使用的資料型態,原因不外乎有許多現成的元件都可以直接繫結,而我們在使用時大概分成四個步驟:1.組SQL語法、2.利用某種DataSource(或許可以說就是SqlDataSource,不管是拉到頁面上還是寫在程式內)、3.將取回的資料放進DataView、4.資料繫結。

而當我們需要把DataView的資料取出來做一些簡單的計算,或是放到特定的地方時,通常會使用
dv.Table.Rows(0).Item(0).ToString()
來取出行列index都是0的資料,如果我們只是為了列出資料,可以利用迴圈很快的列出所有資料,但是當要把每一個欄位值都放到特定位置時(比如編輯介面抓取舊有資料到textbox上),這樣就變得有點麻煩,因為這個index變得要跟SQL內的順序去比對,你也不會一值記得第29欄是誰?

所以或許我們會做點簡單的注解,讓之後程式碼比較好閱讀。

dv.Table.Rows(0).Item(0).ToString() '案件編號

想像一個情況,撈出一筆資料,他擁有50個欄位,都依照上面方式獲得值,而且擺放好了;這時候突然發現需要多增加兩個欄位,而又因為這兩欄與現有某個欄位相關,你希望插到資料庫的第15、16欄,那麼程式碼是該將這兩欄也一併放在序列15、16,還是乾脆放在51、52序列勒?

通常這種狀況,我都會希望自己的程式碼跟資料庫有對應,所以就會重新調整序列(呆~~~)

說了一堆,終於要進入本篇的重點,上面這個情況有沒有更好的辦法?
DataView在取資料時,除了可以利用index的方式抓取,也可以直接輸入欄位名稱,就像是:

dv.Table.Rows(i).Item("PrjID").ToString() '案件編號

而在C#裡面有些許不同:

dv.Table.Rows[i]["PrjID"].ToString()

所以結論相當簡單,當你需要跑迴圈,當然要用index,如果沒有迴圈的需求,為了未來修改時降低困擾增加可讀性,可以直接寫欄位名稱。

2010年11月1日 星期一

201008宜蘭行_day2_白米木屐村

本來白米木屐村,並沒有在行程當中,因為很多年前去過一次,當時那邊只有兩間類似工寮的房子,裡面掛滿了木屐,然後外面有幾雙可以多人一起穿的大木屐,因為想著或許可以買雙木屐回來穿所以還是去了~~~

白米木屐村資訊(http://www.lanyangnet.com.tw/ilmuseums/html/link26main.htm
)
.參觀時間:08:00-17:30(週二~週日,需預約)
.休館日:每週一(暑假期間不休館)
.地址:宜蘭縣蘇澳鎮永春路174號
.電話:03-9952653.傳真:03-9951273

騎在蘇澳鎮永春路的路上,嘉嘉問我「是前面那個嗎?有遊覽車」我回:「不是吧!這很大棟耶~~~」,沒錯!白米木屐村進化了,他從原本兩間小小的工寮,變成一整大棟,聽解說員介紹「我們是在原本的房子上以鋼骨繼續往上加蓋,現在有三層樓」,正當我想找入口進去參觀才注意到這個牌子:

你沒有看錯,現在木屐村的參觀導覽已經要預約了!(不禁對白米村的村民致敬),抬頭看看預約的場次,可以說是滿滿滿。(所以預約完以後,我們就去吃永豐海鮮+海邊寫字了)

整個白米木屐村大概可以分為三個部份:第一個當然就是預約導覽、第二個是目前主建物的旁邊跟後面各有一家賣紀念品(非木屐紀念品)的商家在營業,第三個就是....外面的小吃攤販。XD

而導覽時間到了以後,他會分批帶遊客進去,整個過程大概分為三個部份:
1. 影片導覽:介紹百米木屐村與木屐。
2. 木屐製作:木屐的裁切(可體驗刨光)、加工(雕刻、渲染與電繪),皆會有師父當場示範給大家看,而加工部份就有許多搶答可以獲得一些小腳丫,或是可以直接與他們購買已經完成的一些木屐裝飾品。
3. 特殊木屐體驗:在介紹過程中,他提到的一些特殊木屐都可以在這邊體驗,例如罰站木屐、減肥木屐、按摩木屐等。

其實我們在第二站木屐製作介紹就有點脫離隊伍了,因為我們想把lao刻在小腳ㄚ上:
解說員:如果想把自己的圖騰刻在這腳ㄚ造型吊飾的人可以問問看師父,其他人往下一站。
嘉嘉拿出像機,找到lao的相片
嘉嘉:這個可以刻嗎?
雕刻大師露出難色,「這個雕出來不好看吧,用畫的好了」
「你幫他們選個好板子押」雕刻大師對著媽媽解說員說
啪搭啪搭,媽媽解說員翻著空白的腳ㄚ吊飾「就這個吧!這塊是這邊最好的!」

這時,媽媽解說員帶我們來到傳說中技術很好的電繪師前「他們要畫這個」
「好~~~」
她很快的就定位,開始用鉛筆構圖,拿起電繪筆,開始~~~滋滋~~~
我(小聲)「不錯耶」
嘉「對呀!」
我(小聲)「好像畫好了,你看,他在做什麼...畫皺折耶~~~」
我(小聲)「如果他連"8"都寫上去,我就太佩服她了~~~」
就在這時候"她"寫了一個8。XD
↑為什麼都沒有照片?因為這時候他一邊看相機一邊畫 = =

成品:

超級比一比:

嘉嘉跟超利害電繪師:

所以,如果你有要來,也預備要買這個腳ㄚ,可以先想一下你要刻什麼?或是要畫什麼?會比買他們已經做好的要有趣又有意義。

一出白米木屐村的主建物,我就看到了一個我一值很想玩的東西!大泡泡!從下面的照片量就可以看出我玩了多久~~~~~XD


所以,整體來說,我覺得白米木屐村現在算是一個很值得排的行程,也很有在經營,感受的到村民的努力!

201008宜蘭行_day2_蘇澳南安國中操場外海灘

跟孔子短暫會面後,我們決定加緊今日的蘇澳行程。


遙想還在宜蘭讀書的時候,這也算是一個在地人景點,通常旅遊團或是來玩的人,都會去吃海鮮,然後到另一個小有規劃的礁岩看海區(我忘記名稱了),每次來到這個海灘總是奚奚落落沒什麼人;此次當然不是這樣!才剛接近南安校園,就看到攤販林立,花生捲冰、一串心、考魷魚、龍鳳腿,總之,就是小吃類都來一攤就對了,轉頭看看另一邊,就是一台台的遊覽車,變成了一個很觀光的地方。

到海邊可以做什麼?看海、吹海風、追浪、跑給浪追、打水飄,實在是也老了,又這是一場吃吃喝喝的知性之旅,所以我決定要..."寫字"。而嘉嘉看到字以後就爆氣了!


2011畢業!

嘉嘉,爆氣了,我當然也要...

說來奇怪,「2011畢業」一下就寫好了,「發財」寫了超久的....囧....

最後,當然要來許一下兩個人一起的願~~~~

總體來說,如果不追浪、不給浪追、不寫字、不打水飄、光坐在防波提上看海、吹海風、吃小吃、聊天,我也覺得這邊還不錯!
(只是垃圾記得帶走就是了,防波提前都是被浪打上來的垃圾 /.\)