2010年12月24日 星期五

MapGuide_MapGuide Enterprise 2010 Update2 with WinServer2008

俗話說的好「不更新沒事,沒事不要亂更新」,但是為了"企圖"解決Invalid stream header的問題也只好硬上了。(挺)

昨日先在自家機器(WinServer2003)上測試更新,完全無痛更新,正常關閉程式、正常關閉服務,點完三個更新檔,重啟服務,一切正常到我懷疑他沒更新。到了業主機房就覺得空氣中彌漫著一股"會待很久的FU"。

情境:
1. Win Server2008
2. MapGuide Enterprise2010
3. 預備更新到SP2

情況:
1. 更新WebServerExtensions時"變得"需要安裝光碟,看起來是有遺失檔案?
2. MapGuide studio執行即顯示程式錯誤,被Windows強制關閉。
3. 更新完成後,MapGuide服務正常啟動,但是圖台框架無法正常執行。

解法:
1. 跳出需要檔案時,指向WebServerExtensions的SETUP.ISM。(很簡單,但是很謎,讓我覺得後面還會出大事情。)
2. 重新指定MapGuide studio使用32bit來執行(方法)
3. 重開機,重新依照
a. 關閉MapGuide Enterprise 2010 Server服務
b. 關閉MGE 2010 Service(license服務)
c. 關閉World Wide Web Publishing Service
d. 關閉IIS Admin Service
e. 開啟IIS Admin Service
f. 開啟World Wide Web Publishing Service
g. 開啟MGE 2010 Service(license服務)
h. 開啟MapGuide Enterprise 2010 Server服務
也就是手動正常停止服務,再手動正常的啟動服務。

查資料的過程MapGuide2010感覺還是針對Win Server2003,32bit的環境去開發測試的,似乎Win Server2008還是應該要搭配MapGuide2011版本。

------------------
我的青醬比薩 T.T

2010年12月23日 星期四

MapGuide_2010版出現Invalid stream header exception

最近接連遇到兩台MapGuide伺服器產生『Invalid stream header exception』的錯誤,而發生這個狀況的程式碼竟然是在"site.Open(userInfo)",也就是說嘗試要去連接MapGuide的時候就出現錯誤了,所以不太可能是因為程式的問題,而在重開機以後也恢復了正常。

而今天又突然發生一樣的錯誤,如果去Google『MapGuide Invalid stream header exception』會查到一些類似的描述,意思是:有些情況會造成"某個東西"無法釋放,最後產生這個資料流檔頭異常的狀況。

看起來的解決方法是:
1. 去釋放那些執行緒
2. 更新MapGuide(更新檔哪裡找?)

更新檔的說明文件裡(http://images.autodesk.com/adsk/files/AutodeskMapGuideUpdate2Readme.pdf),其中有一項修訂是:(1219841.01) TCP/IP connections were not always being released and
occasional invalid stream header errors occurred,所以看起來在MapGuide2010第二版的更新中已經修正了這個問題。

如果本篇沒有被移除,表示我更新後沒有再遇到相同的問題,請安心服用。

MapGuide_更新檔哪裡找?

什麼樣的軟體、遊戲,都很難在內部測試就知道所有的問題,遊戲常常會來個封測,然後在公測,最後才是正式上線,但是對於軟體好像就沒有,尤其是越專業的軟體,越不容易被取代的時候,他們總是推出一些"經過嚴密測試,但是還是有很多問題的產品",就跟我們接專案,也是"經過嚴密測試,但是還是交出『極可能』有些問題的系統",當然問題很多,比如自己就是測試人員、時程只以專案期間為考量、人力只以現有人月來考量之類的。一不小心就開始碎碎念了。

有些廠商會做線上更新,只要使用者連上線就可以更新到最新版本,有些則沒有,需要使用者自己去注意有沒有新的更新檔上線了。而通常會去看有沒有更新檔,通常都是遇到無法解決的問題,最終歸類該問題是軟體本身的臭蟲。

所以,最近遇到了MapGuide Enterpirse 2010版的問題,覺得是MapGuide本身的問題,所以開始找更新檔,結果....好難找。

為了讓自己下次快點找到,記載一下:
1. 連到官方網站(http://usa.autodesk.com),台灣歐特克我是沒看到任何相關資訊。
2. 選取Support的Support & Documentation。

3. 進入後,點選下標的一項Service Packs & Downloads。

4. 進入後,會看到很多軟體的圖示,不用找,因為MapGuide是屬於小小眾市場,直接到最下面的下拉式選單。

5. 接下來點選Updates & Service Packs囉。

6. 然後就看到超想下載的更新檔一堆!


更新檔位置(http://usa.autodesk.com/adsk/servlet/ps/dl/index?siteID=123112&id=2334435&linkID=9242179),或許哪天他的連接ID會變,就自己找一下囉。

目前MapGuide2010版的更新是出到第二版,前面歷經1版及1b版,因為2011已經上市了,之後2010應該也不會再出。看看2011已經出第一版更新了,XD。

2010年12月15日 星期三

Android筆記_如何申請Google Map API Key(模擬器用)

本來12月1日很開心的發了一篇文章,想說12月要有好的開始,認真的記載學習日誌,沒想到又被報告、簡報、文件、教育訓練搞的頭腦頓頓的,今天抽空對之前的程式做一個小整理,才又驚覺已經15日了,雖無法過之前高點,也不能讓2010年最後一個月變低點,趕快發一下之前就截好圖的簡單記載。

--------本文----------

在Android開發中,『地圖』是很重要的一塊,許多以前幻想的功能,都可以跟著你的行動裝置進而實現,以往GPS+地圖最常想到的都是導航、巡覽等等的事情,而設備通常不是一般大眾會去買或是會去擁有的,但現在GPS已經變成行動裝置,或是說智慧型手機一個必備的設備之ㄧ。

若是提到地圖,當然就不能不提Android發啟者Google的Google Map了!

想要在手機上顯示Google Map,就必須要先有使用Google Map API的鑰匙,而這邊又分為兩種,一個是真的於手機上使用,另一個就是在模擬器中使用。

本篇主要記載如何在模擬器中使用,直接看步驟:
1. 先於Eclipse找到debug.keystore的位置(Eclipse→Windows→Preferences→Android→Build)


2. 執行cmd,找到Java的bin資料夾(若你也是使用XP,位置是:C:\Program Files\Java\jre6\bin)

3. 輸入取得MD5的指令,可以取得MD5的編碼。(以下C:\Documents and Settings\57237\.android\debug.keystore為第一步驟查到的路徑位置)

keytool -list -alias androiddebugkey -keystore "C:\Documents and Settings\57237\.android\debug.keystore"
-storepass android -keypass android


4. 進入Google Map API Key的申請網站(http://code.google.com/intl/zh-TW/android/maps-api-signup.html),並且輸入剛剛取得的MD5編碼。

5. 就可以取得Android Maps API的金鑰。

6. 將取得的Map API Key貼到com.google.android.maps.MapView的android:apiKey。

註:該金鑰是針對MD5編碼所產生的,所以要開發的電腦都必須要自行申請,使用別人的金鑰是無效的。

等買了手機就可以發一篇,如何申請Google Map API Key(實機用),XD。

2010年12月13日 星期一

Ola認為的基本功─了解戰友及部屬

我們這輩子從大概半歲開始就會接觸許多千奇古怪的人,

一開始是爸爸媽媽、然後親戚鄰居、再來是幼稚園的小朋友....

接著就開始過著所謂的群體生活....

幼稚園,小學、國中、高中、大學、研究所、工作....

在這當中,我們常常需要與別人合作達成一些目的,

幼稚園的積木城堡

小學的大隊接力

國中的籃球比賽

大學的社團活動

研究所的專題研究

工作上的各式專案

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

這些活動若是成功,通常都有一種人,並不特別厲害,但他懂大家..

「他是飛毛腿,給他第一棒!讓我們領先矛頭」

「他運球刁鑽視野又廣,讓他當控衛!」

「這個專題很奇特,你鬼才,可以給我一點意見嗎?」

所以,我以為每一個團體要能夠運作順暢、各安其命,

必須要有一個懂人的人,有時候我們稱他叫做領隊、團長或是長官。

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

說來困難、但又基本,懂得你的部屬,懂得你的戰友,

想想,如果你是教練,給你一支球隊,你第一件事情是什麼?

數數你有幾顆球?比對球衣的顏色?還是確認籃網有沒有破掉?

我想你的答案應該是『我要知道我的球隊有些什麼樣的"人才"』

當真的了解,才有可能在安排上妥適,在調度上自如,

在失去的時候,了解"真正"失去了什麼樣的"實質戰力",

並且了解影響層面的深度與廣度,

懂得恐懼也是實力的一部分。

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

現在,想想你的長官、同事及部屬,想想辦公室的所有人,

你可以細數每個人的"能力"嗎?

如果現在有一個專案,請你組出夢幻團隊,你確認適當的位子,放上適當的人了?

我想實情是,你根本不瞭解其他人的能耐,

而如果你連現在手上的牌都看不清楚,還能知道要補甚麼牌嗎?

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

我們常說無意比故意更恐怖,因為他連事情的重點都抓不到....

所以,自以為懂的懂更讓人覺得是一個笑話。

你今天笑了嗎?

2010年12月1日 星期三

Android筆記_聽Broadcast與發送Broadcast

在課程一開始就說明Android應用程式有四大區塊:
1. Activity
2. Broadcast receiver
3. Service
4. Content provider

上一堂課終於進入了第二個區塊,也就是Broadcast,廣播顧名思義就是"告訴大家這邊有事情發生"?

感覺就很像上面這張圖,手機會去告訴現在發生了什麼事情,比如說簡訊進來了、電話進來了,而發送廣播的源頭可以來自於手機本身,或是某一個自製的Activity,就像是可以發送一個"Ola Good"的廣播;有註冊接收的Activity就會產生相對的反應(手舉起來)~~~ \@o@/

有幾個重點:
1. Broadcast並不是對有去接收該事件的人發送,而是對整個手機進行發送,他沒有預設要發送給誰。
2. 我們除了可以去收手機本身定義的Broadcast,也可以自己發送自己的。
3. 如果註冊了要接收某個Broadcast,在沒有反註冊前都會不斷的接收,也不會進入GC(GarbageCollection)流程。
4. Broadcast可以由Activity發送,也可以由Service發送。

所以,要怎麼發送?註冊接收?取消接收(反註冊)?

發送:
傳送一個名為OLA_ON_SERVICE_001的Broadcast

String OLA_BROATCAST_STRING = "OLA_ON_SERVICE_001";
Intent i = new Intent(OLA_BROATCAST_STRING);
i.putExtra("STR_PARAM1", "廣播訊息");
sendBroadcast(i);


註冊接收:
註冊去接收OLA_ON_SERVICE_001。

String OLA_BROATCAST_STRING = "OLA_ON_SERVICE_001";
IntentFilter mFilter01 = new IntentFilter(OLA_BROATCAST_STRING);
mReceiver01 = new mBroadcastReceiver(); //←實作一個BroadcastReceiver來篩選
registerReceiver(mReceiver01, mFilter01);


反註冊接收:

unregisterReceiver(mReceiver01);


***大衛老師建議:在OnResume註冊、在OnPause反註冊。

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。