2011年10月25日 星期二

asp.net_圖片縮放_另存縮圖_Image Resize

有一類很普遍的應用:

我們可以藉由各種方式取得使用者上傳的的照片到File Server,而另一面則藉由網際網路以不同的介面來觀看這些上傳的圖片。而在這樣單純的應用裡,一值都有一個讓人關心的問題「使用者可以更快看到圖片嗎?」

然而,我們都瞭解想要更快的看到圖片,必須:
1. 有更大的頻寬
2. 有更小的圖片

頻寬通常不是我們所可以決定的,所以"更小且適當"的圖片將是我們希望的。

所以,我們要在一個恰當的時機,把圖片縮小:
1. 上傳圖片前─於使用者端先將圖片縮小後再上傳。
2. 上傳圖片時─使用者上傳原始大小,再於伺服器端另存出縮圖。
3. 下載圖片時─於使用者下載圖片時,另存縮圖讓使用者下載。
4. 下載圖片後─於圖片下載到使用者端後,再進行縮圖動作。

這樣非一般性的處理,通常要在'一次性'的操作來執行是比較恰當的,所以我們應該在上傳前或上傳時進行,但這牽扯到File Server是否要儲存原始圖片,若是答案是必須的,那麼我們只有一個最恰當的時間做縮圖這件事情→於上傳圖片到伺服器後,將其另存一份縮圖檔;至於縮圖需要縮到什麼程度,就必須要視看圖端的需求。


protected void ChangeImageSize(string FileName, string FilePath , int SmallWidth)
{
System.Drawing.Image img = System.Drawing.Image.FromFile(FilePath + FileName);
ImageFormat ThisFormat = img.RawFormat;
int FixWidth = SmallWidth;
int FixHeight = FixWidth * img.Height / img.Width;

Bitmap ImgOutput = new Bitmap(img, FixWidth, FixHeight);
ImgOutput.Save(FilePath + "small_" + FileName, ThisFormat);

img.Dispose();
ImgOutput.Dispose();
}

若以行動裝置目前的照相機,一張相片大約為1.5mb,在另存為640*480的圖片後約為47kb,對於顯示縮圖能夠達到很好的效果,也可以讓使用者介面操作起來更為順暢。

2011年10月21日 星期五

Android錯誤排除_Activity ActivityName has leaked window com.android.internal.policy.impl.PhoneWindow DecorView@40d0ad20 that was originally added here

有時候在關閉Android的Activity時,會跳出"Activity ActivityName has leaked window com.android.internal.policy.impl.PhoneWindow DecorView@40d0ad20 that was originally added here "這個錯誤訊息。

原因:有Dialog未關閉,但Activity就關閉了。

解決方法:在Activity結束時,呼叫dismiss()方法將其關閉。

@Override
protected void onDestroy() {
LoginProgressDialog.dismiss();
super.onDestroy();
}

Android錯誤排除_close() was never explicitly called on database

如果使用SQLite儲存資料,然後在除錯時都會去看log了話,就有可能看到一個錯誤訊息:"close() was never explicitly called on database"。

原因:開啟連線,但未關閉。

解決方法:
1. 於適當的地方呼叫SQLiteOpenHelper的close()方法。
2. 所謂適當的地方,也就是我們使用完的時候,通常是在Activity關閉時;所以可以複寫onDestroy方法,判斷SQLiteOpenHelper是否存在,若存在則將其關閉。

@Override
protected void onDestroy() {
super.onDestroy();
if (dbHelper != null)
{
dbHelper.close();
}
}

單一簽入(SingleSignOn)的簡單作法_Part3_自製單簽架構

如果你需要的單簽是,於A登入→關閉瀏覽器→開啟B則自動登入B,那可以換一篇文章了。

如果你需要的單簽是,於A登入→按下某鈕轉至B→並自動於B登入,或是於不同的介面(A、B系統、手持裝置等)使用同組帳密登入,那可以看一下

架構:

說明:
1. 在資料庫增加tokenInfo的表格,並且建立UserID、token、isActive與updatetime欄位。
2. 以WebService撰寫三個服務,分別為:
A. CreateToken:依照輸入的帳號、密碼產生token,並存入tokenInfo表內。
B. CheckToken:由傳入的token至表tokenInfo,以isActive與updatetime判斷是否有效,若有效傳回UserID,並且更新時間。
C. GetUserInfo:判斷token是否有效,若有效傳回所需的使用者資訊。

情境:
1. 打開A系統,輸入帳密以後,藉由CreateToken產生token,於A系統點擊B系統之超連結,並將該token值置於url參數,轉址至B系統;B系統於pageload去判斷是否有token,若有則利用CheckToken判斷token是否有效,有效則自動登入。

2. 行動裝置將可利用該方式,與Web系統使用同一個帳號密碼,於行動裝置上呼叫WebService來建立token,爾後需驗證之操作則進行CheckToken的動作。



註:產生token的方式,則可以簡單的利用random的方式於字串陣列中隨機組成。

註2:於手持裝置呼叫WebService時,可能會怕知道位址的人用別的程式呼叫,即可利用上述方式,做一個簡單的登入控管,並於每一個webService方法都做token的驗證,來避免被其他人呼叫的可能。

asp.net_有proxy時連接WebService

很多公司都有proxy,很多東西測不通也多是proxy的問題,如果要連接的WebService在公司外部,那就必須進行一些設定。


public string GetUID(string token1)
{
try
{
WebProxy myProxy = new WebProxy("http://proxy.domain.priv:80", true); //proxy主機位址
myProxy.Credentials = new NetworkCredential("帳號", "密碼", "domain"); //可使用proxy的帳號密碼
tw.gov.cp.se.AAMediator govpc = new tw.gov.cp.se.AAMediator();
govpc.Proxy = myProxy;
string govcpData = govpc.ValidateToken1(token1);
XmlDocument xml = new XmlDocument();
xml.LoadXml(govcpData);
string UID = xml.GetElementsByTagName("UID").Item(0).FirstChild.Value;
return UID;
}
catch
{
return "Error";
}
}

上面程式碼要改的有三個地方
1. 帳號:輸入可以穿過proxy的帳號
2. 密碼:就密碼
3. domain:依照proxy的名稱有所不同

單一簽入(SingleSignOn)的簡單作法_Part2_與我的E政府(自然人憑證為例)

因為專案的要求,與我的E政府進行單簽時,僅就自然人憑證的部分,所以以下用自然人憑證單一登入作為說明:

環境:
1. 程式:asp.net
2. 語法:C#
3. 系統登入機制:使用asp.net提供的帳號管理

準備工作:
1. 資料庫增加一個"asp.net帳號管理"與UserID的Mapping表,以身份證字號為key。
2. 撰寫新增帳號的function(功能:當遇到新使用者,利用Membership.CreateUser新增asp.net帳號,並同步寫入Mapping表)

我的登入流程:
1. 由系統按登入鈕後,轉址至我的E政府網站,並依照E政府規定格式擺上returnurl與level參數(例:https://www.cp.gov.tw/portal/Clogin.aspx?returnurl=導回頁網址&level=2)
2. 使用者輸入正確的Ping碼並驗證成功後,E政府會依照上步驟returnurl參數將網頁轉址回來。(註:returnurl必須與"既有服務檔案表"內填寫的網址相同)
3. 回到導回頁後,利用Request.Params["twGovT1"].ToString()取得token1,並適當地將其記錄下來。

string token1 = Request.Params["twGovT1"] == null ? "" : Request.Params["twGovT1"].ToString();

4. 利用token1向E政府提供之WebService取得身份證字號(服務位置:https://se.cp.gov.tw/SEWebApplication/AAmediator.asmx,服務名稱:ValidateToken1)

public string GetUID(string token1)
{
try
{
tw.gov.cp.se.AAMediator govpc = new tw.gov.cp.se.AAMediator();
string govcpData = govpc.ValidateToken1(token1);
XmlDocument xml = new XmlDocument();
xml.LoadXml(govcpData);
string UID = xml.GetElementsByTagName("UID").Item(0).FirstChild.Value;
return UID;
}
catch
{
return "Error";
}
}

若是環境有proxy設定,請參考:asp.net_有proxy時連接WebService

5. 利用步驟四得到的身份證字號與資料庫內的會員資料比對,找出會員UID。
6. 以該UID登入asp.net的帳號管理。

FormsAuthentication.RedirectFromLoginPage("user01", false);


簡單來說:
1. 由E政府取得身分證字號。
2. 由身分證字號找到Mapping表內的User。
3. 系統幫User登入。

單一簽入(SingleSignOn)的簡單作法_Part1_導讀

自從去年開始執行某個令人虛脫的案子後,「單一簽入、Single Sign On、整合登入介面」等等的詞句就一直在耳邊響起,也可能各個單位實在花太多錢在莫名其妙系統的建立上,所以不約而同的都提出希望可以改成單簽的架構。

但通常,之所以會有單簽的願望,狀況會有三個:
1. 是政府單位,他們配合「政府整合單一入口計畫」,所以你要跟"我的E政府進行"界接。
2. 該單位做了很多系統建置的案子,然後每次都不同廠商,所以有很多很多的登入介面。
3. 因為單簽很"飛遜",所以他自然而然將單簽寫到契約裡面了。

所以我們會有三種角色:
1. 要去使用我的E政府來進行單簽。
2. 要去用別的廠商所提供的單簽方案。
3. 要去提供別的廠商單簽。

如果,你要和"我的E政府"進行單簽,準備步驟如下:
1. 下載「e平台服務介接申請表」與「既有服務檔案表」申請表(位置)
2. 表內需要政府單位的OID,可以先上這裡查詢,若沒有了話趕快請承辦員發文。
3. 比較重要的是「既有服務檔案表」,上面必須填寫要進行單簽的網域位置(舊表格僅需填寫服務網址,新表格為WSDL服務位址與IP位址);但是在申請的時候通常不會知道正式的網域或是IP,所以這張最重要的就是填寫你要測試的位址(通常就是公司有對外的server)
4. 接來下交給承辦去簽文,然後等通過的消息。
5. 程式請看下篇。

如果,你要用別的廠商提供的單簽方案:
1. 問他
2. 問他
3. 問他

如果,你要提供別的廠商進行單簽:
1. 看下下篇。


單簽的另一個重點是,如果你在寫行動裝置程式,又你的程式必須進行一些簡單的權限控制,那你就很有可能必須要自己做一個簡單的單簽,讓你的Web與行動裝置使用。

2011年10月19日 星期三

系統裝機注意事項(SSL、負載平衡、Port)

1. 憑證可以申請一次,給很多台電腦用嗎?
Ans:可以,但是必須要先安裝至匯出請求檔的電腦上,再從該電腦連同金鑰匯出(pfx),就可以安裝到同一個DomainName下的電腦上了。

2. 負載平衡廠商問:有特殊需求嗎?要回答什麼?
Ans:必須確保同一批request中,都回到同一台電腦,也就是同一個IP Source都交給同一台處理,確保asp.net不會產生Viewstatus因為跳轉不同Server產生程式錯誤。

3. Port我都開了,還是不能連
Ans:於Server上安裝telnet(server 2008預設沒裝,安裝方法),利用"telnet ip port"來確認是否真的通了。

port即便開了,也有可能網管沒有設定特定電腦的連線,而還是不通,所以可以問『是否需要針對A電腦連B電腦做特殊設定來喚回他的記憶』

4. 備份VM為什麼演練完成以後,還要重新安排job?
Ans:因為每一台VM都有他自己的ID,當把VM移除再進行還原後,雖然機器內容是一樣的,但是對於VM來說ID已經改變,而備份排程式根據VM的ID來進行備份,所以當ID改變以後,就必須將排程重新設定,確保備份還原後的VM。

5. 80與443port是誰要開?
Ans:80 port為IIS架設以後預設使用的Port,理論上IIS正常服務,80 port也開好了;而443 port,為https所走的port號,必須要安裝SSL憑證,並於站台的"繫結"處設定,完成後Server將打開443 port。

Android學習_以Cursor為下拉式選單(Spinner)的來源,Text與Value取得方式

若是程式裡面運用到下拉式選單(Spinner),來源大概有三種:
1. 寫死在程式裡面
2. 寫在XML檔案裡面
3. 放在SQLite裡面(放預設值出問題請看本篇)

如果希望程式比較動態,通常我們會選擇放到SQLite裡面,然後做一個頁面讓使用者可以自行增減項目,所以我們可以由SQLite的查詢取得Cursor,放入也相當簡單:

if (cursor.getCount()>0)
{
cursor.moveToFirst();
SimpleCursorAdapter adapter = new SimpleCursorAdapter(context, android.R.layout.simple_spinner_item,cursor, new String[] { "ItemName" }, new int[] {android.R.id.text1});
spinner.setAdapter(adapter);
}

*以上使用Android預設的樣式simple_spinner_item來顯示下拉式選單

放進去以後,馬上面臨的下一個問題是,下拉式選單中可能需要Text與Value,也就是一個是顯示的內容,一個是程式要用的對應碼。

通常該對應碼,都會儲存在SQLite的某一個欄位中,所以思維應該是如何去取得被選項目的cursor。

有兩個時候必須要取得:
1. 點選spinner的時候
由第一個傳回的參數AdapterView轉為Cursor:

private Spinner.OnItemSelectedListener spinner_AddReturn_CaseType1_Selected = new Spinner.OnItemSelectedListener(){
@Override
public void onItemSelected(AdapterView arg0, View arg1, int arg2,long arg3) {
Cursor cursor = (Cursor) arg0.getSelectedItem();
String SelectItemCode = cursor.getString(cursor.getColumnIndex("ItemCode"));
}
};


2. 要儲存至某地的時候
直接取得後做轉換:

Cursor cursor_PrjIDType = (Cursor) spinner_AddReturn_PrjIDType.getSelectedItem();


取得Cursor後,就可以很輕鬆的讀取任何你希望取得的內容。

Android學習_自訂樣式_以按鈕為例(加上改變文字)

經過Android學習_自訂樣式_以按鈕為例的設定,可以將按鈕的背景改變,但很多時候我們會希望連同按鈕上面的字一同變化,那就必須要做多一點的設定:

1. 先經由前篇,完成背景設定的XML檔案(C步驟)

2. 新開一個於Drawable的文字設定檔

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="false" android:color="#777777" />
<item android:state_pressed="true" android:color="#1559B0" />
<item android:state_enabled="false" android:color="#ffffff" />
</selector>


3. 於res\values內的resources標籤內,加入style的設定描述

<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Button" parent="@android:style/Widget.Button">
<item name="android:gravity">center_vertical|center_horizontal</item>
<item name="android:textColor">@drawable/btn_textcolor_selector</item>
<item name="android:shadowColor">#FF000000</item>
<item name="android:shadowDx">1</item>
<item name="android:shadowDy">2</item>
<item name="android:shadowRadius">0.2</item>
<item name="android:textSize">20dip</item>
<item name="android:textStyle">bold</item>
<item name="android:background">@drawable/btn_selector</item>
<item name="android:focusable">true</item>
<item name="android:clickable">true</item>
</style>
</resources>

重點有兩個地方,textColor與background都是去讀取步驟1與2的設定檔,也就是按鈕按下時,背景會隨著背景設定檔改變,而文字則會依照文字設定檔改變,至於有沒有合併的撰寫方式,初步是沒有測出其他方式。

4. 最後,在按鈕的屬性上設定style

<Button
android:id="@+id/btn_main_Login"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="登入"
style="@style/Button"
></Button>


可以注意到一件事情,drawable的每一個設定,都是一個XML檔案,但Style卻是一個標籤,所以可以將很多Style都放在同一個resources標籤內。

Android學習_自訂樣式_以按鈕為例

寫程式就是這樣,一開始做一個簡簡單單介面,等到功能都可以達到了,就會開始想要改變樣式,希望程式界面變得更好看,這時候諸如我這樣美術細胞很少,大概只會深底白字、灰底深字,連美勞都做不好的一般工程師就會開始感到無力,但完全不做美工的世界也不知道在哪裡?

所以,想要更漂亮的介面,至少先學會怎麼改變,再想怎樣可以變得更好看。

如果要變更按鈕的樣式,大概有兩個方向,一個是"按鈕外殼的改變",另一個是"按鈕上面字的改變"

首先說明改變外殼的方式,方法分為兩種:
1. 使用程式碼的方式

A. 於res點擊右鍵,新增一個Android XML File

B. 輸入檔案名稱後,選擇create Drawable,並於root選擇selector

C. 新建完成以後,可以發現於selecto的標籤內只能加入item標籤,而該標籤內只能放上以android:state開頭的屬性,而觀察字面上的意思就可以猜出,這是用來判斷每一種狀態時,要顯示的按鈕樣式。如果希望一般狀態與按下按鈕時有所區別就可以利用兩個item標籤來設定:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape>
<gradient android:startColor="#FFA10A" android:endColor="#FFB947" android:angle="90" />
<stroke android:width="2dip" android:color="#cccccc" />
<corners android:radius="3dp" />
<padding android:left="10dp" android:top="10dp" android:right="10dp" android:bottom="10dp" />
</shape>
</item>
<item>
<shape>
<gradient android:startColor="#1559B0" android:endColor="#3F92FF" android:angle="90" />
<stroke android:width="2dip" android:color="#cccccc" />
<corners android:radius="3dip" />
<padding android:left="10dp" android:top="10dp" android:right="10dp" android:bottom="10dp" />
</shape>
</item>
</selector>

D. 設定完上述檔案後,就可以到按鈕標籤處將該設定檔引入

<Button
android:id="@+id/btn_main_Login"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="登入"
android:background="@drawable/buttonstyle"
></Button>


那如果自己或是有人可以幫你做按鈕的底圖,當然也可以利用這樣的方式,將圖變為按鈕的外框。
2. 使用背景圖案的方式
直接在item標籤內設定要顯示的圖:

<item android:drawable="@drawable/pressed"
android:state_pressed="true"/>

2011年10月5日 星期三

人的一生



剛剛無意間在youtube上面看到一個有趣的日本動畫,現在大概進行到第10秒左右,生活中也真的很多事情就是比較再比較,快還要更快,好還要更好的在走...一直衝刺的目的是?

不知道從幾歲開始,我非常喜歡看老子、莊子等漫畫書,甚至翻了不下數十次,裡面有一篇也在講這件事情:

一個菜鴨不像其他鴨子玩樂,而是每天很認真的學英文、學電腦、成為最頂尖的菜鴨,但到了屠宰之時,他還是成為了桌上餚;到了天堂他問神明『我這麼認真,為什麼還是換來屠宰?我認真的學習難道錯了嗎?』,神說:認真過沒錯,玩樂過也沒錯。

總之,怎麼過是個人的選擇,有開心的小朋友、也有悲傷的小朋友;有陽光的青少年、也有陰沉的青少年;有熱血的上班族、也有憤世的上班族;有開明的父母、也有無理的父母;有歡樂的老人,當然也有哀怨的;大家的終點都一樣,所以人的一生才真正是一件"過程比較重要"的事情。

事物並不能夠分為極端的兩面,但唯有擁有一邊的經歷才能體會另外一面的時光,

而有菜鴨的衝才有可能感覺到閒暇的輕鬆氣氛。

如果人生是遊樂場,關園時能開心歸賦才真的是『 』。

Flex4學習_捲軸使用(Scroller)_flash做APP_Part6

系列文章:
1. Android學習_以WebView讀取SWF檔_flash做APP_Part1
2. Android學習_以Flash Builder 4.5製作Air放入Android_flash做APP_Part2
3. Android學習_為什麼Flash Builder 4.5做的APP可以跨平台_flash做APP_Part3
4. Android學習_頁面切換_flash做APP_Part4
5. Flex4學習_button change icon_flash做APP_Part5
6. Flex4學習_捲軸使用(Scroller)_flash做APP_Part6

在製作手機程式,很常會碰的問題是:要顯示的內容很多,但是螢幕不夠大。這個時候通常會使用捲軸來完成,而在Flash Builder 4.5製作Mobile專案時,有支援手勢滑動的標籤有兩種一個為List一個為Scroller。

只有測試Scroller就以Scroller來說明:

<s:Scroller x="120" y="10" width="70%" height="100%" >
<s:VGroup width="100%">
<s:Label id="lab_show" y="12" width="100%" text=""/>
<s:Image id="image_show" />
</s:VGroup>
</s:Scroller>

其實很簡單,就是利用Scroller標籤將需要捲軸的內容包起來,並且設定他的height屬性(若不設定將不會產生捲軸)

但其實這樣的東西我就找了兩個多小時 T.T。

Flex4學習_button change icon_flash做APP_Part5

系列文章:
1. Android學習_以WebView讀取SWF檔_flash做APP_Part1
2. Android學習_以Flash Builder 4.5製作Air放入Android_flash做APP_Part2
3. Android學習_為什麼Flash Builder 4.5做的APP可以跨平台_flash做APP_Part3
4. Android學習_頁面切換_flash做APP_Part4
5. Flex4學習_button change icon_flash做APP_Part5
6. Flex4學習_捲軸使用(Scroller)_flash做APP_Part6

因為Flex實在是太久沒用,之前學的Flex3已經有點忘記,這次用Flex4當然更是一直問人又Google,其中有一個很大的變化,就是在Flex3的時候,可以很簡單的設定icon的屬性就可以達成圖片按鈕的效果,但在Flex4把這個屬性拿掉了,轉而要利用skin的方式設定。

方法:
1. 建立一個skin檔案(右鍵新增一個Packge,再於新增MXML Skin)

<?xml version="1.0" encoding="utf-8"?>
<s:SparkSkin
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
alpha.disabled="0.5">

<fx:Metadata>
[HostComponent("components.ImageButton")]
</fx:Metadata>

<fx:Script>
<![CDATA[
static private const exclusions:Array = ["labelElement"];
override public function get colorizeExclusions():Array
{
return exclusions;
}
]]>
</fx:Script>

<s:states>
<s:State name="up" />
<s:State name="over" />
<s:State name="down" />
<s:State name="disabled" />
</s:states>

<!-- UP ICON -->
<s:BitmapImage source="{getStyle('icon')}"
verticalCenter="0" left="5" includeIn="disabled" />


<!-- UP ICON -->
<s:BitmapImage source="{getStyle('icon')}"
verticalCenter="0" left="5" includeIn="up" />

<!-- OVER ICON -->
<s:BitmapImage source="{getStyle('icon')}"
verticalCenter="0" left="5" includeIn="over" />

<!-- DOWN ICON -->
<s:BitmapImage source="{getStyle('icon')}"
verticalCenter="0" left="5" includeIn="down" />

<!-- Text SKIN-->
<s:Label id="labelDisplay" textAlign="center" verticalAlign="middle"
maxDisplayedLines="1" left="0" bottom="0" color="#FFA10A">
</s:Label>

</s:SparkSkin >

新建好以後,可以發現Builder已經幫我們加了很多程式碼,而因為我們要做圖片的變更所以必須將UP ICON後面的程式碼補上,重點有三個:
A. 建立了四個BitmapImage,皆有includeIn的屬性,分別代表了:disabled(預設)、up(拿起)、over(滑動)與down(按下)四個動作,所以我們可以針對這四個動作給予不同的圖片。
B. 放置了一個名為labelDisplay的Label,『labelDisplay』為規定的id名稱,Builder將會把文字放到該名稱的Label內。
C. BitmapImage的source可以在這邊直接指定(source=Embed('images/car_right.png')),因為我們並不會希望一個按鈕就要建一個skin,會希望利用外面給定的方式,所以這邊source以關聯的方式指定(source="{getStyle('icon')})。

2. 於Button指定skin

<s:Button id="btn_Home1" label="A" skinClass="skin.button"/>

skin.button的skin是packge的名稱,button為剛剛建立的skin名稱

3. 指定圖片(利用Style)

<fx:Style>
@namespace s "library://ns.adobe.com/flex/spark";
@namespace mx "library://ns.adobe.com/flex/mx";
#btn_Home1 {
icon: Embed(source="images/car_left.png");
}
</fx:Style>

說明:
A. #btn_Home1表示指定id為btn_Home1的按鈕。
B. icon對應到skin內BitmapImage的source屬性。

效果:

Android學習_頁面切換_flash做APP_Part4

系列文章:
1. Android學習_以WebView讀取SWF檔_flash做APP_Part1
2. Android學習_以Flash Builder 4.5製作Air放入Android_flash做APP_Part2
3. Android學習_為什麼Flash Builder 4.5做的APP可以跨平台_flash做APP_Part3
4. Android學習_頁面切換_flash做APP_Part4
5. Flex4學習_button change icon_flash做APP_Part5
6. Flex4學習_捲軸使用(Scroller)_flash做APP_Part6

因為出發點為電子書程式的測試,所以在交接前也做了與其相關的內容測試,首先是頁面的切換。

於前面的文章有提到,利用Flash Builder 4.5所建立的Mobile專案,是以View為基礎,可以直接想成Android裡面的Activity,所以一開始最關心的莫過於要怎麼從A View切換到B View:

切換View的語法:

navigator.pushView(ViewClass:Class);

關閉View的語法:

navigator.popView();


若是你在剩下一個View的時候執行了navigator.popView()的語法,你會發現整個程式會變成只剩下白色的畫面,原因是即使你關閉了所有的View,他背後還有AIR的環境在繼續執行(相關觀念參考),所以若要關閉整個程式,必須要將AIR的環境一併關閉。

程式關閉語法

NativeApplication.nativeApplication.exit();

Android學習_為什麼Flash Builder 4.5做的APP可以跨平台_flash做APP_Part3

系列文章:
1. Android學習_以WebView讀取SWF檔_flash做APP_Part1
2. Android學習_以Flash Builder 4.5製作Air放入Android_flash做APP_Part2
3. Android學習_為什麼Flash Builder 4.5做的APP可以跨平台_flash做APP_Part3
4. Android學習_頁面切換_flash做APP_Part4
5. Flex4學習_button change icon_flash做APP_Part5
6. Flex4學習_捲軸使用(Scroller)_flash做APP_Part6

以Flash Builder 4.5來開發手機程式有一個好處,你所寫的一份程式碼可以編譯成IOS或Android的版本,原因是什麼?為什麼這樣做就可以達到跨平台的方式?

以Android為例,利用Flash Builder 4.5開發出來的APP並不是"直接"執行在Android Runtime之上,而是外面又包了一層AIR,所以我們寫的程式是執行在AIR之上,而AIR執行在Android Runtime之上,而adobe除了提供了Android的接口以外,也提供了IOS的接口;因為他們提供了兩個平台的AIR環境,而達成跨兩個平台的需求,也就是說如果又建立了WP7的AIR環境,那麼該程式將可以跨三個平台。感覺就像下圖:


雖然聽起來這是一個很棒的方式,但是這取決於Adobe所提供的AIR環境是否可以完整無縫的與其他平台整合,另外執行效能可能也是需要考慮的地方。

Android學習_以Flash Builder 4.5製作Air放入Android_flash做APP_Part2

系列文章:
1. Android學習_以WebView讀取SWF檔_flash做APP_Part1
2. Android學習_以Flash Builder 4.5製作Air放入Android_flash做APP_Part2
3. Android學習_為什麼Flash Builder 4.5做的APP可以跨平台_flash做APP_Part3
4. Android學習_頁面切換_flash做APP_Part4
5. Flex4學習_button change icon_flash做APP_Part5
6. Flex4學習_捲軸使用(Scroller)_flash做APP_Part6

Adobe在Flash Builder 4.5或CS5後,可以建立『Flex Mobile Project』。

建置的流程很直覺:
1. 決定專案名稱

2. 選擇預設的模板

3. 切換到Permissions可以指定需要的專案權限,以Android來說他預設勾選了網路連線(INTERNET)的權限。

4. 設定debug檔案產出的位置。

5. 專案及引入lib的設定。

專案建立完成:

觀察專案配置,可以看到他預設只產生一個View,我們可以拉幾個按鈕以後於專案點擊右鍵來執行看看。

若是第一次進行測試,可以先選擇Run Configurations來設定測試環境;如果要使用模擬器,可以選擇On desktop並指定哪隻手機,若是實機則可以選擇On Device。

效果:

雖然僅一個沒有讀取資料的簡單頁面,但程式起來的時間可以明顯感受到速度並不優且佔用的記憶體也相當的大(Sensation為23mb),但是程式完成後的效果比起利用WebView讀取SWF的方式好非常多,整體介面也與一般的APP並無差異,所以決定利用該方案繼續進行電子書的簡單測試。

Android學習_以WebView讀取SWF檔_flash做APP_Part1

系列文章:
1. Android學習_以WebView讀取SWF檔_flash做APP_Part1
2. Android學習_以Flash Builder 4.5製作Air放入Android_flash做APP_Part2
3. Android學習_為什麼Flash Builder 4.5做的APP可以跨平台_flash做APP_Part3
4. Android學習_頁面切換_flash做APP_Part4
5. Flex4學習_button change icon_flash做APP_Part5
6. Flex4學習_捲軸使用(Scroller)_flash做APP_Part6

昨天突然接到一個需求,有一個案子想要利用Flex或Flash來進行手機程式的開發,整體要求只有一句話『於手機上面顯示出電子書的感覺』,所以有三個可以做的方向。

1. 利用Android裡面的WebView讀取已經製作完成的SWF檔案。

2. 利用Flash Builder 4.5以上版本建立Mobile專案。

3. 直接利用JAVA Code來進行開發。

因為只負責測試環境,所以第三項就不考慮,因為預設是要交給會使用Action Script語法的人繼續開發。

---------------------------------------------------------------------------
為了單純,當然是希望直接用第一種方法,也就是利用Android的WebView來讀取SWF檔案。

作法:
1. xml的配置:只放下一個WebView。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>

<WebView android:id="@+id/webView1"
android:layout_width="match_parent"
android:layout_height="match_parent"></WebView>

</LinearLayout>


2. 製作一個SWF檔案,放置到專案目錄(assets內)。
這邊要注意,製作的swf檔案必須先確認是否可以正常執行,若是發現編譯出來的swf檔案都只有底色,上面的按鈕及圖片等都沒出現,可以利用選單的Prject→Export Release Build來進行編譯。

**2012/11/19補充Export Release Build位置圖:

3. 撰寫Java Code。關鍵程式碼只有四句:
A. 找到webView
B. 設定該webView使用外掛。
C. 指定要讀取的url。(本機位置的語法:file:///android_asset/SmallBook.swf)
D. 利用loadUrl方法讀取該SWF。

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

WebView webView = (WebView) findViewById(R.id.webView1);
webView.getSettings().setPluginsEnabled(true);
String url ="file:///android_asset/SmallBook.swf";
webView.loadUrl(url);
}

接下來應該就可以在手機裡面看到swf檔案,但是整體執行起來的效果"應該"不會很滿意,所以接下來方案二。

2011年10月2日 星期日

Android小抄_將路徑轉為URI

如果已經取得了檔案的路徑的字串,那怎麼轉成URI呢?


String ImagePath = "file://" + 路徑;
Uri uri = Uri.parse(ImagePath);


重點在於要加上『file://』,才能成為合法的URI,不然該URI會無法表示相對應的檔案位置。

EX:file:///ola/android.txt

補充:
或是用Environment.getExternalStorageDirectory()取得sdcard位置。

TakePicFileName = "ola.jpg";
TakePicFilePath = Environment.getExternalStorageDirectory().toString() + "/DCIM/";
File tmpFile = new File(TakePicFilePath, TakePicFileName);
Uri uri = Uri.fromFile(tmpFile);