2014/11/07

2014/08/12

(iOS) Youtube iframe 在 Apple TV 上的播放問題

問題:

有一個頁面使用WebView + Youtube iframe 播放 live channel,在手機上播放正常,但如果使用AirPlay功能cast到Apple TV的話則會出現“ an error occurred loading this content ”。
如果播放的是非live則可以正常運行。

處置:
  • 用電腦開啓Plex Home Theater作為測試裝置,可以播放live,故應該不是AirPlay本身不支援live。
  • 由於以相同的程式碼來作處理時,單則節目可以播放而live不行,故認為是Apple TV那邊無法處理。
  • Apple TV裡的Youtube app 完全搜尋不到Live的節目。
  • 一開始懷疑是訊號來源問題,比方是否為Apple TV無法處理Youtube廣告要求,但查明目前並沒有廣告。
  • 後來發現Youtube官方iOS app並不會有這樣的問題,懷疑如果我不透過iframe的方式也許可以處理。
  • 最後使用https://github.com/hellozimi/HCYoutubeParser來做處理,取得直接播放的URL,則可正常在Apple TV上播放。
  • 在使用HCYoutubeParser上需要小心,因為Youtube曾經改變過responceData,所以會有不能用的風險,這個要自行承擔。

2014/06/27

使用sublime為unity編輯器 in mac 之 CompleteSharp設定障礙排除

標題下得很長
基本上是記載依照http://wiki.unity3d.com/index.php/Using_Sublime_Text_as_a_script_editor的步驟進行時
CompleteSharp這個plugin在mac環境上遇到的一些問題

1. CompleteSharp的安裝
個人測試在windows可以用package control直接安裝成功
而在mac下會出現Unable to download CompleteSharp的錯誤
這時候只能手動安裝
有兩種選擇

a) clone  https://github.com/ewilde/CompleteSharp 到 Package資料夾
不需其他處理(建議)

b) 需事先安裝mono (下載http://www.go-mono.com/mono-downloads/download.html)
clone  https://github.com/quarnster/CompleteSharp 到 Package資料夾
再執行CompleteSharp/build.py

2. CompleteSharp project setting
在mac環境中會用到completesharp_mono_path這個參數
wiki中寫的completesharp_mono_path是3.x 版時的路徑
4.x版可改為如下

2014/06/06

Crashlytics 申請使用記錄

相較於Crittercism
Crashlytics專注於crash的記錄與統計
且目前為免費使用(2014/6/6)

要申請Crashlytics帳號必須先在http://try.crashlytics.com/留下你的資料
個人經驗是下午三點申請大概晚上9點就回覆你了
會收到兩封信
一封是Invitation
另一封是確認你有沒有收到Invitation的信件會要求你回覆(我有回覆,但感覺只是CRM的信件)

從Invitation裡的按鈕進入並依他的步驟一直往下走會進到下載plugin的頁面
個人覺得這是Crashlytics的特色
透過一套plugin讓使用者在設定過程中得到幫助與需要的說明
並在有crash時提供一個清單讓你觀看
這裡我試裝了XCODE與Eclipse兩個plugin
XCODE會出現在右上角系統bar中
而Eclipse會出現在Eclipse Toolbar當中

以XCODE版為例
一開始按下ICON後會出現以下畫面
基本上就是將我的XCODE專案都列出來方便我選擇要使用Crashlytics的專案
在這裡選擇專案以後會出現設定的說明如下
這裡說明了要你在target中加一個Run Script並將設定內容列出來
要注意的是這裡已經幫你在該專案中加了Crashlytics.framework
當你完成設定並build之後他就會進到接下來的步驟像是framework設置以及程式碼的增加
我覺得這個教學的步驟對新手而言可以保證他設定完成
但對有經驗的人可能有點多餘
另外提一下,Eclipse版在選完專案後甚至幫你把Androidmanifest.xml設定與程式碼加進去

設定完成後就可以開始故意讓程式crash來測試
此時crash就會出現在清單中了
根據個人測試,plugin上的crash清單反應似乎沒有web快,需要多等幾分鐘才會出現

點擊清單上的crash項目後會在瀏覽器上開啟該crash的詳細訊息
此時就可以依照錯誤訊息除錯囉

P.s. 尚未測試過,不確定NDK crash狀況是否可以正確呈現 
Evernote 幫您記住生活的點點滴滴,輕鬆保持條理。下載 Evernote。

2014/05/19

自製2048 for Chromecast

近日在看Chromecast的相關文件,發現他可以自己做receiver app
receiver app是以HTML5來製作  但由於有一些效能限制 所以製作時需要注意
只要符合條件  基本上也是可以做遊戲的
剛好最近很紅的2048是開源的  所以就以它來當作例子
其實2048已經有人移植到chromecast上了
但反正是要做一個測驗所以無所謂

以下是實際成品的聯結

其實做起來並不難,主要分為兩個部分(receiver and sender),基本API的用法就不贅述,可以看

receiver
由於2048遊戲部分不太需要去寫邏輯部分,故主要只要處理訊息的接收與發出即可
初始化部分:
在 application.js 中 window.requestAnimationFrame中加入
這裡我有一個部分是用偷懶的做法
window.senderId=event.senderId; 這裡將senderId放在window底下以便之後要回傳訊息使用
但個人覺得不是好的做法 但這是測試用的程式就先略過

鍵盤事件接收部分  在 keyboard_input_manager.js 中的KeyboardInputManager.prototype.listen方法中加入
將sender傳送過來的訊息對應該做的行為

當玩家無法再移動或者是已達到2048的時候都會有訊息出現,在這種狀況下可以回傳訊息給sender出現相對應的操作界面,為此修改html_actuator.js如下

sender
這裡我做了兩個平台的sender程式,其實主要也是改google的範例程式
chrome版主要就是把keyboard event send給receiver
android也是差不多, 只是把swipe的方向改為對應的key code傳給receiver
另外接收遊戲結束的訊息跳出對應的AlertDialog

或許下次可以試試看現有 html5遊戲引擎在chromecast上的效能



以下為參考資料

模擬器
模擬器感覺在自定receiver app的部分支援並不完整  實機測還是比較好
以下是目前有看到的模擬器

CR Cast (chrome 擴展)
Leapcast (python, run on chrome)
android 模擬  cheapcast (跑不起來)
rPlay on iOS


Developer Console
由於要自行開發receiver app所以需要開通Developer Console   
需要五元美金  如果只是要cast媒體就不需要

如圖,可以設置APP 與 測試用裝置
如果Application不是Published的話則要有輸入的裝置才能使用

目前已有的遊戲應用
下面有兩個已在 Google Play上架的應用
GamingCast (for Chromecast)
2048 Chromecast

Evernote 幫您記住生活的點點滴滴,輕鬆保持條理。下載 Evernote。

2014/04/08

Facebook comments 是否能在iOS用原生UI製作

這裡指的是social plugin中的comments
https://developers.facebook.com/docs/plugins/comments/
如果你不要add comment的話應該是做的到的

本次專案中有一個功能是可以對某個頁面做FB comment
在網頁中可以用Facebook的plugin
但在app當中SDK沒有提供相關的UI可供使用
要使用的話必須用UIWebView加上plugin來達成

後來在Facebook的graph api當中找到有關的功能
https://developers.facebook.com/docs/graph-api/reference/object/comments/
裡面有提到Reading與Publishing的功能

但由於我使用的ID是網頁網址所以必須改一下
[FBRequestConnection startWithGraphPath:@“/****** id *******/comments"
[FBRequestConnection startWithGraphPath:@"/comments/?ids=http://www.xxx.xxx.xx”

在Reading的部分沒有問題,但在Publishing的部分就會收到錯誤訊息
body =     {
        error =         {
            code = 100;
            message = "(#100) Comments may not be added to a comment plugin";
            type = OAuthException;
        };
    };

後來仔細查一下
發現原來這個功能是不能使用的
相關連結:
http://stackoverflow.com/questions/16810596/post-comment-via-graph-api-to-social-plugin-box
http://stackoverflow.com/questions/5673821/can-you-write-using-facebook-graph-api-to-a-web-sites-facebook-comment-module
https://developers.facebook.com/bugs/164794086987157

既然都提供了,為何不能使用呢,真猜不透啊

2014/04/07

iOS中播放youtube影片經驗

iOS不像android一樣有提供youtube的API,要播放youtube影片需要使用UIWebView + youtube iframe api

使用iframe api
"the current best practice for embedding YouTube videos in an iOS application is to use the YouTube iframe Player within a UIWebView container."
所以基本上這個方法應該是最好的方法,但由於使用iframe需要寫javascript,一開始因為我懶的關係,所以我先試過一些其他的程式庫,但我最後放棄了(見最後一段)

這裡面提供了相關API資訊

個人寫的讀取用js code

    
    
  • 由於autoplay參數無法用在mobile裝置, 所以如果要讀取自動播放就要在onPlayerReady中來做
  • 可以在onPlayerStateChange中取YT.PlayerState.ENDED事件來知道影片播放完畢
  • playerVars的playsinline是說播放時是要在指定範圍內還是要全螢幕播放(後來再是似乎已無用)
  • window.location = 'js-call://xxxxxx' 可在UIWebViewDelegate shouldStartLoadWithRequest中接收並處理
偷吃步 api

iOS 8 已無法使用

由於沒有提供API供使用,所以有些事件是取不到的,像是進入全螢幕以及離開全螢幕的事件,由於一般使用MPMoviePlayerController都是有notification可以使用,如MPMoviePlayerWillEnterFullscreenNotification以及MPMoviePlayerWillExitFullscreenNotification,但經由UIWebViewController播放的影片並不會有這兩個事件發生,故在這裡必須要用私有API,會有被reject的風險,但值得試試看

取得UIMoviePlayerController
除了事件取不到以外,也沒有辦法可以以程式去控制是否為全螢幕,由於知道底層仍然是使用UIMoviePlayerController,所以如果可以取得到的話就可以使用setFullscreen方法來控制

這個連結提供一個做法去取得該物件,但其實我試了似乎沒效,但可以發現到裡面有FigPluginView的存在(詳細請見下一段),查找資料確認仍有UIMoviePlayerController在其中只是沒有提供方法取用,後來找到一個可行的做法就是藉由NSNotification的callback method來取得
-(void) myMovieEnterFullScreen: (NSNotification*) aNotification
{
    moviePlayer = aNotification.object;
. . .
當然這樣做還是得要用到上一段說到的私有API

quick time plugin 與 player controller
上一段當中有提到我在UIWebView當中找到一個FigPluginView的存在
這個物件與UIWebView, MPMoviePlayerController的關係可見以下連結
詳細說明了播放youtube影片的底層還是使用MPMoviePlayerController

曾試用過的library

一開始可以用, 它的作用是幫你抓出youtube實際的播放串流URL,剛開始的時候採用(2月初),但大約3月時發現不能用了,似乎是資料格式有變動,由於這方面我並不熟所以放棄使用
原理同上,一開始就不能用
幫UIWebView加上Category讓你方便播放,但只有陽春功能且非使用iframe故放棄


20140502

UIWebView的相關設定


mediaPlaybackRequiresUserAction --- 是否可自動播放或經用戶控制
allowsInlineMediaPlayback --- 是否可以inline
mediaPlaybackAllowsAirPlay --- 是否有airplay功能

inline的播放行為

經測試如果inline時點擊播放會自動全螢幕播放
但如果使用js呼叫player.playVideo()則不會變成全螢幕
Evernote 幫您記住生活的點點滴滴,輕鬆保持條理。下載 Evernote。

2013/12/30

使用cocos2d-x實作Post Processing

上次做了一些想做的shader效果
這次主要研究在cocos2d-x上如何實現Post Processing

主要的參考資料如下

裡面主要以OpenGL語法來製作,大概步驟如下
  1. 建立texture
  2. 建立post processing用的framebuffer
  3. 將步驟2的framebuffer作為步驟1的texture資料
  4. 在post processign framebuffer上繪圖
  5. 將步驟1的texture搭配post processing shader繪圖出來
在cocos2d-x中,因為有提供RenderTexture類別,所以我們可以不用處理那麼多步驟。
基本上只要建立起RenderTexture,就可以用getSprite()->getTexture()來取得與步驟1~3相同效果的texture。
步驟4則可以藉由在RenderTexture的begin()與end()中加入要繪圖的物件的visit()來達到。
而步驟5則只要將取出的texture用來建立新的sprite,並在該sprite上加上shader就可以了。

下圖為使用cocos2d-x實作上面連結的效果
右下有按鈕可以切換是否使用Post Processing


2013/12/26

cocos2d-x中實作幾個shader效果

在之前的專案中有機會使用shader實做了mask效果
這次將之前曾經想要做但是專案不願意給時間嘗試的做法試著做出來

清單如下
  • 圖片轉灰階
          cocos2d-x中,sprite的setColor在設定顏色後基本上還是留有本來圖片跟設定顏色混合而已,這個做法是單純的轉灰階
  • 圖片加邊框
          有一次專案的需求是希望可以幫圖片在邊緣加上指定顏色的邊框,後來的作法是另外提供圖片,但如果有20張圖有這個需求就需要額外作20張圖,用shader就比較省事
  • 全畫面遮罩
          另一次專案的需求是希望玩家可以專注於某個功能的使用,想要將其他部分打暗只留該功能按鈕的部分是亮的;這裡使用layer製作,可以自行指定focus的位置
  • 背景填滿
          之前在做背景時都用sprite去拼,實際上物件很多,且容易造成有接縫,如果要移動也麻煩,用shader還滿方便,一樣是用layer去做
目前只有在win32版跑過
用的是vs2013

2013/12/09

使用HTML5製作投影片

由於最近面試有一間公司需要你用投影片去展示一下過去的經歷
看了他的工作需求有對HTML5/CSS3等熟悉的條件
雖然我不是很熟但想說如果用個有關係的做法來呈現也是不錯
(後來發現不是必要)
查了一下後決定用HTML5來做投影片
看到下面的網站
http://www.sitepoint.com/5-free-html5-presentation-systems/
裡面有介紹五個演示系統
後來我決定用reveal.js

成果如下
https://dl.dropboxusercontent.com/u/10581994/reveal.js-master/cv.html

我覺得它有快速鍵可以用
esc可以看全部投影片
f可以切換全螢幕
還有轉換成pdf的功能十分不錯
有需要的可以用一下

唯獨預設的文字感覺較適合英文
如果要用在中文上需要在css中修改一下
像我是加上黑體來用
另外如果是舊一點的電腦換頁動畫可能會有一點delay的狀況

2013/11/14

45度角地圖 Z-Sort 實作

Demo:https://dl.dropboxusercontent.com/u/10581994/ZSortTest/index.html
Github:https://github.com/hsienwei/zSort_cocos2dx_html5

2014/01/16:cocos2d-x 2.2.2已修正此問題
2013/11/24 : 目前在chrome中會無法顯示(火狐可以), 為cocos2d-x html5的bug

這個專案主要是以cocos2d-x html5版本來實作一個我之前在工作中使用的45度角地圖Z-Sort演算法,一來練習cocos2d-x html5,一來為之前的工作內容做一個記錄。

開啟後一開始的狀況是沒有使用演算法排序的狀況,單純依照加入的順序去排序,按下"Sort"後就會依照演算法的結果為各個Sprite設定Z值。

當初主要導入這個做法的是我同事,我只是後來有在稍微修改
演算法參考網頁:http://wgcode.iteye.com/blog/847695

Sprite沒有使用圖,直接用drawingUtil來繪圖,發現用手機來看的話線條會沒辦法出來,也許是一個bug,也有可能是因為手機部分還沒有完善。

另外在點擊事件上也有一點問題,導致必須做很多處理才能達到縮放後也可以正確點擊,不確定這是我的用法錯誤還是這部分本身還不完整,可參照 https://github.com/hsienwei/zSort_cocos2dx_html5/blob/master/src/myApp.js   Line 53

2013/11/13

Unity練習:夜市彈珠台

Demo:https://dl.dropboxusercontent.com/u/10581994/pinball/pinball.html
Github:https://github.com/hsienwei/pinball_unity

玩法就是按一下滑鼠左鍵放球,再按著滑鼠左鍵蓄力,放開後發射,當球都打完後按一下滑鼠左鍵會讓球掉到下面重來。

感覺上沒有花太多時間在寫程式,反而弄Model跟動作的處理比較花時間。

物理部分就完全用Unity內建的功能,主要只有調整Physic material來做到彈珠打到釘子會有彈回的效果,另外有將Time.fixedDeltaTime調小,不然速度快的時候球會飛出去,或者物理的行為不精準。

動作部分,球台下面的檔板基本上使用3ds Max中作的動畫,發射的動畫本來也是要用3ds Max來做,但是由於放到Unity中位置會跑掉,所以後來直接用Unity的Animation來處理。

Shader部分由於本來美術就不是專長,所以直接用一個內建的shader;另外沒有2D介面,之後再來試試看4.3的2D功能。

2013/10/02

cocos2d-x mask 作法嘗試

這裡指的mask是說一張圖但我要將指定一部分挖掉這樣,我在做的時候都是以一張圖為主圖,另一張mask圖以alpha值指定要挖空的地方

目前有試過兩種做法
1. RenderTexture + BlendFunc
大概程式碼如下
CCSprite* createMaskSprite()
{
    cocos2d::ccBlendFunc bf;
    bf.src = GL_DST_ALPHA;//GL_ONE_MINUS_DST_ALPHA;
    bf.dst = GL_ZERO;

    CCSprite* selfSprite = /*主圖的sprite*/;
    CCSprite* maskSprite = /*mask圖的sprite*/;
    selfSprite->setPosition(ccp(selfSprite->getContentSize().width/2, selfSprite->getContentSize().height/2));
    maskSprite->setPosition(ccp(maskSprite->getContentSize().width/2, maskSprite->getContentSize().height/2));
    
    selfSprite->setBlendFunc(bf);
    
    CCRenderTexture *rt = CCRenderTexture::create((int)selfSprite->getContentSize().width, (int)selfSprite->getContentSize().height);
    rt->beginWithClear(0, 0, 0, 0);
    maskSprite->visit();
    selfSprite->visit();
    rt->end();
    
    CCSprite *retval = CCSprite::createWithTexture(rt->getSprite()->getTexture());
    retval->getTexture()->setAntiAliasTexParameters();
    retval->setFlipY(true);
    
    return retval;
}

主要是使用BlendFunc的方法,在RenderTexture畫出想要的效果之後再使用,但如果只直接用BlendFunc可能會被其他的sprite影響產不出想要的效果

2. Shader
Shader程式碼處理起來比較麻煩,建議看cocos2d-x範例程式的shader部分
下面是我寫的一個小範例
https://github.com/hsienwei/shader_cocos2dx

cocos2d-x的部分主要是參考範例程式改的
重要的是shader部分

#ifdef GL_ES
precision mediump float;
#endif

varying vec4 v_fragmentColor;
varying vec2 v_texCoord;

uniform sampler2D u_texture;
uniform sampler2D u_mask;

void main() {
    vec4 mainColor = texture2D(u_texture, v_texCoord);
    vec4 maskColor = texture2D(u_mask, v_texCoord);
    vec4 srcColor = vec4(mainColor.r * maskColor.a,
                         mainColor.g * maskColor.a,
                         mainColor.b * maskColor.a,
                         mainColor.a * maskColor.a);
    
    gl_FragColor = srcColor;
}
將主圖的rgba值都乘以mask圖的alpha值即可,要達到這個效果只要動Fragment Shader即可

2013/10/01

剖析HTML資料轉為JSON

之前有一陣子很迷Puzzle & Dragon,所以常常查閱http://zh.pad.wikia.com/wiki/ 這個wiki網站,有一次用手機查的時候感覺他的手機板介面不太方便,而且如果可以用該資料為基礎讓手機通知我事件發生似乎不錯,所以就開始寫一個parser來處理網頁資料,把"緊急/降臨時間表"與"活動時間表"取需要的資料處理為JSON格式。

結果大概如下:

那時候的大概想法是這樣:
用server跑一個排程,定時更新資料並用手機去取用。

Server端主要使用GAE,主要原因在我對server管理沒有經驗,用GAE我可以跳過server設定這一塊,Java基本上也是很熟了,所以寫起來沒啥問題,只是要了解一下CRON的排程設定。

剖析程式庫那時候選擇了http://jsoup.org/,使用上並不難,基本上就是實作NodeVisitor,然後使用head與tail方法的Node參數來判斷要取的資料,只是那時候有無法取執行javascript的問題,所幸影響不大,所以基本上就是取網頁程式碼,曾經有試過用JavaUnit想要取執行完javascript的網頁但還是失敗,所以這部分我後來就沒處理,JSON部分就直接用Java的JSONObject即可。

另外一個問題就是由於wiki資料由眾人維護,沒有一個既定格式,常常會有變更;取資料也不方便,沒有類似id的東西可以辨識,最後只好用標題來找,再取相對應的結構部分。

最後因為專案太趕就沒時間再進行,後來再去查已經有人出了一個相似但各方面都比較好用的APP,似乎沒有做的必要了。

2013/08/21

John Resig's Javascript inheritance


在上UDACity的HTML5 Game dev以及在看cocos2d-x HTML5時都看的到的一個東西
John Resig的 Javascript inheritance連結

http://ejohn.org/blog/simple-javascript-inheritance/

javascript本身沒有繼承的概念
使用這樣的pattern可以取得類似的效果

2013/08/15

使用ant編譯apk檔

在一般的狀況下最為人所知產出apk的方法是使用ADT eclipse plugin功能來產出APK檔 
(Android Tools->Export Signed/Unsigned Application Package)
但除此之外android也提供開發者經由ant產出apk檔
mac中有內建ant
所以可以在mac的終端機下指令來產出apk檔

那為何要使用ant
如果今天要產出多種版本 你必須要打開你的eclipse分別打開多個專案然後Export Signed/Unsigned Application Package
等於同樣步驟要作三次
而且還需要輸入密碼
而且你必須待在電腦旁邊

如果今天用ant來編的話  你可以指定一次編多種版本  也不用在輸入任何東西(前提是有寫到設定檔)
像我之前有產出10個檔案的需求(五個market api * 2(debug/release))
通常都要離開公司時執行
隔天就可以寄出檔案了

以下寫一些在cocos2d-x中使用ant的經驗
使用cocos2d-x建立的android專案中
會比一般的android project多出以下的檔案
build.xml - ant使用的專案設置
local.properties - 裡面會有sdk的路徑設定值
ant.properties - 預設是空的  但可以在這裡設置編apk檔時使用的key相關設定
要注意的是如果你的android專案有使用其他的android專案當作library
那個專案也需要有這三個檔案

編譯的方式是在終端機下指令
ant <target>
如果沒有給target的話  會跑設定的預設target

在build.xml當中會匯入另一個custom_rules.xml,如果沒有的話就不會處理custom_rules.xml
<import file="custom_rules.xml" optional="true" />
在這裡的註解中有提到你可以在custom_rules.xml使用的target
-pre-build
-pre-compile
-post-compile (This is typically used for code obfuscation.
               Compiled code location: ${out.classes.absolute.dir}
               If this is not done in place, override ${out.dex.input.absolute.dir})
-post-package
-post-build
-pre-clean
基本上就如同target的名稱一樣 你在哪個階段有需求就去寫那個target


比方說我有需求是將編出來的檔案集中到一個資料夾中並讓檔名出現編譯時間, 版本資訊
所以我用到-post-build 內容如下
<target name="-post-build">
      <tstamp>
          <format property="package.time" pattern="yyyyMMdd_HHmm"/>
      </tstamp>
      <property name="apk.copy.name" location="../android_build_apk/${ant.project.name}_${apk.tag}_${build.android.param}_${package.time}.apk" />
      <echo>copy ${out.final.file}</echo>
      <echo>to   ${apk.copy.name}</echo>
      <copy file="${out.final.file}" tofile="${apk.copy.name}"/>
</target>

上面這個target會將編譯產出的apk複製到指定目錄並變更檔名
build.android.param 這個property是設定編譯時是測試版(debug)還是正式版(release)
apk.tag是我設定在ant.properties中用來表示這是那個市場的版本
這樣產出來的檔名會是project.name_xxx_release_20130705_1453.apk的樣子

如果是產出signed Application Package
在編譯的過程中會要求你輸入key的相關資訊
表示你產出多個檔的話就要輸入多次
其實可以把相關需要的參數設定到ant.properties中
就不需要輸入了
詳細的參數名稱可以參閱${sdk.dir}/tools/ant/build.xml
看看需要哪個property
我的狀況如下
key.store=../libs/android/keystore/igsgames.keystore
key.alias=xxx
key.store.password=xxxxxxxx
key.alias.password=xxxxxxxx
apk.tag=gplay
這樣可以不用每次輸入
但相對表示你把密碼打在檔案中給人看
所以你可以在執行ant時使用-Dproperty="xxx"這樣的方式輸入property
就不會有這樣的問題了

用ant其實還滿方便但是資料不太多
除了ant in action這本書外就是網站資料
另外在Android Studio中使用Gradie又是不同的系統
不知道下個專案還會不會有機會用ant


2013/08/06

cocos2d-x i9100 音效播放當機問題

問題描述

使用版本cocos2d-x 2.1.3
特定機型 i9100音效播放時當機

錯誤訊息

I/DEBUG (13020): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
I/DEBUG (13020): Build fingerprint: 'samsung/GT-I9100/GT-I9100:4.0.4/IMM76D/ZSLPQ:user/release-keys'
I/DEBUG (13020): pid: 14187, tid: 14200 >>> xxx.xxxxxx.xxxx <<<
I/DEBUG (13020): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000000
.....
I/DEBUG (13020): #00 pc 00521476 /data/data/xxx.xxxxxx.xxxx/lib/libgame.so (_ZN12OpenSLEngine16setEffectLoopingEjb)
I/DEBUG (13020): #01 pc 00521dfa /data/data/xxx.xxxxxx.xxxx/lib/libgame.so (_ZN23SimpleAudioEngineOpenSL10playEffectEPKcb)

經查詢後發現cocos2d-x引擎在i9100上使用OpenSL(僅有這一隻)   故只有i9100出現此問題


修改方式

先說這不是個好做法

OpenSLEngine.cpp

void OpenSLEngine::setEffectLooping(unsigned int effectID, bool isLooping)
{

if(sharedList().find(effectID) == sharedList().end()) return;   <--add add--="" this="">

SLresult result;
vector* vec = sharedList()[effectID];
assert(NULL != vec);

// get the first effect player that to be set loop config
vector::iterator iter = vec->begin();
AudioPlayer * player = *iter;

主要原因應該是sharedList()[effectID];取vector*時沒有該key的物件
但是vector這樣取會自行幫你產生一個物件
但該物件雖然不是NULL(故可避過assert檢查)又不是有效的物件
才會造成當機

引發的原因查詢後認為是如  http://www.cocos2d-x.org/boards/6/topics/26439 網頁上所講的一樣
因為i9100有音效數量限制所引發
之所以說這不是好做法是因為應該要減少使用音效數
或者作動態載入
緊急的狀況下只能先這樣做
但這樣做會有一些音效播不到

2013/07/08

GCM在無該服務的例外狀況


問題:
把目前運行測試正常的檔案送給大陸廠商,卻發現無法進入遊戲

解答
後來弄到了出現問題的手機運行後發現下面的錯誤訊息
Caused by: java.lang.UnsupportedOperationException: Device does not have package com.google.android.gsf
E/AndroidRuntime( 787): at com.google.android.gcm.GCMRegistrar.checkDevice(GCMRegistrar.java:98)
須處理沒有該服務時例外狀況

重點在於大陸手機多沒有google服務
所以GCM部分需要處理 UnsupportedOperationException

所以
1. 在用google相關服務時須要考慮沒有的狀況
2. 相關服務須要找替代品(金流是很好找  但推播就真的比較少聽過了)


2013/05/31

Android 問題集錦

From Evernote:

Android 問題集錦

Clipped from: http://developer.android.com/guide/topics/manifest/uses-feature-element.html
1.
問題:
一次更新後,所有純平版裝置都無法在Google Play中看到該App,該次更新主要提供使用簡訊小額付費機制

解答:
因為簡訊寄送需要增加SEND_SMS這個Permission,連帶會自動將android.hardware.telephony這個feature設為需求
解法為在 androidmanifest中增加 <uses-featureandroid:name="android.hardware.telephony"android:required="false"/>

2.
問題:
遊戲當中並沒有使用到menu鍵,但是只要手機沒有實體menu鍵的話都會出現虛擬menu鍵

解答:
之前我沒有設定targetSdkVersion,由於targetSdkVersion預設等於minSdkVersion,而我設定的值為9,被判定為legacy,則會顯示虛擬menu鍵
targetSdkVersion設為14後則解決

3.
問題:
targetSdkVersion換成14後的測試期間,發現home鍵與power鍵兩種進入讓遊戲進入背景的方法的行為不同

解答:
解說的十分詳細
我的設定是orientation 修改後解決

4.
問題:
更新Android SDK Tools為22版後,發現無法產生R檔,出現"Error executing aapt.Please check aapt is present at /android-sdk/platform-tools/aapt"

解答:
Android SDK Tools 22有問題   aapt被移到其他路徑但是設定沒有改到
網路找的解法
我自己的做法是使用21版先不要升級