跳到主要內容

Adobe AIR for Mobile( Android 篇)

大家好,我是奶綠茶
今天來教大家如何發怖你的 Flash app , 到 Mobile 上,
軟體需求:
Adobe Flash CS5.5 或是 Adobe Flash Builder4.5
在這以 Flash CS5.5 來做教學
開啟新檔,選擇 AIR for Android

製作方法就和一般的 flash 寫法都一樣
但要注意一些小細節,
1:儘量使用點陣圖而不要用相量
Flash CS5.5 在物件的面版上,提供了新的方法,讓你可以在編譯後,幫你把 MovieClip 直接輸出成點陣圖

使用這個功能,該 MovieClip 就變成了一張圖檔, 裡面的功能會失效
另一個方法是全選你的相量物件,按一下右鍵後,會出現 Convert to Bitmap

2:不要使用 filter, blend mode, alpha
這些都是很吃效能的動作

Publish


General:
Output file:要輸出的 apk 檔名
App name:你的 app 名稱,會出現在 Android 上 icon 的名稱
App ID:這個跟上傳到 android Market 上會有很重要的關係
當你第一次上傳 apk 後, 之後每次更新的 apk 檔, 該 App ID 都要一樣,否則不能上傳
Version:一樣和上到到 android Market 有關,新的 apk 版本號要比前一版高才能上傳。
Version label:這個只是顯示用。
Aspect ratio:可以指定是 Portrait (直), Landscape(橫) 或是 Auto(自動)
Full screen:打勾的話,你的 app 會滿版,沒有的話,上面會保留 Android 的 Tital Bar
Auto orentation:是否自動旋轉。
Render mode:一般 flash 都是透過 CPU 在運算, 在 Mobile 上,可以選擇 GPU 加速。
Included files:編譯成 apk 時,同時把另外的檔案也加入,如圖片或是 sqlite等。

Deployment:

Certificate:驗證檔, 你可以按最右邊的 Create 產生一個屬於自己的驗證檔
Password:你的驗證檔密碼
Android deployment type:
在這雖然有 Emulator 的選項,但更新到 AIR2.6 後,裝上去執行都會出現 Error,如果有人測成功的話再麻煩告知方法。
還是乖乖選擇 Device release 吧
Get AIR runtime from:如果使用者安裝你的 apk , 發現沒有 AIR runtime 時,會到那兒下載
預設就選 Google Android Market吧

Icons:
Android 有三種 Size , 36x36 , 48x48, 72x72

Permissions:
這裡跟 Android 的 Permissions 是一樣的,只是目前 AIR for Android 還沒有那麼多可以選
如果你有需要用到特別的功能,都需要在這兒打勾才可以使用
比如說你要使用 Camera , 就要選  CAMERA
要錄音,就要選 RECORD_AUDIO

安裝 Android SDK
http://developer.android.com/sdk/index.html
接上你的 Android 手機, 按下發怖, 就可以成功上傳到你的手機上了。


關於 catchAsBitmap 和 catchAsBitmapMatrix
在 AIR2.6 裡
所有的 DisplayObject 多了一個 catchAsBitmapMatrix 可以使用
看一下 官方文件的說明
簡單來說,就是你的物件只有 move, rotation, alpha , scale 等動作時
可以開啟這樣的屬性,會讓你的效能更佳
而另一個 cacheAsBitmap 指的是如果物件只有移動的話,開啟該屬性效能會更佳
所以我就針對
什麼都不開啟
開 cacheAsBitmap
開 cacheAsBitmap和 cacheAsBitmapMatrix
並配合二種動作方試來做測試


測試的結果:
什麼都不開,二種動作都會 lag
只開 cacheAsBitmap, 在只有移動時,效能優,但如果加上 rotation 之類的話,比什麼都不開還要慢
開 cacheAsBitmapMatrix, 效能最優
祝大家學習愉快,
下一篇來分享 AIR for iOS

測試影片



補充一下:
你的 Android 手機必需是 2.2 以上版本
同時 CPU 是 v6 以上,才能安裝 AIR runtime.

轉載請註明出處
SourceCodeDownload

留言

jotarun寫道…
謝謝分享
可惜我的android不能裝air..
匿名表示…
奶綠茶老師您好,我有一個問題想要請教您:

我現在使用Flex Builder4.5寫Android的程式,是一個網路電話的程式. 程式的架構是"ViewNavigatorApplication" , 所以一定會有很多的View. 因為是網路電話,所以跟server常常會有資訊交換,例如撥號,來電...等等.

我想問的問題是如何在這些view(s)快速交換資料? 因為有很多資料是要傳到不同的view (parentApplication->view),也會回傳到程式的最上層(view->parentApplication), 目前我只知道用navigator.pushView可以帶資料到不同的view(可是一次好像只能一筆?),不過這樣不就代表一定要換view才能傳送資料? 請問奶綠茶老師有什麼方法可以讓這些view之間互相交換資料..這個問題困擾我很久,也找了蠻多文章,不過到目前為止還沒有找到解決方法,所以想說來這邊請教奶綠茶老師,請老師幫幫忙,謝謝!!
milkmidi寫道…
試試看使用 Singleton Pattern
http://milkmidi.blogspot.com/2009/03/designpatternssingleton.html
應該可以很方便的決解你的問題
chunte表示…
奶綠茶老師您好,謝謝您的回覆!! 這兩天我看了一些關於singleton pattern的文章,也包含您部落格裏面的文章,雖然不是非常了解,但已經有個大致的概念了.

不過我不曉得singleton是否適用於我的程式...
如我上面提到,因為手機版本需要使用很多的view來切換不同畫面, 在我的root view會處理server傳過來的data(從其他.as告訴server要傳什麼資料過來),再根據這些data來控制其他view要怎麼動作,例如我現在可以從其中一個畫面撥號出去,但是當對方把電話接起來時,server會傳送一個命令過來告知我通話已建立,但我在撥號的那一個view就會收不到這筆通知的資訊,造成我撥號的view一直在顯示正在撥號..對方一接起來就出現錯誤,錯誤是發生在root view,所以讓我感覺不太像是要用singleton的作法....


然後想再問老師幾個問題:
(1)不同的view可以呼叫對方的function嗎? 我今天寫了一個小程式,view2是使用者輸入書字要做加法,view1接收使用者從view2所輸入的數字來做加法,再把結果從view1回傳給view2顯示結果,結果顯示錯誤.(num1 num2 sum 都是view2的元件)

parentApplication.view.cal(num1,num2);
sum=parentApplication.view1.num3;

結果顯示以下錯誤:
ReferenceError: Error #1069: Property view1 not found on TEST2 and there is no default value.

錯誤是在parentApplication.view.cal 這一行, 想請問老師如果要不同的view之間互項傳遞資料和互用對方的function要怎麼解決?

(2)在用view navigator時常會出現Error #1009
上次找到錯誤的原因是因為view裡面的元件為null,也就是系統把它砍掉了,是不是有什麼方式能保持每一個view的元件都存在?

不好意思,問題蠻多的,這些都是困擾我蠻久的問題,不過只有這樣講老師可能也很難理解我的問題點到底怎麼解決,如果之後有需要的話再把程式碼給老師看,用看的應該會比較清楚程式的架構,到時候再跟奶綠老師詳細討論.

麻煩你了~! 謝謝!
milkmidi寫道…
當程式碼出現呼叫 parent 的函式就是不好的寫法
你的問題可以用 Singleton 解決
Singleton 除了可以記錄變數,也可以當作發送事件者,
root View 接到事件後,
透過 Singleton 轉發送事件
子 View 在 createComplete時,就對 Singleton 注冊該事件,
這樣就人人可以知道。

比較好的寫法,還是用 MVC 寫會更適合。
希望這樣有決解你的問題
我自己在寫 Mobile 或是 Web 時,都很常用 Singleton。
chunte表示…
"root View 接到事件後,
透過 Singleton 轉發送事件
子 View 在 createComplete時,就對 Singleton 注冊該事件,
這樣就人人可以知道。"

這句話真是讓我眼睛為之一亮啊~! 看到這句話彷彿我的程式就快完成了...XD!!

不曉得奶綠老師有沒有比較推薦的一些線上資源或是書籍,雖然有看過一些網路上的文章,但還是不太了解,第一次碰singleton和MVC,不曉得如何才能從基本的了解他們...

P.S:再請問老師一個問題,VIEW之間的FUNCTION可以互相呼叫嗎??
milkmidi寫道…
這一本很不錯,
http://www.tenlong.com.tw/items/9867794524?item_id=33235
買回來 K 一下。
MatisHsiao寫道…
AIR 2.6要使用Android模擬器要手動編譯APK檔,您可以參考我這篇文章
http://matishsiao.blogspot.com/2011/08/flashcs-5andorid-apk.html
milkmidi寫道…
感謝提供,馬上來讀一下
匿名表示…
請問一下
flash 發佈android 之後
文字欄位無法輸入中文
但是可以輸入數字和英文
這問題可以解決嗎
milkmidi寫道…
我沒遇到這樣的問題也
請問你的手機是什麼型號呢
匿名表示…
我的是 htc sensation
丹尼爾寫道…
老師你好,請教您一個問題
我用CS5.5寫了一個android的遊戲,
裡面有用了SQLite的資料庫,
在電腦上執行時完全功能都正常,
可是一旦轉成apk之後,安裝進手機都沒辦法使用資料庫內的資料,
請問我該怎麼寫才能讓程式讀取到資料庫呢??
附上我的部份程式碼,麻煩您指點一下,謝謝
var conn:SQLConnection = new SQLConnection();
var folder:File = new File(File.applicationDirectory.resolvePath("MyData.db").nativePath);
var runSQL:SQLStatement = new SQLStatement();
runSQL.sqlConnection = conn;
var bstmp:int = 0;
runSQL.parameters["@bbs"] = bbs;
conn.open(folder,SQLMode.READ);
runSQL.text = "SELECT logs FROM bslog WHERE bs = @bbs";
runSQL.execute();
var result:SQLResult = runSQL.getResult();
var row:Object = result.data;
bstmp = row.logs;
conn.close();
if (bstmp == 0 || bssg < bstmp)
{
bwin.patxt.text = "最佳紀錄:" + bssg.toString() + "步";
runSQL.parameters["@bbs"] = bbs;
runSQL.parameters["@logs"] = bssg;
conn.open(folder,SQLMode.UPDATE);
runSQL.text = "UPDATE bslog SET logs = @logs WHERE bs == @bbs";
runSQL.execute();
conn.close();
}
else if (bssg > bstmp)
{
bwin.patxt.text = "最佳紀錄:" + bstmp.toString() + "步";
}
壘包寫道…
我也有與丹尼爾同學同樣的問題...
轉成apk在手機上執行就沒辦法呼叫資料庫的資料
要怎麼解決呢???

謝謝老師
壘包寫道…
我的程式碼如下:
http://codepad.org/uBsl2i52

我是call AMFPHP呼叫我已經寫好的PHP class
然而這個class會幫我做查詢dababase的相關資訊

我可以在電腦上弄成swf檔執行,但是轉到手機上我的respoder就沒反應...

請問這是跟crossdomain.xml有關嗎??
milkmidi寫道…
To 丹尼爾
應該是要讀的到
先查查看是不是載入的 .db 路徑有誤

To 壘包:
AIR 可以跨網域呼叫,
是不是 Android 的 INTERNET permission 沒開啟呢
壘包寫道…
哇真的沒錯...
一開啟就可以了

我竟然忘記最重要的權限...結果想好久

非常感謝老師
壘包寫道…
呃...老師抱歉
我發現可以的原因是因為我有寫個小捷徑測試,忘記註解掉,所以才誤以為有成功。但實際上我用去call PHP裡面的程式還是失敗的...

我有照老師的方式開啟那個permission,但還是不行...我還需要設定哪個部份呢?? 奇怪哩...囧
milkmidi寫道…
應該要可以才對
先試一般的 URLLoader 去試載一個 txt
看成不成功
然後再查一下 Server 端是不是有檔來源
丹尼爾寫道…
老師你好~我檢查過我的檔案本身都是OK的了~
但是他還是查詢不到我的資料庫檔案~
但是我在ADOBE上面查詢過相關的問題
裡面有寫到"發佈預先填入的資料庫"
但是對於"請使用來自 AIR 套件的檔案做為「範本」資料庫"這句話不是很能理解
請問這句話是十麼意思呢??
我該怎麼把我的資料庫檔案改成"範本資料庫"呢?
附上當時查詢的網址
http://help.adobe.com/zh_TW/AIR/1.1/devappsflash/WS5b3ccc516d4fbf351e63e3d118666ade46-7d3c.html
再次的麻煩您了
壘包寫道…
用loader去讀個TXT檔是失敗的
但是很神奇,為什麼弄成swf檔loader可以執行
反而在手機上執行app,loader卻沒反應...

我困惑了- -...
milkmidi寫道…
因為沒開啟 Android Internet 權限 ?
壘包寫道…
恩...我發現老師說的對,internet這個權限確實要開啟,這樣debug在手機上就能正確的呼叫amfphp跟loader。

不過這些成功的要素是我在學校Lab測試的,換到家裡就不行,即使有開權限。

我想是不是因為我的Web Server&Database架在學校的關係呢?導致它只能認Lab的網域??我有試著在amfphp資料夾裡面的service加加看crossdomain.xml,不過還是失敗...

不好意思又麻煩老師了!!
milkmidi寫道…
因為你要跟叫網路資源,就一定要開啟 Internet 的權限,
現在就是確定不是你的程式問題
差差 Server 端是不是有檔呼叫來源
壘包寫道…
好!!我會再試試看
非常感謝老師
小醬寫道…
請想問奶老師,我目前使用Develop進行開發 AIR for Android,不過我碰到解析度上的問題。

如:Sony XPERIA X10解析度是480*820,可是XPERIA S 解析度高達1280。

想請問奶老師,有什麼解決方式嗎?
milkmidi寫道…
就像做網站一下
要自己想辦法定位
小醬寫道…
不好意思,不太懂老師的意思。我目前開發的大小是480*800,我改如何讓解析度更大的手機也能正常顯示?
milkmidi寫道…
要自己寫程式判斷使用者的解悉度
然後物件的座標也要跟者使用者的解悉度一起更改
小醬寫道…
老師不好意思,那這樣子的話 是不是需要多張不同解析度的圖片?
milkmidi寫道…
是的,
不過通常會做一個比較通用的 size
然後再用程式去縮放
匿名表示…
不好意思 我想請問一下
就是我是在FLASH CS5.5的環境下案CTRL+ENTER
進行對資料庫連結和增刪改查的測試
這時候都沒有問題
可是發佈到 ANDROID平板上的時候 就不能使用資料庫
想請問一下是甚麼問題

這個網誌中的熱門文章

webpack2 入門實戰 1

大家好,我是奶綠茶
前端戰場不再只是寫寫 js / css , 各種框架、前處理工具百花齊放
身為前端工程師,不只要把程式寫完,還要寫好
老師說:選對好工具,事情就完成一半
如果你還在一隻 JS 打完全部程式,一隻 css 寫所有的 style
每次存檔還在手動 reload 網頁, 圖片壓 K 壓到不要不要的
透過奶綠伯的系列教學,讓你了解 webpack2 帶來的優勢
學會 webpack 可能不會加薪,但至少可以準時下班(誤)
1. 安裝 nodejs
請參考 gulp 安裝編

2. 安裝 global webpack , 筆者使用的是 2.2.1 版本
npm i webpack@2.2.1 -g
3. 在專案的根目錄放一隻 webpack.config.js
entry:你的主 js 進入點
output.filename:webpack 打包後的檔名
output.path:webpack 打包後的路徑
var path = require('path'); module.exports = { entry: './src/app.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') } };
4. require , module.exports
現在前端都 module 化
可以每個獨立的功能都寫成單一的 js module
除了好管理,也方便讓團隊使用
寫一隻 module_exports_util.js
每隻經過 webpack 打包的 js , 都會是獨立的檔案
所以變數都是私有的, 外部成員都無法得到
在這個 module 裡,我們想開放二個函式
add , getName
所以在最後的 module.exports 指定
筆記加入 jsdoc , 為了方便在開發時,能夠有型別的提示

var name = "milkmidi"; /** * @param {number} num1 * @param {number} num2 * @return {number} */ function ad…

webpack2 入門實戰 3 scss,html,file-loader

大家好,我是奶綠茶
上一篇介紹了 webpack 的核心功能 loader
這篇再來補強各種常用的 loader
css-loader:解悉 css 檔
extract-loader:這個有點難翻,下面會介紹
file-loader:存成實體的檔案, 如圖片
html-loader:解悉 html 檔
sass-loader:解悉 scss 檔
url-loader:解悉圖片路徑
webpack.config.js
module.exports = { resolveLoader: { // 所有用到的 loader, -loader 可以不用打 moduleExtensions: [ "-loader" ], }, resolve: { // 在 require 檔案, 如果不想寫完整的路徑 // 可以加入這些目錄, 讓 webpack 自動尋找對的檔案 // 請注意我們加入了 src/img 路徑,後面會再介紹到 modules: [ path.resolve( 'src/html' ), path.resolve( 'src/img' ), path.resolve( 'src/css' ), path.resolve( 'src/js' ), path.resolve( "node_modules"), ], // 在 require 時可以不用打副檔名 extensions: [ ".js", ".scss" ] }, } 再來就是 loader 的介紹
scss
在這要做多組合的應用
先將 .scss 透過 scss-loader 轉換, 並產生 sourceMap 檔
再過 css-loader
最後再過 style-loader
{ test: /\.scss$/, // 多個 loader 組合, 可寫成一行,或…

gulp 前端自動化 - spritesheet

大家好,我是奶綠茶
今天來介紹如何使用 gulp 來自動化將圖片拼成 spritesheet
奶綠我使用的套件是 gulp.spritesmith
https://www.npmjs.com/package/gulp.spritesmith
可以使用 handlebars 格式,拼出自己想要的 css 格式
{{#sprites}} .{{name}} { background-position: {{px.offset_x}} {{px.offset_y}}; width: {{px.width}}; height: {{px.height}}; background-image: url({{{escaped_image}}}); } {{/sprites}} gulp 的設定
gulp.task('sprite',()=>{ console.log('sprite'); const spriteData = gulp.src('src/sprite_src/*') .pipe(spritesmith({ imgName: '../img/sprite.png', cssName: '_sprite.css', padding: 4, imgOpts: { quality: 100 }, cssTemplate: 'src/css/handlebars/basic.handlebars', })); const imgStream = spriteData.img .pipe(buffer()) .pipe(gulp.dest('dist/img/')); const cssStream = spriteData.css .pipe(gulp.dest('src/css')); return merge(imgStream, cssStream); });…