tag:blogger.com,1999:blog-98735452024-02-02T18:01:32.981+08:00Whilerain Studio徊雨工作室Anonymoushttp://www.blogger.com/profile/10433873918988135141noreply@blogger.comBlogger36125tag:blogger.com,1999:blog-9873545.post-76000192862860468312016-04-12T15:01:00.001+08:002016-04-12T15:01:11.720+08:00如何處理Android切圖<br />
<h2>簡述</h2><br />
<p>因為Android系統特性關係,及裝置機種繁多,為了減輕設計師的負擔,讓設計師專注於流程與介面設計,而不浪費時間在處理切圖,Android工程師需要學習如何自己簡易的處理切圖。</p><br />
<h2>Android排版策略</h2><br />
<p>基本上Android的切圖排版策略分為二種:</p><br />
<ol><li>只使用一套切圖,在各種裝置上以Scale的方式排版</li>
<li>將切圖分為mdpi, hdpi, xhdpi, xxhdpi, xxxhdpi等數套圖</li>
</ol><br />
<p>使用哪種策略端看設計師所繪的設計圖而定,當面臨的設計圖看起來在各種不同尺寸的配備當中,缺乏彈性調整的空間時,或是講求位置精確的設計圖當中,我們會選用一套切圖,並以縮放的方式將圖定位在正確的位置上。例如在Android Animation Desk Classic上的排版就較適合使用一套切圖縮放的方式處理。這樣做的好處是,只要準備一種圖,且size容易計算。這種方式會需要考慮所可能使用最大解析度的裝置,來作為切圖的範本,如果以小的裝置來做設計時,當圖片放大時會產生圖片模糊的問題。另一個問題是當排版複雜時,這可能會耗費額外的運算資源在處理排版的縮放。</p><br />
<p>在具有彈性空間配置的設計圖,則最好能使用第二種方法,將套圖分為不同dpi的套圖。例如在NoteLedge Cloud和PDF Reader當中使用此方法。既然已經分為不同解析度的圖,就不應該在把這種圖進行任何縮放,也不需要擔心圖片模糊的問題。但需要較耗費時間處理各種解析度的切圖。</p><br />
<p>並非一個專案只能使用1或2其中一種方式,而是應依照排版設計,來做適當的選擇。同一個畫面也可能需要同時使用兩種方法來進行排版,端看介面需求而定。</p><br />
<h2>設計師著手設計前</h2><br />
<h3>思考在不同裝置的樣子</h3><br />
<p>設計師在開始著手設計介面之前,得先思考這個App在不同大小的裝置上,應該如何做介面適應,最好的設計是同一張設計圖得以運用在不同尺寸的平板或手機,或只要做行列數的調整,或只要版面位移就能做好不同裝置的適應。</p><br />
<p>考慮 48 rhythem,這是設計師應該了解的最重要概念,如果一個按鈕在手機上是48dp,在平板上也應該是48dp。另外48dp 是適合手指按壓的適切大小。大部分按鈕應大於48dp,不會因為螢幕小,按鈕就小。</p><br />
<p>參考資料: <br /><br />
<a href="https://www.google.com/design/spec/layout/metrics-keylines.html#">UI Metrics & keylines</a></p><br />
<p>考慮哪個尺寸的裝置可能是最主要的使用者來源,選定介面設計的尺寸,並告知工程師,這個設計圖是使用哪個尺寸哪個density來設計的,例如選用Nexus 4為範本來設計時,其尺寸為768 x 1280 且density 為 xhdpi。裝置尺寸可以參考Device Matric網頁。</p><br />
<p>參考資料: <a href="https://design.google.com/devices/">Device Matric</a></p><br />
<p>選定設計圖裝置後,依上例設計師應以768 x 1280 為底開始設計,此時設計師在此設計圖中所設計的元件大小為解析度xhdpi的大小,設計師可以利用工具計算出所繪的元件pixel,實際上在xhdpi裝置上dp是多少,然後提供給工程師。Android工程師通常在元件的大小會使用dp為單位而非px。如此一來工程師就能自己產生所需要的圖。</p><br />
<p>參考資料: <a href="http://developer.android.com/intl/zh-tw/guide/practices/screens_support.html">Supporting Multiple Screens</a></p><br />
<p>參考資料: <a href="http://pixplicity.com/dp-px-converter/">dp/px converter tool</a></p><br />
<h2>dp v.s. px</h2><br />
<h2>設計師切圖</h2><br />
<h3>一般的按鈕切圖(單色,正方形)</h3><br />
<p>設計師提供給工程師切圖時,需要考慮到所提供的圖,支援的最大解析度所需的還大,這樣一來工程師自己製作套圖時才不會有模糊的情況。譬如即使是在xhdpi上設計的圖,設計師要計算出在xxxhdpi上需要多大的圖。至少提供給工程師比xxxhdpi大的圖或相等的圖即可。只要這張圖是單色,工程師就可以利用這張圖來產生不同dpi的套圖。</p><br />
<p>如果是使用Material Icons當中的圖示,設計師甚至可以提供icon名稱請工程師自行下載或使用<a href="http://shreyasachar.com/AndroidAssetStudio/">Android Asset Studio for material design</a>來製作就好。</p><br />
<p><a href="https://design.google.com/icons/">Material Icons</a></p><br />
<h3>不同顏色的切圖</h3><br />
<p>如果因點擊效果而需要不同顏色或透明度的切圖時,只要這張圖示是單色,則不需另外提供切圖,只要告知16進位色碼及透明度,工程師可以自行使用工具產生。</p><br />
<h2>工程師的產生切圖工具</h2><br />
<ul><li><a href="https://romannurik.github.io/AndroidAssetStudio/">Android Asset Studio</a></li>
<li><a href="http://shreyasachar.com/AndroidAssetStudio/">Android Asset Studio for material design</a></li>
</ul><br />
<p>上述兩項工具具有相同功能,第二項則內建了官方Material Design的圖示。有了上述工具,工程師能夠自己建立所需要的icon套圖,自定顏色、透明度和icon大小。</p><br />
<p>在Android Studio當中也有相同的工具,在module name按下右鍵 > New > Image asset 可以進行相同的切圖產生。</p><br />
<p>這個工具仍有其限制,就是當所要產生的切圖不是正方形時,上述工具就無法使用,目前仍未找到適當的工具,因此這時候仍然需要設計師幫忙。</p><br />
<h2>程式當中直接變更Image顏色</h2><br />
<p>執行期間動態變更image顏色</p><br />
<pre><code>imageView.setColorFilter(Color.argb(255, 255, 255, 255)); // White Tint
</code></pre><br />
<p>在XML當中設置變更圖片顏色</p><br />
<pre><code><ImageView id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:tint="#FF000000"
android:src="@drawable/chat_icon"/>
</code></pre><br />
<p>依點擊事件處理圖片顏色</p><br />
<p><a href="http://stackoverflow.com/questions/19500039/how-to-use-selector-to-tint-imageview-in-android">How to use selector to tint imageview in android</a></p><br />
<h2>Vector assets 和 SVG圖示</h2><br />
<p>仍然有一些情況,不適合以上面的方式來處理圖片,例如不是作為按鈕的較大張說明用圖,像是用在Splash 畫面的圖示、不是長方形且大張需隨畫面調整大小的圖、或一些功能介紹圖這些情況會較適合以向量圖示來處理。[Tip: 按鈕通常不會隨裝置大小而變更大小,但介紹用的圖示會需要,所以按鈕icon不需使用向量圖示,但介紹用圖示需要]。</p><br />
<h3>Vector assets</h3><br />
<p>Vector asset是以xml來定義向量圖型的格式,需注意<font color="red">只支援Android 4.4 (API level 20) 及以後的版本</font>。使用Android Studio中的Vector Asset Studio來製作出向量圖xml,並將xml放在drawable文件夾當中,使用時就和圖片資源使用方式一樣。</p><br />
<pre><code><ImageButton
android:id="@+id/imageButton"
android:src="@drawable/ic_build_24dp"
android:tint="@color/colorAccent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/textView2"
android:layout_marginTop="168dp" />
</code></pre><br />
<p>參考文件:<a href="http://developer.android.com/intl/zh-tw/tools/help/vector-asset-studio.html">Vector Asset Studio</a></p><br />
<h3>使用SVG</h3><br />
<p><a href="http://developer.android.com/intl/zh-tw/tools/help/vector-asset-studio.html">Vector Asset Studio</a>也能夠直接將svg格式的文件轉換成Vector assets格式,因此設計師提供向量圖型時只需要提供常見的SVG給工程師即可。</p><br />
<h3>支援Android 4.4以前版本</h3><br />
<p>若需要使用向量圖片支援4.4以前的版本則需使用到其他資源庫,例如<a href="https://code.google.com/archive/p/svg-android/">svg-android</a></p>Anonymoushttp://www.blogger.com/profile/10433873918988135141noreply@blogger.com0tag:blogger.com,1999:blog-9873545.post-18505447384980236652014-05-20T14:38:00.000+08:002014-06-16T17:45:30.829+08:00Corner HUD 介紹<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGtt8xSnEzFiIgBiZLJNg5fkMv_-Rpddq7SPyK3kSesXuGk5H98HcQIkUNcodJVbBEBrvC-Rxc-gZz9Srxntq6cPnyRVI72N9009waTSHXZsY6XO8FA0iXAFj1BcC6v6wKa6rZ/s1600/big.png" imageanchor="1"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGtt8xSnEzFiIgBiZLJNg5fkMv_-Rpddq7SPyK3kSesXuGk5H98HcQIkUNcodJVbBEBrvC-Rxc-gZz9Srxntq6cPnyRVI72N9009waTSHXZsY6XO8FA0iXAFj1BcC6v6wKa6rZ/s640/big.png" /></a><br />
<br />
<div class="p1">
<span class="s1">首先到Google Play搜尋Corner HUD就找的到這個App,</span></div>
<div class="p1">
<span class="s1">這是一個抬頭顯示的導航應用,</span></div>
<div class="p1">
<span class="s1">只要切換到HUD 模式把手機放擋風玻璃下方,</span></div>
<div class="p1">
<span class="s1">手機的畫面就會投射到擋風玻璃上,</span></div>
<div class="p1">
<span class="s1">當然你也可以不使用HUD模式直接看,</span></div>
<div class="p2">
<span class="s1"></span><br /></div>
<div class="p1">
<span class="s1">這個App和Navier HUD這個App風格很像,因為作者都是我...</span></div>
<div class="p1">
<span class="s1">只是Navier HUD當初只畫出行走的路線,</span></div>
<div class="p1">
<span class="s1">沒有其他道路,因此希望藉由開發這個App</span></div>
<div class="p1">
<span class="s1">來補足當初還沒完成的功能,</span></div>
<div class="p1">
<span class="s1">當然Navier HUD還是有這個App所沒有的特色。</span><br />
<span class="s1"></span><br />
<a name='more'></a><span class="s1"><br /></span></div>
<div class="p2">
<span class="s1"></span><br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDWz05U4X1QdHlae1r69qe_StvMZPE2b3Q0xCt8YkxKIu5p9-bpstuz4IQEeC8Sjl99VOkc-lsOZVhnvKDr7xRIardChAAobCEl7SDvbZ7_HqFKwsUKnCyJ7Z9syilW4qxBLqV/s1600/output_ZA607k.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDWz05U4X1QdHlae1r69qe_StvMZPE2b3Q0xCt8YkxKIu5p9-bpstuz4IQEeC8Sjl99VOkc-lsOZVhnvKDr7xRIardChAAobCEl7SDvbZ7_HqFKwsUKnCyJ7Z9syilW4qxBLqV/s1600/output_ZA607k.gif" height="400" width="223" /></a></div>
<div class="p2">
<br /></div>
<div class="p1">
<span class="s1">安裝完成後,執行App時需要有開啟網路和GPS,</span></div>
<div class="p1">
<span class="s1">執行後會開始下載附近的地圖,</span></div>
<div class="p1">
<span class="s1">畫面左下角旋轉的四方體是功能選單,</span></div>
<div class="p1">
<span class="s1">這個旋轉的四方體過一分鐘後會消失,</span></div>
<div class="p1">
<span class="s1">只要在點選一下畫面任何地方,就會再出現</span></div>
<div class="p2">
<span class="s1"></span><br /></div>
<div class="p1">
<span class="s1">左上角是狀態提示小圖示,</span></div>
<div class="p1">
<span class="s1">提示現在是”畫面跟隨目前位置”及”亮度設為最亮”</span></div>
<div class="p1">
<span class="s1">其他還有”HUD模式” “導航中”的小圖示,</span></div>
<div class="p1">
<span class="s1">但目前沒有顯示</span></div>
<div class="p2">
<span class="s1"></span><br /></div>
<div class="p1">
<span class="s1">有下方是車速,中央是目前的位置、朝向、經緯度和位置精確度,</span></div>
<div class="p1">
<span class="s1">背景橘色線條是路網、深灰色是重要建築或區域</span></div>
<div class="p1">
<span class="s1">可以依照使用情況橫向或直向來使用</span></div>
<div class="p1">
<span class="s1">地圖可以用手指移動,以及雙指縮放(縮放幅度不大)</span></div>
<div class="p1">
<span class="s1">**第一次下載該區域圖資會較久,下載完會存在手機資料庫中,</span></div>
<div class="p1">
<span class="s1">下次移到這個區域就會比較快顯示</span></div>
<div class="p2">
<span class="s1"></span><br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTumW5HsiGgWZmE5f4QF7UuG8-9VydOkdhrA6JIR7QEOfEyAYa1dekUuY2gW8vR4sfMrd8nI6SN8FjLTKigqRSnh25zYdkF81AC6qarhzhYM_l4zfQ4bL9C4bRf_doE19qPDle/s1600/output_U5p9iB.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTumW5HsiGgWZmE5f4QF7UuG8-9VydOkdhrA6JIR7QEOfEyAYa1dekUuY2gW8vR4sfMrd8nI6SN8FjLTKigqRSnh25zYdkF81AC6qarhzhYM_l4zfQ4bL9C4bRf_doE19qPDle/s1600/output_U5p9iB.gif" height="400" width="223" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="p2">
<br /></div>
<div class="p1">
<span class="s1">點下旋轉的四方體後,</span></div>
<div class="p1">
<span class="s1">所有功能都藏在裡面,</span></div>
<div class="p1">
<span class="s1">最上方是功能選單,可以用手指頭左右滑動</span></div>
<div class="p1">
<span class="s1">包含”畫面鎖定目前位置””儲存的地點””HUD模式””風格編輯器””最大亮度””解鎖功能”</span></div>
<div class="p2">
<span class="s1"></span><br /></div>
<div class="p1">
<span class="s1">下方點”前往何處?”可以打開小鍵盤輸入地點,</span></div>
<div class="p1">
<span class="s1">右方麥克風圖示讓你可以用語音的方式來輸入地點,</span></div>
<div class="p1">
<span class="s1">輸入地點後,會找出與你輸入有關的底點。</span></div>
<div class="p1">
<span class="s1">這時候長按某個項目,可以把這個地點儲存下來,</span></div>
<div class="p1">
<span class="s1"><br />
</span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdnkTcl_UV6XH5caPIawEVo-raR93ScZEerdJgDVsm7r6CpaCP_GyiKL9njiFM9m6La00IYL7DlTM7MXqgmntWHd6yQxP4aq-agudsS5ogItWTBSoEXr_cSbQZk9O49Jrycv1b/s1600/output_T04W05.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdnkTcl_UV6XH5caPIawEVo-raR93ScZEerdJgDVsm7r6CpaCP_GyiKL9njiFM9m6La00IYL7DlTM7MXqgmntWHd6yQxP4aq-agudsS5ogItWTBSoEXr_cSbQZk9O49Jrycv1b/s1600/output_T04W05.gif" height="400" width="223" /></a></div>
<div class="p1">
<span class="s1"><br />
</span></div>
<div class="p1">
<span class="s1">點擊某個項目後,就會開始進行路線的規劃。</span></div>
<div class="p1">
<span class="s1">畫面會移至目的地去,等到規劃完成,</span></div>
<div class="p1">
<span class="s1">下方會出現規劃結果需要多久時間距離。</span></div>
<div class="p2">
<br />
<span class="s1"></span></div>
<div class="p1">
<span class="s1">點擊結果會顯示詳細的路線資訊,</span></div>
<div class="p1">
<span class="s1">下方有三個按鈕</span></div>
<div class="p1">
<span class="s1">左邊是縮小回到剛剛展開前的狀態,讓你可以再瀏覽地圖,</span></div>
<div class="p1">
<span class="s1">中間是開始導航,</span></div>
<div class="p1">
<span class="s1">旁邊是取消此次規劃。</span></div>
<div class="p2">
<span class="s1"></span><br /></div>
<div class="p1">
<span class="s1">按下導航之後,畫面會切換到目前位置,並鎖定在目前位置,</span></div>
<div class="p1">
<span class="s1">黃色的路線是規劃的導航路線,</span></div>
<div class="p1">
<span class="s1">在轉彎提示處會有白色旋轉的圈圈,</span></div>
<div class="p1">
<span class="s1">進入圈圈時,表示該準備轉彎了,並且會有轉彎語音提示。</span></div>
<div class="p1">
<span class="s1">這個圈圈會隨著車速而放大縮小,</span></div>
<div class="p1">
<span class="s1">當車速較快時,圈圈就比較大,轉彎提示就會比較早出現,</span></div>
<div class="p1">
<span class="s1">以免因車速過快,來不及轉彎。</span></div>
<div class="p1">
<span class="s1">因此只要跟隨黃色路線,就能到達目的地了。</span></div>
<div class="p1">
<span class="s1">畫面左側有一個x按下後可以取消這次導航。</span></div>
<div class="p2">
<span class="s1"></span><br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEif13UEY08QL8jcbzr6aWM1Ffvnt47wB7vExIGu1Y84zM9tuQr6h289i9z5ZqitfKkNA7x9kEx8xoaLXJjBQnyKmYSQ9ptAbk79JXmTcyw1X5BEgArCXkS9ZI1TRWa2HGm4IChI/s1600/output_HAHQ2I.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEif13UEY08QL8jcbzr6aWM1Ffvnt47wB7vExIGu1Y84zM9tuQr6h289i9z5ZqitfKkNA7x9kEx8xoaLXJjBQnyKmYSQ9ptAbk79JXmTcyw1X5BEgArCXkS9ZI1TRWa2HGm4IChI/s1600/output_HAHQ2I.gif" height="400" width="223" /></a></div>
<div class="p2">
<br /></div>
<div class="p1">
<span class="s1">在選單當中還有另外幾項,</span></div>
<div class="p1">
<span class="s1">“儲存的地點”是你常用到或是想要保留的地點,</span></div>
<div class="p1">
<span class="s1">長按項目則可以刪除該項目</span></div>
<div class="p2">
<span class="s1"></span><br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNkc5_I9qGNhF0MoevzkT9pJ_UlXrbUYSMuoCxIWXBZ53FvqQyuI0KqAxboEwR2D0O25eA6rsuEnuaXPWSqpo3l9HN367UevPcf9WxIehBYIqKmAIZhiMsXkk2Ms72705SqP5P/s1600/output_vmjuaa.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNkc5_I9qGNhF0MoevzkT9pJ_UlXrbUYSMuoCxIWXBZ53FvqQyuI0KqAxboEwR2D0O25eA6rsuEnuaXPWSqpo3l9HN367UevPcf9WxIehBYIqKmAIZhiMsXkk2Ms72705SqP5P/s1600/output_vmjuaa.gif" height="400" width="223" /></a></div>
<div class="p2">
<br /></div>
<div class="p1">
<span class="s1">“HUD 模式”可以把畫面上下相反,</span></div>
<div class="p1">
<span class="s1">這樣一來畫面投射到擋風玻璃時畫面才會正確。</span></div>
<div class="p1">
<span class="s1">可以由畫面的左上角狀態圖示來辨識現在是HUD模式還是一般模式</span></div>
<div class="p2">
<span class="s1"></span><br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQ0twbiV9yLQq87obKKqLjFFe_qto5Vc3yHcXGI1rV8CmXtqFbu7dCseANuWU5xri4mdPaVwXWlWyvscd2d-29_sp23uo18JEdAAnCfYtWKR2wZGn59JPmj8gMQQdBhseMHaLW/s1600/output_mozJSL.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQ0twbiV9yLQq87obKKqLjFFe_qto5Vc3yHcXGI1rV8CmXtqFbu7dCseANuWU5xri4mdPaVwXWlWyvscd2d-29_sp23uo18JEdAAnCfYtWKR2wZGn59JPmj8gMQQdBhseMHaLW/s1600/output_mozJSL.gif" height="400" width="223" /></a></div>
<div class="p2">
<br /></div>
<div class="p1">
<span class="s1">“風格編輯器”點下後,</span></div>
<div class="p1">
<span class="s1">可以選擇四種預設的風格,</span></div>
<div class="p1">
<span class="s1">也可以點選下方的+來新增自己的地圖風格,</span></div>
<div class="p1">
<span class="s1">想要編輯某個風格,只要長按選擇編輯,</span></div>
<div class="p1">
<span class="s1">就可以對該風格顏色或名稱進行編輯</span></div>
<div class="p2">
<span class="s1"></span><br /></div>
<div class="p1">
<span class="s1">”最大亮度”能夠調整畫面的亮度,</span></div>
<div class="p1">
<span class="s1">建議使用HUD模式時把最大亮度打開,</span></div>
<div class="p1">
<span class="s1">會更清楚。</span></div>
<div class="p2">
<span class="s1"></span><br /></div>
<div class="p1">
<span class="s1">目前“HUD 模式”和“風格編輯器”只開放給付費使用者,</span></div>
<div class="p1">
<span class="s1">(</span>經過思考後,已經把HUD模式開放免費使用,<br />
<span class="s1">希望各位使用愉快 :))</span></div>
<br />
<div class="p1">
<span class="s1">付費只要點選最後的解鎖功能進行購買就行了</span></div>
<div class="p1">
<br /></div>
<div class="p1">
希望各位能喜歡Corner HUD</div>
Anonymoushttp://www.blogger.com/profile/10433873918988135141noreply@blogger.com0tag:blogger.com,1999:blog-9873545.post-7905667463023733092014-05-16T09:51:00.001+08:002014-05-19T16:11:26.950+08:00Corner HUD is available on Google Play<div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;">Corner HUD available on Google Play</div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: center;"> <a href="https://play.google.com/store/apps/details?id=com.whilerain.holomap"><img alt="Get it on Google Play" src="https://developer.android.com/images/brand/en_generic_rgb_wo_60.png" /></a> </div><div class="separator" style="clear: both; text-align: center;"><object height="360" width="640"><param name="movie" value="//www.youtube.com/v/N1Hjh9uhd54?hl=zh_TW&version=3"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="//www.youtube.com/v/N1Hjh9uhd54?hl=zh_TW&version=3" type="application/x-shockwave-flash" width="640" height="360" allowscriptaccess="always" allowfullscreen="true"></embed></object></div>Anonymoushttp://www.blogger.com/profile/10433873918988135141noreply@blogger.com0tag:blogger.com,1999:blog-9873545.post-24028810166881829882014-03-19T10:50:00.002+08:002014-03-19T11:00:15.920+08:00Holo style : the Android style<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJVXUpDei9bLphMDVGqY8FxBeQ35boH5AbAgiDoF6t-jwB1ffC7ihu3gVc9-VGtePyUzWJRvpW8slaqosSPIhO1_9J1vVejvZgU8sG-522vKXhcwMj_0mTmokF7zudJ_ePmW9w/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7+2014-03-19+%E4%B8%8A%E5%8D%8810.54.05.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJVXUpDei9bLphMDVGqY8FxBeQ35boH5AbAgiDoF6t-jwB1ffC7ihu3gVc9-VGtePyUzWJRvpW8slaqosSPIhO1_9J1vVejvZgU8sG-522vKXhcwMj_0mTmokF7zudJ_ePmW9w/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7+2014-03-19+%E4%B8%8A%E5%8D%8810.54.05.png" height="386" width="640" /></a></div>
<br />
<br />
我是一位Android開發者,獨立開發者,<br />
從UI設計到程式開發一手包辦,<br />
很多會寫程式的人,程式的部份可以自己搞定,<br />
但多數人會卡在『糟糕;我沒有美術的天份』這裡,<br />
認為自己弄不出夠水準的介面設計。<br />
<br />
於是會將程式介面外包給設計師來做,<br />
本來術業有專攻,那也沒什麼不好。<br />
問題是,有些介面設計師手拿iPhone, iPad,<br />
連Android手機都沒用過,<br />
你怎麼能期待他比你更知道Android的介面應該是什麼樣子呢?<br />
<br />
<a name='more'></a><br />
<br />
我認為介面設計不會只是『美術的天份』這件事而已,<br />
也包含對於系統的熟悉和元件配置,而導致的使用者操作習慣上等。<br />
<br />
同樣的,因為我對ios的介面使用和操作習慣並沒有很深入的了解,<br />
如果有人請我幫忙去設計ios上的app介面,<br />
我一樣會感覺到非常無所適從。<br />
因為我並不知道ios上的給開發者的原生元件是什麼樣子,<br />
我所設計的元件,開發者需要多少時間精力去修改,<br />
並且不知道這樣的設計是否有符合ios使用者的習慣。<br />
<br />
所以身為Android開發者,您有沒有想過Android style應該是什麼樣子,<br />
反而言之,如果你知道Android style 該是什麼樣子,<br />
那你是否就有能力自己寫出符合Android使用習慣,夠水準的UI!<br />
<br />
Google 在Android3.0 時推出了Holo風格的預設主題,<br />
在Android4.0時開始強制要求手機製造商必須把Holo風格留在裝置上,<br />
並且不能更改Holo風格中的樣式。<br />
<br />
在這之前,手機廠會根據自己的需求或各廠牌設計師的審美觀,<br />
把Android的預設改成自己需要的樣式,<br />
如此一來,開發者寫好的App放到各個廠牌的手機時,<br />
全都長得不一樣,開發者沒辦法全權控制自己App的樣式。<br />
除非開發者非常有耐心的在每一個元件都仔細設定字型,大小,顏色等各個項目。<br />
<br />
有了Holo theme之後開發者在建立UI時,<br />
能夠更得心應手,不需要擔心在不同品牌的手機,<br />
會看到不同的結果了。<br />
<br />
以前在寫Windows桌面程式的時候,如果你總是只使用預設的風格,<br />
那你寫出來的介面就會等於醜到暴,或是等於看起來很普通。<br />
但這樣的情況正在改觀,使用者開始要求開發者要以Holo style來寫App,<br />
許多Android app 也開始在介紹的地方,<br />
強調是使用Holo style來設計,<br />
因為Holo style才是符合使用者心目中Android app該有的樣子。<br />
<br />
Google 所提供的預設Holo theme有三種,<br />
Holo Light, Holo Dark 和 Holo Light with dark action bars<br />
除了這三種還可以利用<a href="http://android-holo-colors.com/" target="_blank">Android Assets Studio</a>工具<br />
來客製出您所需要的Holo Theme Color<br />
<br />
因上述提的,Holo theme只支援到Android3.0以後的裝置,<br />
如果需要在3.0之前使用Holo 風格的元件,<br />
可以在專案中使用開放原始碼專案 <a href="https://github.com/Prototik/HoloEverywhere" target="_blank">HoloEverywhere</a>,<br />
<br />
通常只要在App中使用Holo theme並善用Roboto(我喜歡叫他蘿蔔頭字型)字型,<br />
就能設計出不錯的介面。設定Roboto字型的方式如下:<br />
在layout xml中做如下設定<br />
<pre class="default prettyprint prettyprinted" style="background-color: #eeeeee; border: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; font-size: 14px; line-height: 17.804800033569336px; margin-bottom: 10px; max-height: 600px; overflow: auto; padding: 5px; vertical-align: baseline; width: auto; word-wrap: normal;"><code style="border: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; margin: 0px; padding: 0px; vertical-align: baseline; white-space: inherit;"><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">android</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">:</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">fontFamily</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="str" style="background-color: transparent; border: 0px; color: maroon; margin: 0px; padding: 0px; vertical-align: baseline;">"sans-serif"</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"> </span><span class="com" style="background-color: transparent; border: 0px; color: grey; margin: 0px; padding: 0px; vertical-align: baseline;">// roboto regular </span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">
android</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">:</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">fontFamily</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="str" style="background-color: transparent; border: 0px; color: maroon; margin: 0px; padding: 0px; vertical-align: baseline;">"sans-serif-light"</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"> </span><span class="com" style="background-color: transparent; border: 0px; color: grey; margin: 0px; padding: 0px; vertical-align: baseline;">// roboto light </span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">
android</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">:</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">fontFamily</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="str" style="background-color: transparent; border: 0px; color: maroon; margin: 0px; padding: 0px; vertical-align: baseline;">"sans-serif-condensed"</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"> </span><span class="com" style="background-color: transparent; border: 0px; color: grey; margin: 0px; padding: 0px; vertical-align: baseline;">// roboto condensed </span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">
android</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">:</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">fontFamily</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="str" style="background-color: transparent; border: 0px; color: maroon; margin: 0px; padding: 0px; vertical-align: baseline;">"sans-serif-thin"</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"> </span><span class="com" style="background-color: transparent; border: 0px; color: grey; margin: 0px; padding: 0px; vertical-align: baseline;">// roboto thin (android 4.2) </span></code></pre>
想要小試試身手嗎?如果你手邊沒有合適的專案,<br />
試試看這個開放原始碼的練習,<br />
你會對做出有水準的UI更具有信心<br />
<br />
<br />
<h3>
Making apps beautiful</h3>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/pPyR0nYUXqc?feature=player_embedded' frameborder='0'></iframe></div>
<br />
<br />
<div class="p1">
<span class="s1">YouTube : <a href="https://www.youtube.com/watch?v=8dzMHKDkV6U"><span class="s2">https://www.youtube.com/watch?v=pPyR0nYUXqc</span></a></span></div>
<br />
<div class="p2">
<span class="s3">GitHub : <a href="https://github.com/ankurkotwal/making-apps-beautiful"><span class="s4">https://github.com/ankurkotwal/making-apps-beautiful</span></a></span></div>
<br />
<br />
<a href="http://asnippets.blogspot.tw/p/cowallet-change-log.html" target="_blank">CoWallet</a>是一個以Holo theme主題製作的App,<br />
適合團體/家庭共同記帳管理使用,<br />
找個知心好友或家人一起陪你記帳會更有動力哦!<br />
<br />Anonymoushttp://www.blogger.com/profile/10433873918988135141noreply@blogger.com0tag:blogger.com,1999:blog-9873545.post-81348543214584560342014-02-20T08:37:00.003+08:002014-02-20T09:33:27.364+08:00Hangout 造成發送與接收SMS問題<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-0_grncEDtdE7OBMiC2cYN3tQfGtG6Y9DQmyMN63vwzaUdsHcs0yQJjtr-KsWIC1Ad_SJEDxMK86DDTjcaIJmn0Y0YV4VvydmxA_4F2IZLwni32EJLxv1cpw5ZmQHuZ119AUC/s1600/android-kitkat1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-0_grncEDtdE7OBMiC2cYN3tQfGtG6Y9DQmyMN63vwzaUdsHcs0yQJjtr-KsWIC1Ad_SJEDxMK86DDTjcaIJmn0Y0YV4VvydmxA_4F2IZLwni32EJLxv1cpw5ZmQHuZ119AUC/s1600/android-kitkat1.jpg" height="250" width="400" /></a></div>
<br />
Google 在Android 4.4改以Hangout來取代原本預設的簡訊App,因此在App如果有寫到傳送或接收SMS功能時,在Kitkat上或是有安裝Hangout的舊版本(Android 4.3及以下)手機上,可能會運作不正常。<br />
<br />
在接收SMS時,因為Hangout有可能由使用者在Google Play下載,裝在舊版的手機上,為了避免有兩個預設的SMS App在收到SMS時都提供通知,因此若有安裝Hangout,Hangout似乎會攔住"android.provider.Telephony.SMS_RECEIVED"這個broadcast event,來避免舊的簡訊App也產生notification,因此如果您的App有聆聽此event來獲得收到的簡訊時,在安裝Hangout之後會發現收不到"android.provider.Telephony.SMS_RECEIVED"。<span style="color: red;">此時解決方法是在Broadcast Receiver上加上priority,並將priority設為大於3</span>,如此一來便能解決收不到"android.provider.Telephony.SMS_RECEIVED"的問題。請參考<a href="http://stackoverflow.com/questions/20021492/enabling-sms-support-in-hangouts-2-0-breaks-the-broadcastreceiver-of-sms-receive" target="_blank">此討論</a><br />
<br />
<pre class="default prettyprint prettyprinted" style="background-color: #eeeeee; border: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; font-size: 14px; line-height: 17.804800033569336px; margin-bottom: 10px; max-height: 600px; overflow: auto; padding: 5px; vertical-align: baseline; width: auto; word-wrap: normal;"><code style="border: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="tag" style="background-color: transparent; border: 0px; color: maroon; margin: 0px; padding: 0px; vertical-align: baseline;"><receiver</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"> </span><span class="atn" style="background-color: transparent; border: 0px; color: red; margin: 0px; padding: 0px; vertical-align: baseline;">android:name</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="atv" style="background-color: transparent; border: 0px; color: blue; margin: 0px; padding: 0px; vertical-align: baseline;">"com.google.android.apps.babel.sms.AbortSmsReceiver"</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"> </span><span class="atn" style="background-color: transparent; border: 0px; color: red; margin: 0px; padding: 0px; vertical-align: baseline;">android:permission</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="atv" style="background-color: transparent; border: 0px; color: blue; margin: 0px; padding: 0px; vertical-align: baseline;">"android.permission.BROADCAST_SMS"</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"> </span><span class="atn" style="background-color: transparent; border: 0px; color: red; margin: 0px; padding: 0px; vertical-align: baseline;">android:enabled</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="atv" style="background-color: transparent; border: 0px; color: blue; margin: 0px; padding: 0px; vertical-align: baseline;">"false"</span><span class="tag" style="background-color: transparent; border: 0px; color: maroon; margin: 0px; padding: 0px; vertical-align: baseline;">></span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">
</span><span class="tag" style="background-color: transparent; border: 0px; color: maroon; margin: 0px; padding: 0px; vertical-align: baseline;"><intent-filter</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"> </span><span class="atn" style="background-color: transparent; border: 0px; color: red; margin: 0px; padding: 0px; vertical-align: baseline;">android:priority</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="atv" style="background-color: transparent; border: 0px; color: blue; margin: 0px; padding: 0px; vertical-align: baseline;">"3"</span><span class="tag" style="background-color: transparent; border: 0px; color: maroon; margin: 0px; padding: 0px; vertical-align: baseline;">></span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">
</span><span class="tag" style="background-color: transparent; border: 0px; color: maroon; margin: 0px; padding: 0px; vertical-align: baseline;"><action</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"> </span><span class="atn" style="background-color: transparent; border: 0px; color: red; margin: 0px; padding: 0px; vertical-align: baseline;">android:name</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="atv" style="background-color: transparent; border: 0px; color: blue; margin: 0px; padding: 0px; vertical-align: baseline;">"android.provider.Telephony.SMS_RECEIVED"</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"> </span><span class="tag" style="background-color: transparent; border: 0px; color: maroon; margin: 0px; padding: 0px; vertical-align: baseline;">/></span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">
</span><span class="tag" style="background-color: transparent; border: 0px; color: maroon; margin: 0px; padding: 0px; vertical-align: baseline;"></intent-filter></span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">
</span><span class="tag" style="background-color: transparent; border: 0px; color: maroon; margin: 0px; padding: 0px; vertical-align: baseline;"></receiver></span></code></pre>
在傳送SMS時在Kitkat上Google 已經把簡訊App拿掉,因此已以往Intent的方式來發送SMS可能會遇到找不到預設App的問題,解決方式如下:請參考此<a href="http://stackoverflow.com/questions/20079047/android-kitkat-4-4-hangouts-cannot-handle-sending-sms-intent" target="_blank">討論</a><br />
<br />
<pre class="default prettyprint prettyprinted" style="background-color: #eeeeee; border: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; font-size: 14px; line-height: 17.804800033569336px; margin-bottom: 10px; max-height: 600px; overflow: auto; padding: 5px; vertical-align: baseline; width: auto; word-wrap: normal;"><code style="border: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="kwd" style="background-color: transparent; border: 0px; color: darkblue; margin: 0px; padding: 0px; vertical-align: baseline;">if</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"> </span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="typ" style="background-color: transparent; border: 0px; color: #2b91af; margin: 0px; padding: 0px; vertical-align: baseline;">Build</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">VERSION</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">SDK_INT </span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">>=</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"> </span><span class="typ" style="background-color: transparent; border: 0px; color: #2b91af; margin: 0px; padding: 0px; vertical-align: baseline;">Build</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">VERSION_CODES</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">KITKAT</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"> </span><span class="com" style="background-color: transparent; border: 0px; color: grey; margin: 0px; padding: 0px; vertical-align: baseline;">//At least KitKat</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">
</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">{</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">
</span><span class="typ" style="background-color: transparent; border: 0px; color: #2b91af; margin: 0px; padding: 0px; vertical-align: baseline;">String</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"> defaultSmsPackageName </span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"> </span><span class="typ" style="background-color: transparent; border: 0px; color: #2b91af; margin: 0px; padding: 0px; vertical-align: baseline;">Telephony</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="typ" style="background-color: transparent; border: 0px; color: #2b91af; margin: 0px; padding: 0px; vertical-align: baseline;">Sms</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">getDefaultSmsPackage</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">activity</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">);</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"> </span><span class="com" style="background-color: transparent; border: 0px; color: grey; margin: 0px; padding: 0px; vertical-align: baseline;">//Need to change the build to API 19</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">
</span><span class="typ" style="background-color: transparent; border: 0px; color: #2b91af; margin: 0px; padding: 0px; vertical-align: baseline;">Intent</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"> sendIntent </span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"> </span><span class="kwd" style="background-color: transparent; border: 0px; color: darkblue; margin: 0px; padding: 0px; vertical-align: baseline;">new</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"> </span><span class="typ" style="background-color: transparent; border: 0px; color: #2b91af; margin: 0px; padding: 0px; vertical-align: baseline;">Intent</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="typ" style="background-color: transparent; border: 0px; color: #2b91af; margin: 0px; padding: 0px; vertical-align: baseline;">Intent</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">ACTION_SEND</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">);</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">
sendIntent</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">setType</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="str" style="background-color: transparent; border: 0px; color: maroon; margin: 0px; padding: 0px; vertical-align: baseline;">"text/plain"</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">);</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">
sendIntent</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">putExtra</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="typ" style="background-color: transparent; border: 0px; color: #2b91af; margin: 0px; padding: 0px; vertical-align: baseline;">Intent</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">EXTRA_TEXT</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">,</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"> smsText</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">);</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">
</span><span class="kwd" style="background-color: transparent; border: 0px; color: darkblue; margin: 0px; padding: 0px; vertical-align: baseline;">if</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"> </span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">defaultSmsPackageName </span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">!=</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"> </span><span class="kwd" style="background-color: transparent; border: 0px; color: darkblue; margin: 0px; padding: 0px; vertical-align: baseline;">null</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">)</span><span class="com" style="background-color: transparent; border: 0px; color: grey; margin: 0px; padding: 0px; vertical-align: baseline;">//Can be null in case that there is no default, then the user would be able to choose any app that support this intent.</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">
</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">{</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">
sendIntent</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">setPackage</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">defaultSmsPackageName</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">);</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">
</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">}</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">
activity</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">startActivity</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">sendIntent</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">);</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">
</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">}</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">
</span><span class="kwd" style="background-color: transparent; border: 0px; color: darkblue; margin: 0px; padding: 0px; vertical-align: baseline;">else</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"> </span><span class="com" style="background-color: transparent; border: 0px; color: grey; margin: 0px; padding: 0px; vertical-align: baseline;">//For early versions, do what worked for you before.</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">
</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">{</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">
</span><span class="typ" style="background-color: transparent; border: 0px; color: #2b91af; margin: 0px; padding: 0px; vertical-align: baseline;">Intent</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"> sendIntent </span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"> </span><span class="kwd" style="background-color: transparent; border: 0px; color: darkblue; margin: 0px; padding: 0px; vertical-align: baseline;">new</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"> </span><span class="typ" style="background-color: transparent; border: 0px; color: #2b91af; margin: 0px; padding: 0px; vertical-align: baseline;">Intent</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="typ" style="background-color: transparent; border: 0px; color: #2b91af; margin: 0px; padding: 0px; vertical-align: baseline;">Intent</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">ACTION_VIEW</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">);</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">
sendIntent</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">setData</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="typ" style="background-color: transparent; border: 0px; color: #2b91af; margin: 0px; padding: 0px; vertical-align: baseline;">Uri</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">parse</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="str" style="background-color: transparent; border: 0px; color: maroon; margin: 0px; padding: 0px; vertical-align: baseline;">"sms:"</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">));</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">
sendIntent</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">putExtra</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="str" style="background-color: transparent; border: 0px; color: maroon; margin: 0px; padding: 0px; vertical-align: baseline;">"sms_body"</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">,</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"> smsText</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">);</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">
activity</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">startActivity</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">(</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">sendIntent</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">);</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">
</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">}</span></code></pre>
<br />Anonymoushttp://www.blogger.com/profile/10433873918988135141noreply@blogger.com0tag:blogger.com,1999:blog-9873545.post-82851144834006832592013-10-15T23:11:00.001+08:002013-11-05T17:06:41.180+08:00Code Lab - Communication among Android devices : A chat room<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhY6ijoK59woRjtBne47rB77SyC_d6esqnhnHE4GHRFpUJSx2FgDbBdNGUWqAcsgOrFB9O_I8_GALfGWuvouGsQAeqPEJoE8PDcWtF4RDeZBxckc9u9qP50DyzlsXZNTIwkfb-x/s1600/%25E8%259E%25A2%25E5%25B9%2595%25E5%25BF%25AB%25E7%2585%25A7+2013-10-15+%25E4%25B8%258B%25E5%258D%25883.38.06.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhY6ijoK59woRjtBne47rB77SyC_d6esqnhnHE4GHRFpUJSx2FgDbBdNGUWqAcsgOrFB9O_I8_GALfGWuvouGsQAeqPEJoE8PDcWtF4RDeZBxckc9u9qP50DyzlsXZNTIwkfb-x/s400/%25E8%259E%25A2%25E5%25B9%2595%25E5%25BF%25AB%25E7%2585%25A7+2013-10-15+%25E4%25B8%258B%25E5%258D%25883.38.06.png" width="400" /></a></div>
<br />
此Android程式練習是為成大資工系-電腦通訊網路課程 所設計的一個Code Lab,目的在介紹Android之間的裝置通訊,以及在Android上面如何實作一個聊天室應用,其中包含在Server端的HttpServerlet以及GCM Api的使用。<br />
此App運用可以上安裝此App的所有使用者彼此間進行聊天。<br />
課程時間:3小時<br />
<br />
投影片<a href="https://drive.google.com/file/d/0B_nPmd5lFvJ9RDdpSG5RREFXQnM/edit?usp=sharing" target="_blank">下載</a><br />
<br />
<a name='more'></a><br />
<br />
<h3>
<span style="color: orange;">Check Point 0 : Android 環境設定</span></h3>
安裝設定Android開發環境,以繼續接下來的練習<br />
<h4>
Step 1 : 下載並安裝Android ADT Bundle</h4>
<br />
<ul>
<li><h3 style="background-color: white; color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; margin: 0px; position: relative;">
<li><span style="font-weight: normal; line-height: 1.4;">下載URL: </span><a href="http://developer.android.com/sdk/index.html" style="color: #888888; line-height: 1.4; text-decoration: none;">http://developer.android.com/sdk/index.html</a></li>
<li><span style="font-weight: normal; line-height: 1.4;">開啟SDK Manager 並勾選Android4.3(API18)底下的SDK Platform 和Google API</span></li>
<li><span style="font-weight: normal; line-height: 1.4;">按下Install package</span></li>
<li><span style="font-weight: normal; line-height: 1.4;">點選Accept license > Install</span></li>
<div>
<span style="font-weight: normal;">註:若無法開啟Eclipse,須先安裝JDK (</span><a href="http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html" style="color: #888888; text-decoration: none;">http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html</a>)</div>
</h3>
</li>
</ul>
<br />
<h4>
Step 2 : 下載ChatRoom Project ,並進行解壓縮</h4>
<br />
<ul style="background-color: white; color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 13px; line-height: 18px; margin: 0.5em 0px; padding: 0px 2.5em;">
<li style="margin: 0px 0px 0.25em; padding: 0px;">URL: <a href="https://drive.google.com/file/d/0B_nPmd5lFvJ9OHJucEphZWNiX1E/edit?usp=sharing" target="_blank">下載</a></li>
</ul>
<ul style="background-color: white; color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 13px; line-height: 18px; margin: 0.5em 0px; padding: 0px 2.5em;">
<li style="margin: 0px 0px 0.25em; padding: 0px;">Do not publish this code to Google Play !!</li>
</ul>
<br />
<h4>
Step 3 : 在新的Workspace 中,匯入<span style="font-size: 13px;">ChatRoom</span><span style="font-size: 13px;"> Project</span></h4>
<ul style="background-color: white; color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 13px; line-height: 18px; margin: 0.5em 0px; padding: 0px 2.5em;">
<li style="margin: 0px 0px 0.25em; padding: 0px;">File> Import > General> Existing Project into Workspace</li>
<li style="margin: 0px 0px 0.25em; padding: 0px;">選擇Project路徑</li>
<li style="margin: 0px 0px 0.25em; padding: 0px;">按下Select All 按鈕</li>
<li style="margin: 0px 0px 0.25em; padding: 0px;">勾選 Copy project into workspace</li>
</ul>
<div>
<span style="color: #666666; font-family: Trebuchet MS, Trebuchet, Verdana, sans-serif; font-size: x-small;"><span style="line-height: 18px;">若匯入後有錯,請檢查Project name右鍵 > Properties > Google > AppEngine > AppEngine SDK路徑是否正確</span></span></div>
<h4>
<span style="font-weight: normal;">Step 4 : 設定Project Build Target為Android 4.3</span></h4>
<br />
<ul style="line-height: 1.4; margin: 0.5em 0px; padding: 0px 2.5em;">
<li style="margin: 0px 0px 0.25em; padding: 0px;">Project上按右鍵 > Properties > Android > Project Build Target > Google APIs Level 18</li>
</ul>
<br />
<br />
<h4>
<span style="font-weight: normal;">Step 5 : 註冊下載Genymotion Android 模擬器 / 或使用Android 手機</span></h4>
<ul style="background-color: white; color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 13px; line-height: 18px; margin: 0.5em 0px; padding: 0px 2.5em;">
<li style="margin: 0px 0px 0.25em; padding: 0px;"><a href="https://cloud.genymotion.com/" style="color: #888888; text-decoration: none;">https://cloud.genymotion.com</a></li>
<li style="margin: 0px 0px 0.25em; padding: 0px;">完成註冊後依平台下載Genymotion </li>
<li style="margin: 0px 0px 0.25em; padding: 0px;">下載Vertual box <a href="https://www.virtualbox.org/wiki/Downloads" style="color: #888888; text-decoration: none;">https://www.virtualbox.org/wiki/Downloads</a></li>
<li style="margin: 0px 0px 0.25em; padding: 0px;">下載Eclipse Plugin : ADT > Help > Install new software 加入url:http://plugins.genymotion.com/eclipse</li>
</ul>
<h4>
<span style="font-weight: normal;">Step 6 :執行Genymotion並建立一個Galaxy Nexus with Google App API17</span></h4>
<h4>
Step 7 :嘗試在模擬器上執行專案</h4>
*中文字如果出現亂碼請將編碼改為UTF-8 (File > Properties > Resource > Text file encoding)<br />
<br />
<div style="background-color: white; color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 13px; font-weight: normal; line-height: 18px;">
*如果有任何錯誤,請坐下列檢查</div>
<br />
<ul style="background-color: white; color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 13px; font-weight: normal; line-height: 1.4; margin: 0.5em 0px; padding: 0px 2.5em;">
<li style="margin: 0px 0px 0.25em; padding: 0px;">ADT > Project > clean > clean all</li>
<li style="margin: 0px 0px 0.25em; padding: 0px;">Project右鍵 > property > Android > 檢查Build Target 及 Library</li>
</ul>
<hr />
<br />
<h3>
<span style="color: orange;">Check Point 1 : 下載App Engine SDK</span></h3>
<div style="background-color: white;">
<h4>
<b style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 13px;">Step 1 : 安裝Eclipse 外掛</b></h4>
</div>
<div style="background-color: white;">
<ul>
<li><span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 13px;">ADT > Help > install new software > 輸入 </span><span style="font-family: Trebuchet MS, Trebuchet, Verdana, sans-serif;"><span style="font-size: 12.800000190734863px;">http://dl.google.com/eclipse/plugin/4.2</span></span></li>
<li><span style="font-family: Trebuchet MS, Trebuchet, Verdana, sans-serif;"><span style="font-size: 12.800000190734863px;">勾選(1)Google App Engine Tools for Android、(2) SDKs / Google App Engine Java SDK 及(3)SDKs / Google Web Toolkit > 按下Next開始安裝 (4) Google plugin for Eclipse</span></span></li>
<li><span style="font-family: Trebuchet MS, Trebuchet, Verdana, sans-serif; font-size: x-small;"><a href="https://developers.google.com/appengine/downloads?hl=zh-TW&csw=1">https://developers.google.com/appengine/downloads?hl=zh-TW&csw=1</a></span></li>
<li>在GAE-ChetRoom按右鍵 > Properties > Google > App Engine > Use App Engine</li>
</ul>
<div>
註: app engine sdk 1.8.6 需要以JDK 7 來編譯,JDK 6會有錯</div>
</div>
<div style="background-color: white;">
<h4>
Step 2: 建立Web Application專案</h4>
</div>
<div style="background-color: white;">
<ul>
<li>File > new > Web application project > 只勾選Use Google App Engine</li>
<li>Project Name 設為TEST</li>
<li>Package 設為com.xxx.gae.test</li>
<li>執行新建立的專案,並在瀏覽器開啟http://localhost:8888/,看是否正常顯示</li>
<li>觀察此專案內容結構</li>
</ul>
<h3>
<span style="color: orange;">Check Point 2 : 在Google Api Console 開啟GCM服務</span></h3>
<div>
Step 1 : 連到Google API Console 並建立一Project</div>
<div>
<ul>
<li><a href="https://code.google.com/apis/console/">https://code.google.com/apis/console/</a></li>
<li>Create Project</li>
<li style="margin: 0px 0px 0.25em; padding: 0px;">Services > <span style="color: red;">Google Cloud Messaging for Android</span> > On</li>
<li style="margin: 0px 0px 0.25em; padding: 0px;">記錄下你的project number,這個數字就是你的GCM_SENDER_ID</li>
</ul>
</div>
<div>
Step 2 : 取得API Key</div>
<div>
<ul>
<li style="margin: 0px 0px 0.25em; padding: 0px;">API Access > <span style="color: red;">Create Server Key</span> </li>
<li style="margin: 0px 0px 0.25em; padding: 0px;">填入whitelist ip, 此處保持空白就好</li>
<li style="margin: 0px 0px 0.25em; padding: 0px;">按下Create</li>
<li style="margin: 0px 0px 0.25em; padding: 0px;">將API_KEY記錄下來,之後會用到</li>
</ul>
</div>
</div>
<hr />
<h3>
<span style="color: orange;">Check Point 3 : 在Server上建立App Engine Project,並上傳專案</span></h3>
<div style="background-color: white;">
<h4>
Step 1 : Create GAE project</h4>
</div>
<ul>
<li>https://appengine.google.com/ > create project </li>
<li>輸入一個<span style="font-family: Arial, sans-serif; font-size: 12.800000190734863px; font-weight: bold;">Application Identifier</span>,此名稱必須沒有被用過。http://[applicaton identifier].appspot.com 為你所申請的server domain name</li>
</ul>
<div>
<h4>
Step 2 : 將Web Application上傳</h4>
</div>
<div style="background-color: white;">
<ul>
<li>GAE_ChatRoom project > 右鍵 > Properties > Google > App Engine > Application Id 填入Step 1 所設定的Application Identifier</li>
<li>GAE_ChatRoom project > 右鍵 > Google > Deploy to App Engine</li>
</ul>
<div>
<h4>
Step 3 : 測試</h4>
</div>
<ul>
<li>嘗試 http://[applicaton identifier].appspot.com </li>
</ul>
</div>
<hr />
<h3>
<span style="color: orange;">Check Point 4 : 建立GcmRegister.java HttpServlet處理註冊</span></h3>
<div style="background-color: white;">
<h4>
Step 1 : 建立GcmRegister來定義DataStore欄位</h4>
</div>
<ul style="background-color: white;">
<li>建立GcmRegister其中包含regid的String欄位</li>
</ul>
<div>
<h4>
<div style="background-color: white; font-weight: normal;">
GcmRegister.java</div>
<div style="font-weight: normal;">
<pre><table border="1" ddd="" style="background-color: white; color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 13px; line-height: 18px;"><tbody>
<tr><td><blockquote class="tr_bq">
<pre style="color: #333333; line-height: 16px;"><pre><span style="color: #0000aa;">package</span> com.<span style="color: dodgerblue;">whilerain</span>.<span style="color: dodgerblue;">gae</span>.<span style="color: dodgerblue;">chatroom</span>.<span style="color: dodgerblue;">db</span>;
<span style="color: #0000aa;">import</span> <span style="color: #00aaaa; text-decoration: underline;">javax.jdo.annotations.PersistenceCapable</span>;
<span style="color: #0000aa;">import</span> <span style="color: #00aaaa; text-decoration: underline;">javax.jdo.annotations.Persistent</span>;
<span style="color: #0000aa;">import</span> <span style="color: #00aaaa; text-decoration: underline;">javax.jdo.annotations.PrimaryKey</span>;
<span style="color: #888888;">@PersistenceCapable</span>
<span style="color: #0000aa;">public</span> <span style="color: #0000aa;">class</span> <span style="color: #00aa00; text-decoration: underline;">GcmRegister</span> {
<span style="color: #888888;">@PrimaryKey</span>
<span style="color: #0000aa;">private</span> String regid;
<span style="color: #0000aa;">public</span> <span style="color: #00aa00;">GcmRegister</span>(String id){
regid = id;
}
<span style="color: #0000aa;">public</span> String <span style="color: #00aa00;">getRegid</span>() {
<span style="color: #0000aa;">return</span> regid;
}
<span style="color: #0000aa;">public</span> <span style="color: #00aaaa;">void</span> <span style="color: #00aa00;">setRegid</span>(String regid) {
<span style="color: #0000aa;">this</span>.<span style="color: dodgerblue;">regid</span> = regid;
}
}</pre>
<div>
</div>
</pre>
</blockquote>
</td></tr>
</tbody></table>
</pre>
</div>
</h4>
<h4>
<span style="font-family: inherit;">Step 2 : 在GAE_ChatRoom當中建立PMF類別來處理DataStore的存取作業。</span></h4>
<h4>
<ul>
<li>建立PMF.java</li>
</ul>
</h4>
</div>
<h3>
<pre>PMF.java</pre>
<pre><pre style="background-color: white; font-size: medium; font-weight: normal;"><table border="1" ddd="" style="color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 13px; line-height: 18px;"><tbody>
<tr><td><blockquote class="tr_bq">
<pre style="color: #333333; line-height: 16px;"><pre><span style="color: #0000aa;">package</span> com.<span style="color: dodgerblue;">whilerain</span>.<span style="color: dodgerblue;">gae</span>.<span style="color: dodgerblue;">chatroom</span>.<span style="color: dodgerblue;">db</span>;
<span style="color: #0000aa;">import</span> <span style="color: #00aaaa; text-decoration: underline;">javax.jdo.JDOHelper</span>;
<span style="color: #0000aa;">import</span> <span style="color: #00aaaa; text-decoration: underline;">javax.jdo.PersistenceManagerFactory</span>;
<span style="color: #0000aa;">public</span> <span style="color: #0000aa;">final</span> <span style="color: #0000aa;">class</span> <span style="color: #00aa00; text-decoration: underline;">PMF</span> {
<span style="color: #0000aa;">private</span> <span style="color: #0000aa;">static</span> <span style="color: #0000aa;">final</span> PersistenceManagerFactory pmfInstance = JDOHelper.<span style="color: dodgerblue;">getPersistenceManagerFactory</span>(<span style="color: #aa5500;">"transactions-optional"</span>);
<span style="color: #0000aa;">public</span> <span style="color: #0000aa;">static</span> PersistenceManagerFactory <span style="color: #00aa00;">get</span>() {
<span style="color: #0000aa;">return</span> pmfInstance;
}
}</pre>
</pre>
</blockquote>
</td></tr>
</tbody></table>
</pre>
</pre>
</h3>
<h3>
<pre style="font-weight: normal;"><pre style="background-color: white;"></pre>
</pre>
</h3>
<h4>
<span style="font-family: inherit;">Step 3 : 在DoGcmRegister.java當中,儲存所上傳的registration_id</span></h4>
<h4>
<pre style="background-color: white; font-weight: normal;"><span style="white-space: normal;">DoGcmRegister.java</span>
<div>
<pre><table border="1" ddd="" style="color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 13px; line-height: 18px;"><tbody>
<tr><td><blockquote class="tr_bq">
<pre style="color: #333333; line-height: 16px;"><pre><span style="color: #888888;">@Override</span>
<span style="color: #0000aa;">protected</span> <span style="color: #00aaaa;">void</span> <span style="color: #00aa00;">doPost</span>(HttpServletRequest req, HttpServletResponse resp)
<span style="color: #0000aa;">throws</span> ServletException, IOException {
String jsonState = URLDecoder.<span style="color: dodgerblue;">decode</span>(req.<span style="color: dodgerblue;">getParameter</span>(<span style="color: #aa5500;">"statement"</span>));
PersistenceManager pm=PMF.<span style="color: dodgerblue;">get</span>().<span style="color: dodgerblue;">getPersistenceManager</span>();
JSONObject jsonResp = <span style="color: #0000aa;">new</span> JSONObject();
<span style="color: #0000aa;">try</span> {
JSONObject jsonObject = <span style="color: #0000aa;">new</span> JSONObject(jsonState);
String regid = jsonObject.<span style="color: dodgerblue;">getString</span>(<span style="color: #aa5500;">"regid"</span>);
GcmRegister reg = <span style="color: #0000aa;">new</span> GcmRegister(regid);
pm.<span style="color: dodgerblue;">makePersistent</span>(reg);
jsonResp.<span style="color: dodgerblue;">put</span>(<span style="color: #aa5500;">"result"</span>, <span style="color: #aa5500;">"ok"</span>);
resp.<span style="color: dodgerblue;">setContentType</span>(<span style="color: #aa5500;">"text/json"</span>);
resp.<span style="color: dodgerblue;">setCharacterEncoding</span>(<span style="color: #aa5500;">"UTF-8"</span>);
resp.<span style="color: dodgerblue;">getWriter</span>().<span style="color: dodgerblue;">println</span>(jsonResp.<span style="color: dodgerblue;">toString</span>());
} <span style="color: #0000aa;">catch</span> (Exception e) {
resp.<span style="color: dodgerblue;">setContentType</span>(<span style="color: #aa5500;">"text/plain"</span>);
resp.<span style="color: dodgerblue;">getWriter</span>().<span style="color: dodgerblue;">println</span>(e.<span style="color: dodgerblue;">getMessage</span>());
e.<span style="color: dodgerblue;">printStackTrace</span>();
}<span style="color: #0000aa;">finally</span>{
pm.<span style="color: dodgerblue;">close</span>();
}
}</pre>
</pre>
</blockquote>
</td></tr>
</tbody></table>
</pre>
</div>
</pre>
</h4>
<h4>
<span style="background-color: white;">Step 4 : 宣告Servlet路徑</span></h4>
<h4>
<ul>
<li><span style="background-color: white;">在war/WEB-INF/web.xml加入servlet路徑宣告,在<web-app>標籤之間加入</span></li>
</ul>
</h4>
<h4>
<pre style="font-weight: normal;"><div style="background-color: white;">
<table border="1" ddd="" style="color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 13px; line-height: 18px;"><tbody>
<tr><td><blockquote class="tr_bq">
<pre style="color: #333333; line-height: 16px;"><pre><span style="color: dodgerblue;"><servlet></span>
<span style="color: dodgerblue;"><servlet-name></span>GCMREG<span style="color: dodgerblue;"></servlet-name></span>
<span style="color: dodgerblue;"><servlet-class></span>com.whilerain.gae.chatroom.DoGcmRegister<span style="color: dodgerblue;"></servlet-class></span>
<span style="color: dodgerblue;"></servlet></span>
<span style="color: dodgerblue;"><servlet-mapping></span>
<span style="color: dodgerblue;"><servlet-name></span>GCMREG<span style="color: dodgerblue;"></servlet-name></span>
<span style="color: dodgerblue;"><url-pattern></span>/gcmreg<span style="color: dodgerblue;"></url-pattern></span>
<span style="color: dodgerblue;"></servlet-mapping></span></pre>
</pre>
</blockquote>
</td></tr>
</tbody></table>
</div>
</pre>
</h4>
<h4>
<b style="background-color: white;">step 5 : 上傳目前版本,並測試之</b></h4>
<h4>
<div>
<pre style="font-weight: normal;"></pre>
</div>
</h4>
<h4>
<ul>
<li><b style="background-color: white;">使用<a href="http://www.google.com/intl/zh-TW/chrome/">Chrome</a>應用程式</b><a href="https://chrome.google.com/webstore/detail/advanced-rest-client/hgmloofddffdnphfgcellkdfbfbjeloo">Advanced REST client</a></li>
<li>輸入如下測試之</li>
</ul>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFtTrKsZ9tWk7kQN9HkiXBE-wDYkgD6ZQoerCVWBwnYjOm-DtfwkupQIesJo6PuhVQfRfzI0zVHxmDOjoum42ciWe1l8NI0Rq3ohIsrWmci0nDwUiiFMOFzwDxCpFBKtHpH_7h/s1600/%25E8%259E%25A2%25E5%25B9%2595%25E5%25BF%25AB%25E7%2585%25A7+2013-10-15+%25E4%25B8%258B%25E5%258D%25884.20.55.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="210" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFtTrKsZ9tWk7kQN9HkiXBE-wDYkgD6ZQoerCVWBwnYjOm-DtfwkupQIesJo6PuhVQfRfzI0zVHxmDOjoum42ciWe1l8NI0Rq3ohIsrWmci0nDwUiiFMOFzwDxCpFBKtHpH_7h/s400/%25E8%259E%25A2%25E5%25B9%2595%25E5%25BF%25AB%25E7%2585%25A7+2013-10-15+%25E4%25B8%258B%25E5%258D%25884.20.55.png" width="400" /></a></div>
<br />
</h4>
<hr />
<h3>
<span style="color: orange;">Check Point 5 : 建立SendMessage.java HttpServlet處理訊息的推送</span></h3>
Step 1 : 在SendMessage.java實作doPost()來處理取得Http Post參數<br />
<pre><table border="1" ddd="" style="color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 13px; line-height: 18px;"><tbody>
<tr><td><blockquote class="tr_bq">
<pre style="color: #333333; line-height: 16px;"><pre><span style="color: #888888;">@Override</span>
<span style="color: #0000aa;">protected</span> <span style="color: #00aaaa;">void</span> <span style="color: #00aa00;">doPost</span>(HttpServletRequest req, HttpServletResponse resp) <span style="color: #0000aa;">throws</span> ServletException, IOException {
String jsonState = URLDecoder.<span style="color: dodgerblue;">decode</span>(req.<span style="color: dodgerblue;">getParameter</span>(<span style="color: #aa5500;">"statement"</span>));
PersistenceManager pm = PMF.<span style="color: dodgerblue;">get</span>().<span style="color: dodgerblue;">getPersistenceManager</span>();
JSONObject jsonResp = <span style="color: #0000aa;">new</span> JSONObject();
<span style="color: #0000aa;">try</span> {
JSONObject jsonObject = <span style="color: #0000aa;">new</span> JSONObject(jsonState);
castMessage(pm, jsonObject);
jsonResp.<span style="color: dodgerblue;">put</span>(<span style="color: #aa5500;">"result"</span>, <span style="color: #aa5500;">"ok"</span>);
resp.<span style="color: dodgerblue;">setContentType</span>(<span style="color: #aa5500;">"text/json"</span>);
resp.<span style="color: dodgerblue;">setCharacterEncoding</span>(<span style="color: #aa5500;">"UTF-8"</span>);
resp.<span style="color: dodgerblue;">getWriter</span>().<span style="color: dodgerblue;">println</span>(jsonResp.<span style="color: dodgerblue;">toString</span>());
} <span style="color: #0000aa;">catch</span> (Exception e) {
resp.<span style="color: dodgerblue;">setContentType</span>(<span style="color: #aa5500;">"text/plain"</span>);
resp.<span style="color: dodgerblue;">getWriter</span>().<span style="color: dodgerblue;">println</span>(e.<span style="color: dodgerblue;">getMessage</span>());
e.<span style="color: dodgerblue;">printStackTrace</span>();
} <span style="color: #0000aa;">finally</span> {
pm.<span style="color: dodgerblue;">close</span>();
}
}</pre>
</pre>
</blockquote>
</td></tr>
</tbody></table>
</pre>
<br />
Step 2 : <span style="background-color: white; font-weight: bold;">在war/WEB-INF/web.xml加入servlet路徑宣告,在<web-app>標籤之間加入</span><br />
<pre><div style="background-color: white;">
<table border="1" ddd="" style="color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 13px; line-height: 18px;"><tbody>
<tr><td><blockquote class="tr_bq">
<pre style="color: #333333; line-height: 16px;"><pre><span style="color: #204a87; font-weight: bold;"> <servlet></span>
<span style="color: #204a87; font-weight: bold;"><servlet-name></span>SendMessage<span style="color: #204a87; font-weight: bold;"></servlet-name></span>
<span style="color: #204a87; font-weight: bold;"><servlet-class></span>com.whilerain.gae.chatroom.SendMessage<span style="color: #204a87; font-weight: bold;"></servlet-class></span>
<span style="color: #204a87; font-weight: bold;"></servlet></span>
<span style="color: #204a87; font-weight: bold;"><servlet-mapping></span>
<span style="color: #204a87; font-weight: bold;"><servlet-name></span>SendMessage<span style="color: #204a87; font-weight: bold;"></servlet-name></span>
<span style="color: #204a87; font-weight: bold;"><url-pattern></span>/sendmsg<span style="color: #204a87; font-weight: bold;"></url-pattern></span>
<span style="color: #204a87; font-weight: bold;"></servlet-mapping></span></pre>
</pre>
</blockquote>
</td></tr>
</tbody></table>
</div>
</pre>
Step 3 : 上傳目前版本<br />
<hr />
<h3>
<span style="color: orange;">Check Point 6 : 將訊息丟給GCM廣播至裝置</span></h3>
<h4>
Step 1 : 在GAE_ChatRoom專案加入gcm-server.jar參考 (已加入Project中)</h4>
<h4>
<ul>
<li>將gcm-server.jar複製到war/WEB-INF/lib</li>
<li>並且在CoWallet-GAE右鍵 > properties > java build path > Library > add JAR 選擇gcm-server.jar</li>
</ul>
Step 2 : 在GAE_ChatRoom專案加入json-simple-1.1.1.jar (已加入Project中)</h4>
<h4>
<ul>
<li>將json-simple-1.1.1.jar複製到war/WEB-INF/lib</li>
</ul>
</h4>
<h4>
Step 3 : 在GAE_ChatRoom專案加入設定API_KEY</h4>
<h4>
<ul>
<li>在GCM.java置換在<a href="https://code.google.com/apis/console/">Google API Console</a>所申請的API_KEY參數</li>
</ul>
<div>
<pre style="font-weight: normal;"><table border="1" ddd="" style="color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 13px; line-height: 18px;"><tbody>
<tr><td><blockquote class="tr_bq">
<pre style="color: #333333; line-height: 16px;"><pre><span style="color: #0000aa;">public</span> <span style="color: #0000aa;">static</span> String API_KEY = <span style="color: #aa5500;">"AIzaSyBY0AYX9RdPpvsAmnyjuwm9hl1-Xh..."</span>;</pre>
</pre>
</blockquote>
</td></tr>
</tbody></table>
</pre>
</div>
</h4>
<h4>
Step 4 : cast to GCM 程式碼</h4>
<h4>
<ul>
<li><span style="font-weight: normal;">在SendMessage.java, 加入castMessage()來將所有regid取出,並依序將message丟給GCM</span></li>
</ul>
<div>
<pre style="font-weight: normal;"><table border="1" ddd="" style="color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 13px; line-height: 18px;"><tbody>
<tr><td><blockquote class="tr_bq">
<pre style="color: #333333; line-height: 16px;"><pre><span style="color: #0000aa;">private</span> <span style="color: #00aaaa;">void</span> <span style="color: #00aa00;">castMessage</span>(PersistenceManager pm, JSONObject jsonReq) <span style="color: #0000aa;">throws</span> IOException {
Query queryRegid = pm.<span style="color: dodgerblue;">newQuery</span>(GcmRegister.<span style="color: dodgerblue;">class</span>);
List<GcmRegister> reg_results = (List<GcmRegister>) queryRegid.<span style="color: dodgerblue;">execute</span>();
<span style="color: #0000aa;">for</span> (GcmRegister gcmReg : reg_results) {
GCM.<span style="color: dodgerblue;">cast</span>(pm, gcmReg.<span style="color: dodgerblue;">getRegid</span>(), jsonReq.<span style="color: dodgerblue;">toString</span>(), gcmReg.<span style="color: dodgerblue;">getMember</span>());
}
}</pre>
</pre>
</blockquote>
</td></tr>
</tbody></table>
</pre>
</div>
</h4>
<h4>
Step 5 : 在GCM.java當中實作Cast to GCM</h4>
<h3>
<pre style="font-size: medium; font-weight: normal;"><table border="1" ddd="" style="color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 13px; line-height: 18px;"><tbody>
<tr><td><blockquote class="tr_bq">
<pre style="color: #333333; line-height: 16px;"><pre><span style="color: #0000aa;">public</span> <span style="color: #0000aa;">static</span> <span style="color: #00aaaa;">void</span> <span style="color: #00aa00;">cast</span>(PersistenceManager pm, String regid, String content) <span style="color: #0000aa;">throws</span> IOException{
Sender sender = <span style="color: #0000aa;">new</span> Sender(API_KEY);
Message.<span style="color: dodgerblue;">Builder</span> builder = <span style="color: #0000aa;">new</span> Message.<span style="color: dodgerblue;">Builder</span>();
builder.<span style="color: dodgerblue;">addData</span>(<span style="color: #aa5500;">"timestamp"</span>, String.<span style="color: dodgerblue;">valueOf</span>(System.<span style="color: dodgerblue;">currentTimeMillis</span>()));
builder.<span style="color: dodgerblue;">addData</span>(<span style="color: #aa5500;">"statement"</span>, URLEncoder.<span style="color: dodgerblue;">encode</span>(content,<span style="color: #aa5500;">"UTF-8"</span>));
Message message = builder.<span style="color: dodgerblue;">build</span>();
Result result = sender.<span style="color: dodgerblue;">send</span>(message, regid, <span style="color: #009999;">5</span>);
<span style="color: #0000aa;">if</span> (result.<span style="color: dodgerblue;">getMessageId</span>() != <span style="color: #0000aa;">null</span>) {
String canonicalRegId = result.<span style="color: dodgerblue;">getCanonicalRegistrationId</span>();
<span style="color: #0000aa;">if</span> (canonicalRegId != <span style="color: #0000aa;">null</span>) {
<span style="color: #aaaaaa; font-style: italic;">// same device has more than one registration ID: update</span>
<span style="color: #aaaaaa; font-style: italic;">// database</span>
GcmRegister reg = pm.<span style="color: dodgerblue;">getObjectById</span>(GcmRegister.<span style="color: dodgerblue;">class</span>, regid);
pm.<span style="color: dodgerblue;">deletePersistent</span>(reg);
reg = <span style="color: #0000aa;">new</span> GcmRegister(canonicalRegId);
pm.<span style="color: dodgerblue;">makePersistent</span>(reg);
}
} <span style="color: #0000aa;">else</span> {
String error = result.<span style="color: dodgerblue;">getErrorCodeName</span>();
<span style="color: #0000aa;">if</span> (error.<span style="color: dodgerblue;">equals</span>(Constants.<span style="color: dodgerblue;">ERROR_NOT_REGISTERED</span>)) {
<span style="color: #aaaaaa; font-style: italic;">// application has been removed from device - unregister from</span>
<span style="color: #aaaaaa; font-style: italic;">// database</span>
GcmRegister reg = pm.<span style="color: dodgerblue;">getObjectById</span>(GcmRegister.<span style="color: dodgerblue;">class</span>, regid);
pm.<span style="color: dodgerblue;">deletePersistent</span>(reg);
}
}
}</pre>
</pre>
</blockquote>
</td></tr>
</tbody></table>
</pre>
</h3>
<hr />
<h3>
<span style="color: orange;">Check point 7 : Android端取得裝置GCM Registration id,並註冊到Server上</span></h3>
<div>
Step 1 : 修改SENDER_ID</div>
<div>
<ul>
<li>將MainActivity.java中的SENDER_ID改為Google API Console的 Project number</li>
</ul>
<div>
<div>
<pre><table border="1" ddd="" style="color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 13px; line-height: 18px;"><tbody>
<tr><td><blockquote class="tr_bq">
<pre style="color: #333333; line-height: 16px;"><pre>String SENDER_ID = <span style="color: #aa5500;">"36994572588"</span>;</pre>
</pre>
</blockquote>
</td></tr>
</tbody></table>
</pre>
</div>
<ul></ul>
</div>
</div>
<div>
Step 2 : 修改Server URL</div>
<div>
<ul>
<li>修改URL為GAE的project name</li>
</ul>
</div>
<div>
<pre><table border="1" ddd="" style="color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 13px; line-height: 18px;"><tbody>
<tr><td><blockquote class="tr_bq">
<pre style="color: #333333; line-height: 16px;"><pre><span style="color: #0000aa;">private</span> <span style="color: #0000aa;">static</span> <span style="color: #0000aa;">final</span> String URL_GCMREG = <span style="color: #aa5500;">"http://your-gae-projectname.appspot.com/gcmreg"</span>;</pre>
</pre>
</blockquote>
</td></tr>
</tbody></table>
</pre>
</div>
<div>
Step 3 : 在MainActivity.java中收到regid後,使用http post註冊到server上</div>
<div>
<ul>
<li>送出http post到Server上</li>
</ul>
</div>
<div>
<pre><table border="1" ddd="" style="color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 13px; line-height: 18px;"><tbody>
<tr><td><blockquote class="tr_bq">
<pre style="color: #333333; line-height: 16px;"><pre><span style="color: #0000aa;">private</span> <span style="color: #00aaaa;">boolean</span> <span style="color: #00aa00;">sendRegistrationIdToBackend</span>(String regid) {
ArrayList<NameValuePair> paramList = <span style="color: #0000aa;">new</span> ArrayList<NameValuePair>();
<span style="color: #0000aa;">try</span> {
JSONObject statement = <span style="color: #0000aa;">new</span> JSONObject();
statement.<span style="color: dodgerblue;">put</span>(<span style="color: #aa5500;">"action"</span>, <span style="color: #aa5500;">"GcmReg"</span>);
statement.<span style="color: dodgerblue;">put</span>(<span style="color: #aa5500;">"regid"</span>, regid);
paramList.<span style="color: dodgerblue;">add</span>(<span style="color: #0000aa;">new</span> BasicNameValuePair(<span style="color: #aa5500;">"statement"</span>, statement.<span style="color: dodgerblue;">toString</span>()));
String result = Util.<span style="color: dodgerblue;">sentHttpPost</span>(URL_GCMREG, paramList, Util.<span style="color: dodgerblue;">getHttpClient</span>());
<span style="color: #0000aa;">if</span> (result == <span style="color: #0000aa;">null</span>) {
<span style="color: #0000aa;">return</span> <span style="color: #0000aa;">false</span>;
} <span style="color: #0000aa;">else</span> {
JSONObject json = <span style="color: #0000aa;">new</span> JSONObject(result);
<span style="color: #0000aa;">if</span> (json.<span style="color: dodgerblue;">get</span>(<span style="color: #aa5500;">"result"</span>).<span style="color: dodgerblue;">equals</span>(<span style="color: #aa5500;">"ok"</span>)) {
<span style="color: #0000aa;">return</span> <span style="color: #0000aa;">true</span>;
} <span style="color: #0000aa;">else</span> {
<span style="color: #0000aa;">return</span> <span style="color: #0000aa;">false</span>;
}
}
} <span style="color: #0000aa;">catch</span> (Exception e) {
e.<span style="color: dodgerblue;">printStackTrace</span>();
<span style="color: #0000aa;">return</span> <span style="color: #0000aa;">false</span>;
}
}</pre>
<div>
</div>
</pre>
</blockquote>
</td></tr>
</tbody></table>
</pre>
</div>
<hr />
<h3>
<span style="color: orange;">Check point 8 : Android傳送訊息到Server上,廣播給其他使用者</span></h3>
<div>
Step 1 : 實作SendMessageTask</div>
<div>
<ul>
<li>在SendMessageTask.java當中,修改URL_SENDMESSAGE參數為你的Server</li>
</ul>
<div>
<pre><table border="1" ddd="" style="color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 13px; line-height: 18px;"><tbody>
<tr><td><blockquote class="tr_bq">
<pre style="color: #333333; line-height: 16px;"><pre><span style="color: #0000aa;">private</span> <span style="color: #0000aa;">static</span> <span style="color: #0000aa;">final</span> String URL_SENDMESSAGE = <span style="color: #aa5500;">"http://[project-identifier].appspot.com/sendmsg"</span>;</pre>
</pre>
</blockquote>
</td></tr>
</tbody></table>
</pre>
</div>
<ul>
<li>在SendMessageTask.java當中送出Http Post到Server</li>
</ul>
<div>
<div>
<pre><table border="1" ddd="" style="color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 13px; line-height: 18px;"><tbody>
<tr><td><blockquote class="tr_bq">
<pre style="color: #333333; line-height: 16px;"><pre><span style="color: #888888;">@Override</span>
<span style="color: #0000aa;">protected</span> Boolean <span style="color: #00aa00;">doInBackground</span>(Void... params) {
ArrayList<NameValuePair> paramList = <span style="color: #0000aa;">new</span> ArrayList<NameValuePair>();
<span style="color: #0000aa;">try</span>{
JSONObject statement = <span style="color: #0000aa;">new</span> JSONObject();
statement.<span style="color: dodgerblue;">put</span>(<span style="color: #aa5500;">"action"</span>, <span style="color: #aa5500;">"SendMessage"</span>);
statement.<span style="color: dodgerblue;">put</span>(<span style="color: #aa5500;">"message"</span>, mMessage);
statement.<span style="color: dodgerblue;">put</span>(<span style="color: #aa5500;">"member"</span>, mName);
paramList.<span style="color: dodgerblue;">add</span>(<span style="color: #0000aa;">new</span> BasicNameValuePair(<span style="color: #aa5500;">"statement"</span>, statement.<span style="color: dodgerblue;">toString</span>()));
String result = Util.<span style="color: dodgerblue;">sentHttpPost</span>(URL_SENDMESSAGE, paramList, Util.<span style="color: dodgerblue;">getHttpClient</span>());
<span style="color: #0000aa;">if</span> (result == <span style="color: #0000aa;">null</span>) {
<span style="color: #0000aa;">return</span> <span style="color: #0000aa;">false</span>;
} <span style="color: #0000aa;">else</span> {
JSONObject json = <span style="color: #0000aa;">new</span> JSONObject(result);
<span style="color: #0000aa;">if</span>(json.<span style="color: dodgerblue;">get</span>(<span style="color: #aa5500;">"result"</span>).<span style="color: dodgerblue;">equals</span>(<span style="color: #aa5500;">"ok"</span>)){
<span style="color: #0000aa;">return</span> <span style="color: #0000aa;">true</span>;
}<span style="color: #0000aa;">else</span>{
<span style="color: #0000aa;">return</span> <span style="color: #0000aa;">false</span>;
}
}
}<span style="color: #0000aa;">catch</span>(Exception e){
e.<span style="color: dodgerblue;">printStackTrace</span>();
<span style="color: #0000aa;">return</span> <span style="color: #0000aa;">false</span>;
}
}</pre>
</pre>
</blockquote>
</td></tr>
</tbody></table>
</pre>
</div>
</div>
Step 2 : 送出SendMessage Http Post要求<br />
<ul>
<li>在MainActivity中當使用者按下傳送按鈕後,將訊息透過SendMessageTask送出</li>
</ul>
</div>
<div>
<pre><table border="1" ddd="" style="color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 13px; line-height: 18px;"><tbody>
<tr><td><blockquote class="tr_bq">
<pre style="color: #333333; line-height: 16px;"><pre><span style="color: #0000aa;">protected</span> <span style="color: #00aaaa;">void</span> <span style="color: #00aa00;">doSend</span>(String name, String message) {
SendMessageTask task = <span style="color: #0000aa;">new</span> SendMessageTask(name, message, <span style="color: #0000aa;">new</span> OnSendMessageListener() {
<span style="color: #888888;">@Override</span>
<span style="color: #0000aa;">public</span> <span style="color: #00aaaa;">void</span> <span style="color: #00aa00;">onPostExecute</span>(Boolean ok) {
<span style="color: #0000aa;">try</span> {
String msg;
<span style="color: #0000aa;">if</span> (ok) {
msg = <span style="color: #aa5500;">"Message send"</span>;
} <span style="color: #0000aa;">else</span> {
msg = <span style="color: #aa5500;">"ohhh! something wrong"</span>;
}
Toast.<span style="color: dodgerblue;">makeText</span>(MainActivity.<span style="color: dodgerblue;">this</span>, msg, Toast.<span style="color: dodgerblue;">LENGTH_SHORT</span>).<span style="color: dodgerblue;">show</span>();
} <span style="color: #0000aa;">catch</span> (Exception e) {
e.<span style="color: dodgerblue;">printStackTrace</span>();
}
}
});
task.<span style="color: dodgerblue;">execute</span>();
}</pre>
</pre>
</blockquote>
</td></tr>
</tbody></table>
</pre>
</div>
<hr />
<h3>
<span style="color: orange;">Check point 9 : 取得其他使用者的廣播內容</span></h3>
<div>
Step 1 : 接收與處理GCM訊息,並以LocalBroadcast廣播</div>
<div>
<ul>
<li>在GcmIntentService.java中,當收到來自GCM的訊息時,將內容以LocalBroadcast廣播給MainActivity來更新訊息列表內容</li>
</ul>
</div>
<div>
GcmIntentService.java</div>
<div>
<h3>
<pre style="font-size: medium; font-weight: normal;"><table border="1" ddd="" style="color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 13px; line-height: 18px;"><tbody>
<tr><td><blockquote class="tr_bq">
<pre style="color: #333333; line-height: 16px;"><pre>...
<span style="color: #0000aa;">if</span> (intent.<span style="color: dodgerblue;">getStringExtra</span>(<span style="color: #aa5500;">"statement"</span>) != <span style="color: #0000aa;">null</span>) {
String statement = URLDecoder.<span style="color: dodgerblue;">decode</span>(intent.<span style="color: dodgerblue;">getStringExtra</span>(<span style="color: #aa5500;">"statement"</span>));
String timestamp = URLDecoder.<span style="color: dodgerblue;">decode</span>(intent.<span style="color: dodgerblue;">getStringExtra</span>(<span style="color: #aa5500;">"timestamp"</span>));
<span style="color: #0000aa;">try</span> {
JSONObject castevent = <span style="color: #0000aa;">new</span> JSONObject(statement);
String event = castevent.<span style="color: dodgerblue;">getString</span>(<span style="color: #aa5500;">"action"</span>);
<span style="color: #0000aa;">if</span> (event.<span style="color: dodgerblue;">equalsIgnoreCase</span>(<span style="color: #aa5500;">"SendMessage"</span>)) {
String member = castevent.<span style="color: dodgerblue;">getString</span>(<span style="color: #aa5500;">"member"</span>);
String message = castevent.<span style="color: dodgerblue;">getString</span>(<span style="color: #aa5500;">"message"</span>);
sendLocalBroadcast(member, message);
Log.<span style="color: dodgerblue;">i</span>(TAG,<span style="color: #aa5500;">"Completed work @ "</span> + SystemClock.<span style="color: dodgerblue;">elapsedRealtime</span>());
sendNotification(<span style="color: #aa5500;">"Received: "</span> + extras.<span style="color: dodgerblue;">toString</span>());
Log.<span style="color: dodgerblue;">i</span>(TAG, <span style="color: #aa5500;">"Received: "</span> + extras.<span style="color: dodgerblue;">toString</span>());
}
} <span style="color: #0000aa;">catch</span> (Exception e) {
e.<span style="color: dodgerblue;">printStackTrace</span>();
}
}</pre>
</pre>
</blockquote>
</td></tr>
</tbody></table>
</pre>
</h3>
</div>
<div>
Step 2 : 傳送LocalBroadcast</div>
<div>
<ul>
<li>實作sendLocalBroadcast</li>
</ul>
</div>
<div>
<h3>
<pre style="font-size: medium; font-weight: normal;"><table border="1" ddd="" style="color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 13px; line-height: 18px;"><tbody>
<tr><td><blockquote class="tr_bq">
<pre style="color: #333333; line-height: 16px;"><pre><span style="color: #0000aa;">private</span> <span style="color: #00aaaa;">void</span> <span style="color: #00aa00;">sendLocalBroadcast</span>(String member, String message) {
Intent localIntent = <span style="color: #0000aa;">new</span> Intent(<span style="color: #aa5500;">"com.whilerain.chatroom.MESSAGE"</span>);
localIntent.<span style="color: dodgerblue;">putExtra</span>(<span style="color: #aa5500;">"member"</span>, member);
localIntent.<span style="color: dodgerblue;">putExtra</span>(<span style="color: #aa5500;">"message"</span>, message);
LocalBroadcastManager.<span style="color: dodgerblue;">getInstance</span>(<span style="color: #0000aa;">this</span>).<span style="color: dodgerblue;">sendBroadcast</span>(localIntent);
}</pre>
</pre>
</blockquote>
</td></tr>
</tbody></table>
</pre>
</h3>
</div>
<div>
Step 3 : 實作BroadcastReceiver物件<br />
<ul>
<li>在MainActivity中實作BroadcastReceiver,接收來自GcmIntentService的LocalBroadcast,並更新訊息列表</li>
</ul>
</div>
<div>
<pre><table border="1" ddd="" style="color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 13px; line-height: 18px;"><tbody>
<tr><td><blockquote class="tr_bq">
<pre style="color: #333333; line-height: 16px;"><pre>BroadcastReceiver mLocalBroadcastReceiver = <span style="color: #0000aa;">new</span> BroadcastReceiver() {
<span style="color: #888888;">@Override</span>
<span style="color: #0000aa;">public</span> <span style="color: #00aaaa;">void</span> <span style="color: #00aa00;">onReceive</span>(Context context, Intent intent) {
String member = intent.<span style="color: dodgerblue;">getStringExtra</span>(<span style="color: #aa5500;">"member"</span>);
String message = intent.<span style="color: dodgerblue;">getStringExtra</span>(<span style="color: #aa5500;">"message"</span>);
ChatMessage msg = <span style="color: #0000aa;">new</span> ChatMessage(member, message);
mList.<span style="color: dodgerblue;">add</span>(msg);
mListAdapter.<span style="color: dodgerblue;">notifyDataSetChanged</span>();
}
};</pre>
</pre>
</blockquote>
</td></tr>
</tbody></table>
</pre>
</div>
<h4>
Step 4 : 註冊與取消註冊BroadcastReceiver</h4>
<h4>
<ul>
<li>在MainActivity.onCreate()中註冊BroadcastReceiver, </li>
</ul>
</h4>
<div>
<pre><table border="1" ddd="" style="color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 13px; line-height: 18px;"><tbody>
<tr><td><blockquote class="tr_bq">
<pre style="color: #333333; line-height: 16px;"><pre>LocalBroadcastManager.<span style="color: dodgerblue;">getInstance</span>(<span style="color: #0000aa;">this</span>).<span style="color: dodgerblue;">registerReceiver</span>(mLocalBroadcastReceiver, <span style="color: #0000aa;">new</span> IntentFilter(<span style="color: #aa5500;">"com.whilerain.chatroom.MESSAGE"</span>));</pre>
</pre>
</blockquote>
</td></tr>
</tbody></table>
</pre>
</div>
<div>
<ul>
<li>並在MainActivity.onDestory()中取消註冊</li>
</ul>
</div>
<div>
<div>
<pre><table border="1" ddd="" style="color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 13px; line-height: 18px;"><tbody>
<tr><td><blockquote class="tr_bq">
<pre style="color: #333333; line-height: 16px;"><pre>LocalBroadcastManager.<span style="color: dodgerblue;">getInstance</span>(<span style="color: #0000aa;">this</span>).<span style="color: dodgerblue;">unregisterReceiver</span>(mLocalBroadcastReceiver);</pre>
</pre>
</blockquote>
</td></tr>
</tbody></table>
</pre>
</div>
</div>
<div>
<h3>
<pre style="font-size: medium; font-weight: normal;"><div style="font-family: 'LiHei Pro'; white-space: normal;">
</div>
</pre>
</h3>
<h3>
<pre style="font-size: medium; font-weight: normal; margin: 0px;"><div style="font-family: 'LiHei Pro'; white-space: normal;">
<pre></pre>
</div>
</pre>
</h3>
</div>
Anonymoushttp://www.blogger.com/profile/10433873918988135141noreply@blogger.com0tag:blogger.com,1999:blog-9873545.post-7843864611672541652013-10-09T01:56:00.000+08:002013-10-31T16:35:38.992+08:00Code Lab - RESTful App on Android : A POI Map<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhroV60rz2RzyiNjBqfE05315ophhqpWGdxVj5vxI-SJK3gLyGwIBJVWWPj6P55-KTBOQKzBdLE6XHaKEu_lKFoA6PWVchgxCEh_ENICsuo6ICsKKLK71PScHd_w1nwZn_phLix/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7+2013-10-09+%E4%B8%8A%E5%8D%881.45.45.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="210" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhroV60rz2RzyiNjBqfE05315ophhqpWGdxVj5vxI-SJK3gLyGwIBJVWWPj6P55-KTBOQKzBdLE6XHaKEu_lKFoA6PWVchgxCEh_ENICsuo6ICsKKLK71PScHd_w1nwZn_phLix/s400/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7+2013-10-09+%E4%B8%8A%E5%8D%881.45.45.png" width="400" /></a></div>
<h3>
此Android程式練習是為成大資工系-電腦通訊網路課程 所設計的一個Code Lab,目的在介紹REST架構的運作原理,以及在Android上面如何實作包含Google Map、Http Request、AsyncTask及UI Adapter應用。</h3>
<h3>
此App運用DEH API來開發一個簡易的LBS服務,查詢地圖中心附近2公里內所包含的景點有哪些。</h3>
<div>
課程時間:3小時<br />
<a href="https://docs.google.com/file/d/0B_nPmd5lFvJ9WXV1V1Jxdkc5cGM/edit?usp=sharing" target="_blank">投影片下載</a><br />
在Google Play下載:<a href="https://play.google.com/store/apps/details?id=com.whilerain.restdemo"><br />
<img alt="Get it on Google Play" src="https://developer.android.com/images/brand/zh-tw_generic_rgb_wo_45.png" /><br />
</a><br />
<a name='more'></a></div>
<hr />
<h3>
<b><span style="color: orange;">Check Point 0 : Android 環境設定</span></b></h3>
<h3>
<div style="font-size: medium; font-weight: normal;">
安裝設定Android開發環境,以繼續接下來的練習</div>
<div style="font-size: medium; font-weight: normal;">
<br /></div>
Step 1 : 下載並安裝Android ADT Bundle 並安裝Android SDK<br />
<br />
<ul>
<li><span style="font-weight: normal;">下載URL: </span><a href="http://developer.android.com/sdk/index.html">http://developer.android.com/sdk/index.html</a></li>
<li><span style="font-weight: normal;">開啟SDK Manager 並勾選Android4.3(API18)底下的SDK Platform 和Google API</span></li>
<li><span style="font-weight: normal;">按下Install package</span></li>
<li><span style="font-weight: normal;">點選Accept license > Install</span></li>
</ul>
<div>
<span style="font-weight: normal;">註:若無法開啟Eclipse,須先安裝JDK (</span><a href="http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html">http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html</a>)</div>
</h3>
<h4>
Step 2 : 下載RESTDemo Project ,並進行解壓縮</h4>
<ul>
<li>URL: <a href="https://docs.google.com/file/d/0B_nPmd5lFvJ9a0RmRlJWbjA5cnM/edit?usp=sharing" target="_blank">下載</a></li>
<li>Do not publish this code to Google Play !!</li>
</ul>
<h4>
Step 3 : 在新的Workspace 中,匯入RESTDemo Project</h4>
<div style="font-size: medium; font-weight: normal;">
</div>
<ul>
<li>File > Import > Android > Existing Android Code into Workspace</li>
<li>選擇Project路徑</li>
<li>按下Select All 按鈕</li>
<li>勾選 Copy project into workspace</li>
</ul>
<h4>
<span style="font-weight: normal;">Step 4 : 設定Project Build Target為Google APIs Level 18</span></h4>
<div>
<ul>
<li>Project上按右鍵 > Properties > Android > Project Build Target > Google APIs Level 18</li>
</ul>
</div>
<h4>
<span style="font-weight: normal;">Step 5 : 註冊下載Genymotion Android 模擬器 / 或使用Android 手機</span></h4>
<ul>
<li><a href="https://cloud.genymotion.com/">https://cloud.genymotion.com</a></li>
<li>完成註冊後依平台下載Genymotion </li>
<li>下載Vertual box <a href="https://www.virtualbox.org/wiki/Downloads">https://www.virtualbox.org/wiki/Downloads</a></li>
<li>下載Eclipse Plugin : ADT > Help > Install new software 加入url:http://plugins.genymotion.com/eclipse </li>
</ul>
Step 6 :建立模擬器<br />
<br />
<ul>
<li>執行Genymotion並建立一個Galaxy Nexus with Google App API17</li>
<li>下載完成後依指示設定Android SDK路徑</li>
<li>在手機設定中開啟Setting > Developer options > Usb debugging (若沒有Developer options,先到About phone裡面連點build number)</li>
</ul>
<br />
<div>
Step 7 :嘗試在模擬器上執行專案</div>
<div>
<ul></ul>
<span style="font-weight: normal;">*如果有任何錯誤,請坐下列檢查</span><br />
<br />
<ul>
<li>ADT > Project > clean > clean all</li>
<li>Project右鍵 > property > Android > 檢查Build Target 及 Library</li>
</ul>
<hr />
<h3>
<span style="color: orange; font-weight: normal;">Check Point 1 : Google Map API 環境</span></h3>
<h4>
<span style="font-weight: normal;">Step 1 : 下載Google Play Service SDK 並引用之 (此步驟已經完成)</span></h4>
<ul>
<li>Window > Android SDK Manager >Extras > Google Play Service 勾選並下載</li>
<li>File > Import > [sdk path]/extras/google/google play services/libproject/google_play_service_lib</li>
<li>Project name 右鍵 > Properties > Android > Library > Add > google-play-service_lib</li>
</ul>
<h4>
<span style="font-weight: normal;">Step 2 : 找到你的Debug Key SHA1指紋碼</span></h4>
<div>
<ul>
<li>ADT(Window) > Preferences> Android > build > SHA1 fingerprint</li>
</ul>
</div>
<h4>
<span style="font-weight: normal;">Step 3 : Google Console上設定Project</span></h4>
<div>
<ul>
<li><b><a href="https://code.google.com/apis/console/">https://code.google.com/apis/console/</a> Create Project</b></li>
<li>Services > Google Maps Android API v2 > On</li>
<li>API Access > Create Android Key > 輸入 [SHA1 fingerprint];com.whilerain.restdemo</li>
</ul>
Step 4 : 將Step 3取得的API Key填到AndroidManifest.xml中,<application>之內</application><br />
<application><br />
</application> <br />
<table border="1"><tbody>
<tr><td><blockquote class="tr_bq">
<pre style="color: #333333; line-height: 16px;"><span style="color: #007700;"><meta-data span=""><span style="color: #0000cc;">android:name=</span><span style="background-color: #fff0f0;">"com.google.android.maps.v2.API_KEY"</span>
<span style="color: #0000cc;">android:value=</span><span style="background-color: #fff0f0;">"AIzaSyAjP-Km7aFTWCRhvCTuuwiEf5NYIFw0EGQ"</span> <span style="color: #007700;">/></span></meta-data></span></pre>
</blockquote>
</td></tr>
</tbody></table>
</div>
<div>
<h4>
<span style="font-weight: normal;">Step 5 : 在虛擬機器上執行Project</span></h4>
</div>
<hr />
<div>
<h3>
<span style="color: orange;">Check Point 2 : Send HTTP Request</span></h3>
<br />
<ul>
<li>在MainActivity.doDataSearch()中置入送出Http request的程式碼,並以Log.i()來觀察取得的內容 (Window > showview > other > Android > Logcat)</li>
</ul>
<table border="1"><tbody>
<tr><td><span style="color: #008800; font-size: x-small; font-weight: bold; line-height: 16px;">private</span><span style="color: #333333; font-size: x-small; line-height: 16px;"> </span><span style="color: #333399; font-size: x-small; font-weight: bold; line-height: 16px;">void</span><span style="color: #333333; font-size: x-small; line-height: 16px;"> </span><span style="color: #0066bb; font-size: x-small; font-weight: bold; line-height: 16px;">doDataSearch</span><span style="color: #333333; font-size: x-small; line-height: 16px;">() {</span><br />
<pre style="color: #333333; line-height: 16px;"><span style="font-size: x-small;"> <span style="color: #008800; font-weight: bold;">try</span> {
String result = sentHttpRequest(API_GET_NEARBY_POI + <span style="background-color: #fff0f0;">"?"</span>+ <span style="background-color: #fff0f0;">"lat="</span> + defaultLocation.<span style="color: #0000cc;">latitude</span> + <span style="background-color: #fff0f0;">"&lng="</span> + defaultLocation.<span style="color: #0000cc;">longitude</span>+ <span style="background-color: #fff0f0;">"&dist=2000"</span>);
Log.<span style="color: #0000cc;">i</span>(<span style="background-color: #fff0f0;">"RESTDemo"</span>, result);
} <span style="color: #008800; font-weight: bold;">catch</span> (Exception e) {
e.<span style="color: #0000cc;">printStackTrace</span>();
}
}</span></pre>
</td><td><br /></td></tr>
</tbody></table>
<pre style="color: #333333; line-height: 16px;"><pre><span style="background-color: #f6f4f0; color: #444444; font-family: 'courier new'; font-size: 13px; line-height: normal; white-space: normal;"></span></pre>
</pre>
</div>
</div>
<span style="font-size: x-small;"><span style="color: #008800; font-weight: bold;"></span></span><span style="color: #008800; font-size: x-small; font-weight: bold;"></span><br />
<hr />
<h3>
<span style="color: orange;">Check Point 3 : Send HTTP Request with AsyncTask</span></h3>
<div>
<ul>
<li>在doDataSearch()中將Http request的程式碼換置為</li>
</ul>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: 'LiHei Pro'; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
<table border="1"><tbody>
<tr><td><blockquote class="tr_bq">
<pre style="color: #333333; line-height: 16px; margin: 0px;"><pre><span style="font-size: x-small;"><span style="color: #008800; font-weight: bold;">private</span> <span style="color: #333399; font-weight: bold;">void</span> <span style="color: #0066bb; font-weight: bold;">doDataSearch</span>() {
<span style="color: #008800; font-weight: bold;">new</span> <span style="color: #0066bb; font-weight: bold;">DataSearchAsyncTask</span>().<span style="color: #0000cc;">execute</span>();
}</span></pre>
</pre>
</blockquote>
</td></tr>
</tbody></table>
</div>
<pre style="line-height: 16px;"><span style="color: #008800; font-size: x-small;"><b></b></span></pre>
<ul>
<li>將原本在doDataSearch()中Http Request的程式碼,移至DataSearchAsyncTask.doInBackground當中</li>
</ul>
<div>
<pre style="color: #333333; line-height: 16px;"><pre style="color: black;"><div style="font-family: 'LiHei Pro'; line-height: normal; white-space: normal;">
<table border="1"><tbody>
<tr><td><blockquote class="tr_bq">
<pre style="color: #333333; line-height: 16px;"><pre><span style="font-size: x-small;"><span style="color: #555555; font-weight: bold;">@Override</span>
<span style="color: #008800; font-weight: bold;">protected</span> ArrayList<poi> <span style="color: #0066bb; font-weight: bold;">doInBackground</span>(Void... params) {
ArrayList<poi> list = <span style="color: #008800; font-weight: bold;">new</span> ArrayList<poi>();
<span style="color: #008800; font-weight: bold;">try</span> {
String result = sentHttpRequest(API_GET_NEARBY_POI + <span style="background-color: #fff0f0;">"?"</span>+ <span style="background-color: #fff0f0;">"lat="</span> + center.<span style="color: #0000cc;">latitude</span> + <span style="background-color: #fff0f0;">"&lng="</span> + center.<span style="color: #0000cc;">longitude</span>+ <span style="background-color: #fff0f0;">"&dist=2000"</span>);
} <span style="color: #008800; font-weight: bold;">catch</span> (Exception e) {
e.<span style="color: #0000cc;">printStackTrace</span>();
}
<span style="color: #008800; font-weight: bold;">return</span> <span style="color: #008800; font-weight: bold;">null</span>;
}</poi></poi></poi></span></pre>
</pre>
</blockquote>
</td></tr>
</tbody></table>
</div>
<pre><span style="color: #008800; font-size: x-small;"><b></b></span></pre>
<ul style="font-family: 'LiHei Pro'; line-height: normal; white-space: normal;"></ul>
</pre>
</pre>
</div>
</div>
<hr />
<div>
<h3>
<span style="color: orange;">Check Point 4 : Parse result and fill content to the ListView</span></h3>
</div>
<div>
<ul>
<li>將http取得的內容,使用JSONObject和JSONArray來儲存,在DataSearchTask. doInBackground()當中加入下列內容進行解析</li>
</ul>
<pre><pre style="color: #333333; line-height: 16px;"><pre style="color: black; line-height: normal;"><div style="font-family: 'LiHei Pro'; white-space: normal;">
<table border="1"><tbody>
<tr><td><blockquote class="tr_bq">
<pre style="color: #333333; line-height: 16px;"><pre><span style="font-size: x-small;">JSONObject jsonObject = <span style="color: #008800; font-weight: bold;">new</span> JSONObject(result);
JSONArray array = jsonObject.<span style="color: #0000cc;">getJSONArray</span>(<span style="background-color: #fff0f0;">"results"</span>);
<span style="color: #008800; font-weight: bold;">for</span> (<span style="color: #333399; font-weight: bold;">int</span> i = <span style="color: #0000dd; font-weight: bold;">0</span>; i < array.<span style="color: #0000cc;">length</span>(); i++) {
JSONObject poiObject = array.<span style="color: #0000cc;">getJSONObject</span>(i);
Poi poi = <span style="color: #008800; font-weight: bold;">new</span> Poi();
poi.<span style="color: #0000cc;">setDescript</span>(poiObject.<span style="color: #0000cc;">getString</span>(<span style="background-color: #fff0f0;">"POI_description"</span>));
poi.<span style="color: #0000cc;">setName</span>(poiObject.<span style="color: #0000cc;">getString</span>(<span style="background-color: #fff0f0;">"POI_title"</span>));
Double lat = Double.<span style="color: #0000cc;">parseDouble</span>(poiObject.<span style="color: #0000cc;">getString</span>(<span style="background-color: #fff0f0;">"latitude"</span>));
Double lng = Double.<span style="color: #0000cc;">parseDouble</span>(poiObject.<span style="color: #0000cc;">getString</span>(<span style="background-color: #fff0f0;">"longitude"</span>));
poi.<span style="color: #0000cc;">setLatlng</span>(<span style="color: #008800; font-weight: bold;">new</span> LatLng(lat, lng));
list.<span style="color: #0000cc;">add</span>(poi);
}</span></pre>
</pre>
</blockquote>
</td></tr>
</tbody></table>
</div>
</pre>
</pre>
<pre><ul>
<li><span style="font-family: 'LiHei Pro'; white-space: normal;">在DataSearchTask.onPostExecute()當中,更新ListView內容</span></li>
</ul>
<div style="font-family: 'LiHei Pro'; white-space: normal;">
<table border="1"><tbody>
<tr><td><blockquote class="tr_bq">
<pre style="color: #333333; line-height: 16px;"><pre><span style="font-size: x-small;"><span style="color: #008800; font-weight: bold;">if</span> (MainActivity.<span style="color: #0000cc;">this</span> != <span style="color: #008800; font-weight: bold;">null</span>) {
vRefreshBtn.<span style="color: #0000cc;">setVisible</span>(<span style="color: #008800; font-weight: bold;">true</span>);
vDrawerLayout.<span style="color: #0000cc;">openDrawer</span>(vDrawerList);
mPois = pois;
<span style="color: #008800; font-weight: bold;">if</span> (mAdapter == <span style="color: #008800; font-weight: bold;">null</span>) {
mAdapter = <span style="color: #008800; font-weight: bold;">new</span> PoiListAdapter();
vDrawerList.<span style="color: #0000cc;">setAdapter</span>(mAdapter);
} <span style="color: #008800; font-weight: bold;">else</span> {
mAdapter.<span style="color: #0000cc;">notifyDataSetChanged</span>();
}
}</span></pre>
</pre>
</blockquote>
</td></tr>
</tbody></table>
</div>
</pre>
</pre>
</div>
<hr />
<div>
<h3>
<span style="color: orange;">Check Point 5 : Shows POIs on the map </span></h3>
</div>
<div>
<ul>
<li>在initView()處,將ListView 加入回呼函數,處理當列表中某POI被選擇後的動作</li>
</ul>
<blockquote class="tr_bq">
<pre style="color: #333333; line-height: 16px;">vDrawerList.<span style="color: #0000cc;">setOnItemClickListener</span>(<span style="color: #008800; font-weight: bold;">new</span> DrawerItemClickListener());</pre>
</blockquote>
<ul>
<li>建立OnItemClickListener類別接收POI被選擇的事件</li>
</ul>
</div>
<div>
<pre style="color: #333333; line-height: 16px;"></pre>
<pre style="color: #333333; line-height: 16px;"></pre>
<pre style="color: #333333; line-height: 16px;"><pre><pre style="color: black; line-height: normal;"><div style="font-family: 'LiHei Pro'; white-space: normal;">
<table border="1"><tbody>
<tr><td><blockquote class="tr_bq">
<pre style="color: #333333; line-height: 16px;"><pre><pre><pre style="color: black; line-height: normal;"></pre>
</pre>
<pre><span style="font-size: x-small;"><span style="color: #008800; font-weight: bold;">private</span> <span style="color: #008800; font-weight: bold;">class</span> <span style="color: #bb0066; font-weight: bold;">DrawerItemClickListener</span> <span style="color: #008800; font-weight: bold;">implements</span> ListView.<span style="color: #0000cc;">OnItemClickListener</span> {
<span style="color: #555555; font-weight: bold;">@Override</span>
<span style="color: #008800; font-weight: bold;">public</span> <span style="color: #333399; font-weight: bold;">void</span> <span style="color: #0066bb; font-weight: bold;">onItemClick</span>(AdapterView parent, View view, <span style="color: #333399; font-weight: bold;">int</span> position, <span style="color: #333399; font-weight: bold;">long</span> id) {
selectItem(position);
}
}
<span style="color: #008800; font-weight: bold;">private</span> <span style="color: #333399; font-weight: bold;">void</span> <span style="color: #0066bb; font-weight: bold;">selectItem</span>(<span style="color: #333399; font-weight: bold;">int</span> position) {
LatLng latLng = Pois.<span style="color: #0000cc;">get</span>(position).<span style="color: #0000cc;">getLatlng</span>();
String title = mPois.<span style="color: #0000cc;">get</span>(position).<span style="color: #0000cc;">getName</span>();
String desc = Pois.<span style="color: #0000cc;">get</span>(position).<span style="color: #0000cc;">getDescript</span>();
vMap.<span style="color: #0000cc;">clear</span>();
vMap.<span style="color: #0000cc;">addMarker</span>(<span style="color: #008800; font-weight: bold;">new</span> MarkerOptions().<span style="color: #0000cc;">position</span>(latLng).<span style="color: #0000cc;">title</span>(title) .<span style="color: #0000cc;">snippet</span>(desc));
vMap.<span style="color: #0000cc;">moveCamera</span>(CameraUpdateFactory.<span style="color: #0000cc;">newLatLngZoom</span>(latLng, <span style="color: #0000dd; font-weight: bold;">18</span>));
vDrawerLayout.<span style="color: #0000cc;">closeDrawers</span>();
}</span></pre>
</pre>
</pre>
</blockquote>
</td></tr>
</tbody></table>
</div>
</pre>
</pre>
</pre>
</div>
Anonymoushttp://www.blogger.com/profile/10433873918988135141noreply@blogger.com0tag:blogger.com,1999:blog-9873545.post-2127868940272882482013-10-02T04:48:00.000+08:002013-10-02T12:38:31.260+08:00CoWallet<div style="background-color: white; color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 13px; line-height: 18px; text-align: center;">
<span style="font-size: 13px;"><b>Coming soon on Google Play!</b></span></div>
<div style="background-color: white; color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 13px; line-height: 18px; text-align: center;">
<br style="font-size: 13px;" /></div>
<div style="background-color: white; color: #666666; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 13px; line-height: 18px; text-align: center;">
<span style="font-size: 13px;">CoWallet makes expense management of a group easier.</span><br />
<span style="font-size: 13px;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLvaKJiJMON1Rv3zAXqEYApG2PlqU-zF3y9q3f4NZzmFbl56Grja3kFVkceIFm1IP2d0XfoULmA37SlI9TEYNcOBtlor29RzPtqIRMoP3s4IpEZj37YpRpdV9GuEbGSI5v730g/s1600/breezi_placeit+%25281%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="265" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLvaKJiJMON1Rv3zAXqEYApG2PlqU-zF3y9q3f4NZzmFbl56Grja3kFVkceIFm1IP2d0XfoULmA37SlI9TEYNcOBtlor29RzPtqIRMoP3s4IpEZj37YpRpdV9GuEbGSI5v730g/s400/breezi_placeit+%25281%2529.png" width="400" /></a></div>
<span style="font-size: 13px;"><br /></span></div>
Anonymoushttp://www.blogger.com/profile/10433873918988135141noreply@blogger.com0tag:blogger.com,1999:blog-9873545.post-20338871804113130332013-06-26T01:45:00.000+08:002013-06-26T02:28:08.096+08:00Suunto Ambit:一支和Navier HUD操作邏輯酷似的錶<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIIrty_OUV869O-yYai5HfcQIuGdKuoVIraDUV-703whwNsiPiMpEcWP7XB4Xf6TgNEeKD0buJiXvs_VGQrsIc_W8KTvwtYMQ9HvGy5Epo-Cd7H-T3WVfreC4myJOzblQ0IBGV/s1600/Suunto-Ambit-Black-3777.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIIrty_OUV869O-yYai5HfcQIuGdKuoVIraDUV-703whwNsiPiMpEcWP7XB4Xf6TgNEeKD0buJiXvs_VGQrsIc_W8KTvwtYMQ9HvGy5Epo-Cd7H-T3WVfreC4myJOzblQ0IBGV/s320/Suunto-Ambit-Black-3777.png" width="320" /></a></div>
不久前買了一支手錶Suunto Ambit,原本只是期待有個功能穩定具有GPS軌跡記錄功能的手錶,不過卻發現其操作邏輯和Navier HUD的使用邏輯相當接近。<br />
<br />
荷蘭廠商Suunto將Suunto Ambit其定位為適合專業登山及運動的電子錶,以硬體規格來看,這隻錶具有GPS接收器、氣溫計、氣壓(高度)計、羅盤四種Sensor,並且可以無線連接心律帶,因而能夠提供GPS定位、軌跡記錄、提供氣溫、垂直水平移動速度、距離、高度等資訊,並具有100米防水的規格,也就是你絕對可以帶著去進行大部分水中的活動,並絕對可以提供大部分運動時的需求。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8gMe3PRCiEOdP5q6Av6fpKrKqfeXcS4UnAPUmt1pt_GuofMHwh2v3zb76hehRLPJgTPSc_NusdTOmNsEkaqUQM7uniB9qU3-PbgA8Ym3ItJbWYHt8o9QrWONpynJBhOrFeqQA/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7+2013-06-26+%E4%B8%8A%E5%8D%8812.37.53.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="192" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8gMe3PRCiEOdP5q6Av6fpKrKqfeXcS4UnAPUmt1pt_GuofMHwh2v3zb76hehRLPJgTPSc_NusdTOmNsEkaqUQM7uniB9qU3-PbgA8Ym3ItJbWYHt8o9QrWONpynJBhOrFeqQA/s400/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7+2013-06-26+%E4%B8%8A%E5%8D%8812.37.53.png" width="400" /></a></div>
<br />
透過Movecounts帳號,可以輕易的將運動記錄保留下來,並分享到其他社群網站當中。並且在Movescount網頁中調教你的手錶設定<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSivspF-GNHLljC61PhUcI6Qh3r3xnj7Ywl4RMUMRTnrqbaCxV4Galwc9MCmQMkLNvBIQUv5UspRbUGFuQKkVQeE7P5xHDCYqQcNbMnhu818pjHFgXIHw9LydQXsGvlxsOqOZl/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7+2013-06-26+%E4%B8%8A%E5%8D%8812.40.54.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSivspF-GNHLljC61PhUcI6Qh3r3xnj7Ywl4RMUMRTnrqbaCxV4Galwc9MCmQMkLNvBIQUv5UspRbUGFuQKkVQeE7P5xHDCYqQcNbMnhu818pjHFgXIHw9LydQXsGvlxsOqOZl/s320/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7+2013-06-26+%E4%B8%8A%E5%8D%8812.40.54.png" width="260" /></a></div>
<br />
只要安裝Moveslink這個軟體,並將手錶連接到電腦上,就能進行資料同步。<br />
<br />
但以上都不是重點,以下才是重點XDDD<br />
<br />
到底哪裡和Navier HUD有夠相似呢?以下兩點說明:<br />
<br />
<h3>
自定資訊顯示面板</h3>
<div>
Suunto Ambit中提供了幾種預設的運動模式,也可以自行調整或新增運動模式,每種運動模式能夠顯示最多八個畫面的內容,每個畫面可以自行調整要顯示哪些資訊。</div>
<div>
<br /></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-GwuiARSHKzJdDJ2B2jqHGom817XWs7wMFlamw_KYFQsf-jsNXt-t8_VT_msaLZUgY0YFnJaVRKz5c2kzzHjTHo4uC06JYDoe19AjJ4TQ2ab1KoUUQOlcCmab6IESrJIUaQjM/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7+2013-06-26+%E4%B8%8A%E5%8D%8812.48.07.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="223" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-GwuiARSHKzJdDJ2B2jqHGom817XWs7wMFlamw_KYFQsf-jsNXt-t8_VT_msaLZUgY0YFnJaVRKz5c2kzzHjTHo4uC06JYDoe19AjJ4TQ2ab1KoUUQOlcCmab6IESrJIUaQjM/s400/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7+2013-06-26+%E4%B8%8A%E5%8D%8812.48.07.png" width="400" /></a></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkNYXpOg5j5RWLmAEJWVuzkoZUNeMeflruFcpvW-wPZ-Yo6mlA_BqrvRmNfejNSy_8HLZHiOIrhgDKfjsXUoofQiMYt9RJjwVvC9u4UXsin8Bkyf-a9IP9XjTpjFHqs4gLhMIN/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7+2013-06-26+%E4%B8%8A%E5%8D%8812.49.16.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="233" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkNYXpOg5j5RWLmAEJWVuzkoZUNeMeflruFcpvW-wPZ-Yo6mlA_BqrvRmNfejNSy_8HLZHiOIrhgDKfjsXUoofQiMYt9RJjwVvC9u4UXsin8Bkyf-a9IP9XjTpjFHqs4gLhMIN/s400/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7+2013-06-26+%E4%B8%8A%E5%8D%8812.49.16.png" width="400" /></a></div>
<div>
<br /></div>
舉個例子,我希望在我跑步這個模式當中,能夠有五個畫面來顯示我需要的訊息,其中第一個畫面要顯示包含跑步累積時間、累積的距離、以及我的心律。第二個畫面則要顯示跑步的速度、平均速度及當時的氣溫。第三個畫面顯示我的上坡累計里程和下坡累計里程、目前時間...<br />
<br />
當我在執行跑步的模式時,我就能透過按鈕來切換到不同的畫面,查看我所定義的畫面。因此你可以調整各種運動所需要取得的內容,來因應當運動的需求。<br />
<br />
這樣的概念與Navier HUD可以依照需求來新增與編輯所需的面板,並且為每個面板加入適當的元件,邏輯一致。但Navier HUD因為手機畫面較大,能夠調整元件的位置較自由。Suunto Ambit則因為所配備的Sensor而能夠有更多移動資訊來源。<br />
<br />
<h3>
路線導航</h3>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9XGyBC3yLoCCkBEHWmbvz1OO6uiDJEo-OSobRSEzvZ7qLtovmind5MTVE4XUMZQ-6hoe8D1zfQpBW0Flb3-aXf10sM6bptjMbUng-eTgdcCRVpjJlSDoJGl5PvOnZvq54m_gD/s1600/Suunto-Ambit-Black-4301.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9XGyBC3yLoCCkBEHWmbvz1OO6uiDJEo-OSobRSEzvZ7qLtovmind5MTVE4XUMZQ-6hoe8D1zfQpBW0Flb3-aXf10sM6bptjMbUng-eTgdcCRVpjJlSDoJGl5PvOnZvq54m_gD/s320/Suunto-Ambit-Black-4301.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
Suunto Ambit因為具備GPS Sensor,因此也具備了簡單的導航功能,由於手錶操作限制,在使用導航功能之前,你需要在Movecounts先規劃完路線,並連接手錶與電腦將路線匯入之後,就可以開啟導航功能。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizakVRBpB2Vbly_ZMrKnF-S9nEvLK4mGz4x0hXIDyQSZjOP4QaBQhon0-g5F51w56zdYKhtXaen6U0wvWTgtsYgNBKR_SpOdZyRFi0Ppu_IMZuCzMzdqJ5pa7F6ZR1IQvmfn3M/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7+2013-06-26+%E4%B8%8A%E5%8D%881.12.17.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="193" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizakVRBpB2Vbly_ZMrKnF-S9nEvLK4mGz4x0hXIDyQSZjOP4QaBQhon0-g5F51w56zdYKhtXaen6U0wvWTgtsYgNBKR_SpOdZyRFi0Ppu_IMZuCzMzdqJ5pa7F6ZR1IQvmfn3M/s400/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7+2013-06-26+%E4%B8%8A%E5%8D%881.12.17.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
和Navier HUD同樣,你得先在地圖上找出要走的路,啟動導航之後,你只會看到該走的路線,而不包含其他的叉路。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
除了這些以外,Suunto Ambit也把App的概念帶進來,在Suunto Ambit當中所指的App,其實是以簡單的Script將本來已經有的數值資料,經過額外的計算產生另一個你所想要知道的資料。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
舉例來說,我常常一次跑步跑5公里,所以當我在跑步時想知道依我現在跑步的速率,以及累計的里程數來算,究竟還要跑多少時間才能跑完5公里?或者單車騎士在行進過程到底做了多少次衝刺?</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
這些資料在原本的手錶當中並沒有提供,使用者卻可以利用撰寫程式碼來建立符合自己需求的App,將計算結果放到某個運動模式的畫面中,並可以選擇把它分享在App Zone當中。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEht-86s1zZMzc6fLlO4x4AuM2fWTCoQF7L4Qal_V8gEY2D6gkrY3hyA5clukuEkw4ERZzgTbdNm-qYr1fc7zBLGqbzDIWBYRDBwtK-mUmmXYTLdBxa8O9nQwY0w9fzUD4hrw1dZ/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7+2013-06-26+%E4%B8%8A%E5%8D%881.34.30.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="222" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEht-86s1zZMzc6fLlO4x4AuM2fWTCoQF7L4Qal_V8gEY2D6gkrY3hyA5clukuEkw4ERZzgTbdNm-qYr1fc7zBLGqbzDIWBYRDBwtK-mUmmXYTLdBxa8O9nQwY0w9fzUD4hrw1dZ/s400/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7+2013-06-26+%E4%B8%8A%E5%8D%881.34.30.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
如果你懶得自己寫,或者不會寫程式,可以直接到App Zone當中找到適合你使用的App,其中已經有多達一千多個App,有很大的機會有其他人已經寫了你需要的計算了。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
這真是一支很酷的手錶,並且耗電也在可接受的範圍(沒使用GPS時,可以使用約30天,連續使用GPS且設定每秒一筆資料時,可以支撐八小時,和一般軌跡記錄器差不多),還有很多功能小細節沒有講,只好自己去體驗。這絕對不是勸拜文,如果你不小心拜了,也要記得連Navier HUD一起拜阿阿阿...</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<br />Anonymoushttp://www.blogger.com/profile/10433873918988135141noreply@blogger.com0tag:blogger.com,1999:blog-9873545.post-16992269916180172912013-04-13T19:29:00.003+08:002013-04-16T03:09:10.175+08:00抬頭顯示DIY<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCwhY0K0vJ-manIoZ7I6Z-iCdt0q7Zt7Y9730tSqg-HzuHFDysetlV17FP1Er2StEBnEgpJr4pDlI0f6MqnEMMkZ07vR8eRqKvIfV6BzYLY3MZwO6XhvWXV9Yo1PDRxou4rITt/s1600/DSC07575.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="265" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCwhY0K0vJ-manIoZ7I6Z-iCdt0q7Zt7Y9730tSqg-HzuHFDysetlV17FP1Er2StEBnEgpJr4pDlI0f6MqnEMMkZ07vR8eRqKvIfV6BzYLY3MZwO6XhvWXV9Yo1PDRxou4rITt/s400/DSC07575.JPG" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMsUILGD-3QpM-CM7frw0zJYdN8UG5f6b6-M3WOCHStM7ovDgc7hY5ILChl2eROVKpqtEKOHriOZQCgN6ygcjy8RyElEwP13yR_aL9MStsnOZTbl_fwHpzHL_YrDwhimknBHgK/s1600/DSC07598.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="265" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMsUILGD-3QpM-CM7frw0zJYdN8UG5f6b6-M3WOCHStM7ovDgc7hY5ILChl2eROVKpqtEKOHriOZQCgN6ygcjy8RyElEwP13yR_aL9MStsnOZTbl_fwHpzHL_YrDwhimknBHgK/s400/DSC07598.JPG" width="400" /></a></div>
<br />
<br />
常常有使用者問說在白天的時候,使用Navier HUD時是不是會看不清楚?<br />
是的,如果在大太陽下把手機放擋風玻璃下肯定會看不清楚,<br />
但如果需要在白天也能使用抬頭顯示,其實還是有方法可以自己DIY做到,<br />
<br />
<h3>
反光隔熱紙</h3>
<div>
<br /></div>
只要到汽車用品店購買一張反光隔熱紙,貼在手機映射的位置上,<br />
就能讓抬頭顯示影像在白天更清楚。<br />
一般市售隔熱紙都是一大張,因此需要依照自己的手機大小,動手裁切成適合的尺寸。<br />
我覺得在駕駛座左下角是最適合的位置,也不會擋到視野。<br />
<h3>
</h3>
<h3>
</h3>
<h3>
止滑墊</h3>
<div>
<br /></div>
且為了避免手機會在前方會滑來滑去,<br />
您可能還需要一個小小的止滑墊,也是在汽車用品店可以買到,<br />
<h3>
</h3>
<h3>
</h3>
<h3>
車充與電源線</h3>
<div>
<br /></div>
<div>
在使用抬頭顯示時,通常會把手機亮度開到最大,這時螢幕耗電量將大增,</div>
<div>
因此如果是長途使用時,會需要以車充來補充電源,車充在便利商店就可以買到。</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
如此一來,配合上Navier HUD您就有一個專業的抬頭顯示環境囉。</div>
<br />
在這裡下載Navier HUD<a href="https://play.google.com/store/apps/details?id=idv.xunqun.navier.premium"><br />
<img alt="Android app on Google Play" src="https://developer.android.com/images/brand/en_app_rgb_wo_45.png" /><br />
</a>Anonymoushttp://www.blogger.com/profile/10433873918988135141noreply@blogger.com1tag:blogger.com,1999:blog-9873545.post-41714922088122871792013-03-13T23:52:00.002+08:002013-03-14T00:05:25.396+08:00Google Partner Day 2013<div class="separator" style="clear: both; text-align: center;">
真高興能夠有機會參與Google Partner Day活動,這是我第一次參加,今年舉辦地點在台北寒舍艾美酒店,活動著實讓我獲益良多,</div>
<div class="separator" style="clear: both; text-align: center;">
活動主要分成兩個部分,Adsense和AdMob,我當然是選聽AdMob的部份</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiRhmkatKHq-Abh-7GR2IEJKSVfeBXriraj5xfrS4aZD0l5oCchQmGa1kB7n7VrXqHO1UU1wQGFuLqW0FEniNaUnqmCgkCzSssAdJh3ArPB-6X9Kyiv2L0tAeNPW3zK19JVvU4/s1600/IMG_20130313_131458.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiRhmkatKHq-Abh-7GR2IEJKSVfeBXriraj5xfrS4aZD0l5oCchQmGa1kB7n7VrXqHO1UU1wQGFuLqW0FEniNaUnqmCgkCzSssAdJh3ArPB-6X9Kyiv2L0tAeNPW3zK19JVvU4/s400/IMG_20130313_131458.jpg" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
多"螢"為活動主題</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjL_Ll3IewObXxnMDCmSw_UpCz_eI3Vx-UXHO1iRUf7Gp057K3nDcRsQBSyfm6ecYRjsJLOTksseyASSUd1rC3F1OvC1kfYq8nb3li4ZbGNOqAmmWc3TdzH1HRjAJb9RDYLuilU/s1600/FB_IMG_13631527028101138.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjL_Ll3IewObXxnMDCmSw_UpCz_eI3Vx-UXHO1iRUf7Gp057K3nDcRsQBSyfm6ecYRjsJLOTksseyASSUd1rC3F1OvC1kfYq8nb3li4ZbGNOqAmmWc3TdzH1HRjAJb9RDYLuilU/s400/FB_IMG_13631527028101138.jpg" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
寒舍酒店的場地</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgn15prKeo95xnrLsMh3NyEG8VrC_Qlz68N63kl8P0fq8A9tLV8PhGIgYYuFs8J1wduFeL59Exl5G_sl23RnkyOxCC8SufnPASe7PlaiahMqIjQ4asBlRQyRJzEhfkYfQfY_u1B/s1600/IMG_20130313_155121.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgn15prKeo95xnrLsMh3NyEG8VrC_Qlz68N63kl8P0fq8A9tLV8PhGIgYYuFs8J1wduFeL59Exl5G_sl23RnkyOxCC8SufnPASe7PlaiahMqIjQ4asBlRQyRJzEhfkYfQfY_u1B/s400/IMG_20130313_155121.jpg" width="400" /></a></div>
<br />
<div class="" style="clear: both; text-align: center;">
廣告類型和位置擺放的注意事項</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNXFEozRXaVq0ehOyRqf6wm0UVI9j922xe0QgWaTiLPUnkGpX9y4pX2PENzmZJam9-_ngjFB1H5XBWCwsFJhLPvWskdOpTlbal5uICCKkjA1lhPGYTKXvtMsQ28bNM5BkFBbES/s1600/IMG_20130313_160111.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNXFEozRXaVq0ehOyRqf6wm0UVI9j922xe0QgWaTiLPUnkGpX9y4pX2PENzmZJam9-_ngjFB1H5XBWCwsFJhLPvWskdOpTlbal5uICCKkjA1lhPGYTKXvtMsQ28bNM5BkFBbES/s400/IMG_20130313_160111.jpg" width="400" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
Sam Lu 聊成功經驗</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNYW_a7mj14eihPmxo_hCSieksXqSiMrXqLpuBzG8n_n8kXZNPYfxK3VAO8bV43vpHrd4pVZ0R0zvNb_GkS2zK2fEO4BZeD-gQyzufytfVi1kh22T-CpMDD1fZQHfuHAlIyLNH/s1600/IMG_20130313_152143.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNYW_a7mj14eihPmxo_hCSieksXqSiMrXqLpuBzG8n_n8kXZNPYfxK3VAO8bV43vpHrd4pVZ0R0zvNb_GkS2zK2fEO4BZeD-gQyzufytfVi1kh22T-CpMDD1fZQHfuHAlIyLNH/s400/IMG_20130313_152143.jpg" width="400" /></a></div>
<div class="" style="clear: both; text-align: center;">
這張圖很清楚的解釋使用px與dp在不同解析度螢幕的差異</div>
<div class="" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6oCwnx8WXdH-teTzKgsrNp9rQUU5hp5sA3lSAsKmYM2Ssf1WWR0pauEDLbIhif6iRK6mjBoBxBRcmMmE_TcmvXltZUEqNsw2JAhVm99pAAEVxF_TfkGRjBshygf_NZi7DIcjK/s1600/IMG_20130313_160432.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6oCwnx8WXdH-teTzKgsrNp9rQUU5hp5sA3lSAsKmYM2Ssf1WWR0pauEDLbIhif6iRK6mjBoBxBRcmMmE_TcmvXltZUEqNsw2JAhVm99pAAEVxF_TfkGRjBshygf_NZi7DIcjK/s400/IMG_20130313_160432.jpg" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
包含WhosCall的營運長和Sam Lu、Google代表等成員的座談</div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEgFOLFGb_w3bpg0R0mOTZqDC5W459-yfTB6MWJPO89Dd7dxg9a8AuFJyDQq5C560dKytxIVVWR0v7UuwB3ZaFHmsb_bHzDO-W63hGo2Mg0LYdwxc3VTP6SD5dXvmWmZCDo3Cw/s1600/IMG_20130313_151057.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEgFOLFGb_w3bpg0R0mOTZqDC5W459-yfTB6MWJPO89Dd7dxg9a8AuFJyDQq5C560dKytxIVVWR0v7UuwB3ZaFHmsb_bHzDO-W63hGo2Mg0LYdwxc3VTP6SD5dXvmWmZCDo3Cw/s400/IMG_20130313_151057.jpg" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
與會者的App Logo,Navier HUD也在上面</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
我認為其中最有幫助的是討論到如何讓自己的App被Google Play feature的部份,</div>
<div class="separator" style="clear: both; text-align: center;">
雖然現在我的app還沒有被feature過,不過我有信心那只是不久之後的事情罷了(自以為..) :D</div>
<div class="separator" style="clear: both; text-align: center;">
參加完活動又點燃了我的雄心壯志了</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-size: large;">2013我們一起成長吧</span></div>
<br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/10433873918988135141noreply@blogger.com0tag:blogger.com,1999:blog-9873545.post-87169687759811963402013-02-17T06:51:00.000+08:002013-03-04T01:22:24.786+08:00在Android 上模擬GPS位置<br />
最近在大翻修Navier HUD,<br />
為了加入一些過去做不到的特色,<br />
這些功能不是靠小改版就能處理的,<br />
因此把過去沒加入的遺珠之憾透過這一次翻修,<br />
整理整個架構。<br />
Google Map也使用新版本來寫,<br />
但在Google Map v2 API 無法在模擬器上執行,<br />
地圖的部分會變成下圖那樣一片黑<br />
並要求你更新Google Play Services<br />
只是基於安全政策,模擬器是沒辦法更新Google Play Service的<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9ApKUOPB3MDwoP-tO4jdRfTHfx32EPJrwMiDDjFiD5oqfsOZfESy7ZLZsTTBHBnqa35ZrWjCe1n3exvp2Sd1RXXHu4fZ_lfvHO0OWMBj9xpoNLkeYRSZD8HOT8GQItID0ngyf/s1600/device-2013-02-17-062656.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9ApKUOPB3MDwoP-tO4jdRfTHfx32EPJrwMiDDjFiD5oqfsOZfESy7ZLZsTTBHBnqa35ZrWjCe1n3exvp2Sd1RXXHu4fZ_lfvHO0OWMBj9xpoNLkeYRSZD8HOT8GQItID0ngyf/s320/device-2013-02-17-062656.png" width="320" /></a></div>
本來那也沒什麼,因為只要使用實機來測試就行了,<br />
在模擬器上執行有個好處,<br />
就是可以使用DDMS來餵模擬器kml或gpx格式的GPS資料,<br />
如果已經有了預先記錄好的GPS 經緯度資料,<br />
就可以拿來測試。<br />
一旦模擬器開不了地圖,這些GPS就沒用武之地了。<br />
<br />
如果程式碼中沒有使用到Google API元件<br />
可以參考此文章的作法<br />
<a href="http://nemanjakovacevic.net/blog/2012/12/how-to-make-android-google-maps-v2-work-in-android-emulator/">http://nemanjakovacevic.net/blog/2012/12/how-to-make-android-google-maps-v2-work-in-android-emulator/</a><br />
<br />
但如果需要使用Google API,上面的方法就沒用拉。<br />
既然實機不能用DDMS餵資料,<br />
最後只好自己寫程式餵自己APP資料拉。<br />
<br />
那在實機上怎麼餵假的GPS資料呢?<br />
這時會需要實作一個Mock Location Provider<br />
如下程式碼<br />
<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; background: white; border-width: .1em .1em .1em .8em; border: solid gray; color: black; overflow: auto; padding: .2em .6em; width: auto;">
<table><tbody>
<tr><td><pre style="line-height: 125%; margin: 0;">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33</pre>
</td><td><pre style="line-height: 125%; margin: 0;"><span style="color: green; font-weight: bold;">public</span> <span style="color: green; font-weight: bold;">class</span> <span style="color: #b00060; font-weight: bold;">MockLocationProvider</span> <span style="color: #303030;">{</span>
String providerName<span style="color: #303030;">;</span>
Context ctx<span style="color: #303030;">;</span>
<span style="color: green; font-weight: bold;">public</span> <span style="color: #0060b0; font-weight: bold;">MockLocationProvider</span><span style="color: #303030;">(</span>String name<span style="color: #303030;">,</span> Context ctx<span style="color: #303030;">)</span> <span style="color: #303030;">{</span>
<span style="color: green; font-weight: bold;">this</span><span style="color: #303030;">.</span><span style="color: #0000c0;">providerName</span> <span style="color: #303030;">=</span> name<span style="color: #303030;">;</span>
<span style="color: green; font-weight: bold;">this</span><span style="color: #303030;">.</span><span style="color: #0000c0;">ctx</span> <span style="color: #303030;">=</span> ctx<span style="color: #303030;">;</span>
LocationManager lm <span style="color: #303030;">=</span> <span style="color: #303030;">(</span>LocationManager<span style="color: #303030;">)</span> ctx
<span style="color: #303030;">.</span><span style="color: #0000c0;">getSystemService</span><span style="color: #303030;">(</span>Context<span style="color: #303030;">.</span><span style="color: #0000c0;">LOCATION_SERVICE</span><span style="color: #303030;">);</span>
lm<span style="color: #303030;">.</span><span style="color: #0000c0;">addTestProvider</span><span style="color: #303030;">(</span>providerName<span style="color: #303030;">,</span> <span style="color: green; font-weight: bold;">false</span><span style="color: #303030;">,</span> <span style="color: green; font-weight: bold;">false</span><span style="color: #303030;">,</span> <span style="color: green; font-weight: bold;">false</span><span style="color: #303030;">,</span> <span style="color: green; font-weight: bold;">false</span><span style="color: #303030;">,</span> <span style="color: green; font-weight: bold;">false</span><span style="color: #303030;">,</span>
<span style="color: green; font-weight: bold;">true</span><span style="color: #303030;">,</span> <span style="color: green; font-weight: bold;">true</span><span style="color: #303030;">,</span> <span style="color: #0000d0; font-weight: bold;">0</span><span style="color: #303030;">,</span> <span style="color: #0000d0; font-weight: bold;">5</span><span style="color: #303030;">);</span>
lm<span style="color: #303030;">.</span><span style="color: #0000c0;">setTestProviderEnabled</span><span style="color: #303030;">(</span>providerName<span style="color: #303030;">,</span> <span style="color: green; font-weight: bold;">true</span><span style="color: #303030;">);</span>
<span style="color: #303030;">}</span>
<span style="color: green; font-weight: bold;">public</span> <span style="color: #303090; font-weight: bold;">void</span> <span style="color: #0060b0; font-weight: bold;">pushLocation</span><span style="color: #303030;">(</span><span style="color: #303090; font-weight: bold;">double</span> lat<span style="color: #303030;">,</span> <span style="color: #303090; font-weight: bold;">double</span> lon<span style="color: #303030;">)</span> <span style="color: #303030;">{</span>
LocationManager lm <span style="color: #303030;">=</span> <span style="color: #303030;">(</span>LocationManager<span style="color: #303030;">)</span> ctx
<span style="color: #303030;">.</span><span style="color: #0000c0;">getSystemService</span><span style="color: #303030;">(</span>Context<span style="color: #303030;">.</span><span style="color: #0000c0;">LOCATION_SERVICE</span><span style="color: #303030;">);</span>
Location mockLocation <span style="color: #303030;">=</span> <span style="color: green; font-weight: bold;">new</span> Location<span style="color: #303030;">(</span>providerName<span style="color: #303030;">);</span>
mockLocation<span style="color: #303030;">.</span><span style="color: #0000c0;">setLatitude</span><span style="color: #303030;">(</span>lat<span style="color: #303030;">);</span>
mockLocation<span style="color: #303030;">.</span><span style="color: #0000c0;">setLongitude</span><span style="color: #303030;">(</span>lon<span style="color: #303030;">);</span>
mockLocation<span style="color: #303030;">.</span><span style="color: #0000c0;">setAltitude</span><span style="color: #303030;">(</span><span style="color: #0000d0; font-weight: bold;">0</span><span style="color: #303030;">);</span>
mockLocation<span style="color: #303030;">.</span><span style="color: #0000c0;">setTime</span><span style="color: #303030;">(</span>System<span style="color: #303030;">.</span><span style="color: #0000c0;">currentTimeMillis</span><span style="color: #303030;">());</span>
lm<span style="color: #303030;">.</span><span style="color: #0000c0;">setTestProviderLocation</span><span style="color: #303030;">(</span>providerName<span style="color: #303030;">,</span> mockLocation<span style="color: #303030;">);</span>
<span style="color: #303030;">}</span>
<span style="color: green; font-weight: bold;">public</span> <span style="color: #303090; font-weight: bold;">void</span> <span style="color: #0060b0; font-weight: bold;">shutdown</span><span style="color: #303030;">()</span> <span style="color: #303030;">{</span>
LocationManager lm <span style="color: #303030;">=</span> <span style="color: #303030;">(</span>LocationManager<span style="color: #303030;">)</span> ctx
<span style="color: #303030;">.</span><span style="color: #0000c0;">getSystemService</span><span style="color: #303030;">(</span>Context<span style="color: #303030;">.</span><span style="color: #0000c0;">LOCATION_SERVICE</span><span style="color: #303030;">);</span>
lm<span style="color: #303030;">.</span><span style="color: #0000c0;">removeTestProvider</span><span style="color: #303030;">(</span>providerName<span style="color: #303030;">);</span>
<span style="color: #303030;">}</span>
<span style="color: #303030;">}</span>
</pre>
</td></tr>
</tbody></table>
</div>
<br />
使用下列方式來餵一個假GPS位置,如果是模擬連續收到數個GPS位置可以以一個迴圈來提供位置,並mock.wait(int milisec)來處理時間間隔<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; background: white; border-width: .1em .1em .1em .8em; border: solid gray; color: black; overflow: auto; padding: .2em .6em; width: auto;">
<table><tbody>
<tr><td><pre style="line-height: 125%; margin: 0;">1
2
3</pre>
</td><td><pre style="line-height: 125%; margin: 0;">mock <span style="color: #303030;">=</span> <span style="color: green; font-weight: bold;">new</span> MockLocationProvider<span style="color: #303030;">(</span>LocationManager<span style="color: #303030;">.</span><span style="color: #0000c0;">GPS_PROVIDER</span><span style="color: #303030;">,</span> _context<span style="color: #303030;">);</span>
mock<span style="color: #303030;">.</span><span style="color: #0000c0;">pushLocation</span><span style="color: #303030;">(</span>point<span style="color: #303030;">.</span><span style="color: #0000c0;">lat</span><span style="color: #303030;">,</span> point<span style="color: #303030;">.</span><span style="color: #0000c0;">lng</span><span style="color: #303030;">);</span>
</pre>
</td></tr>
</tbody></table>
</div>
<br />
在AndroidManifest.xml需加入允許假位置的權限<br />
<br />
<span style="background-color: #eeeeee;"><span style="color: #38761d;"><span class="s1"><uses-permission span=""><span class="s2"> </span><span class="s3">android:name</span><span class="s4">=</span>"android.permission.ACCESS_MOCK_LOCATION"<span class="s1">;</span></uses-permission></span></span></span><br />
<span style="background-color: #eeeeee;"><span style="color: #38761d;"><span class="s1"><br /></span></span></span><span class="s1"><span style="background-color: white;">在測試的手機上必須在設定></span></span><span style="background-color: white;">開發人員選項>允許模擬位置 打勾</span><br />
<span style="background-color: white;"><br /></span>
<span style="background-color: white;"><br /></span>
<span class="s1" style="background-color: white;">最後,在釋出正式版本之前,記得要註解掉假GPS部分的程式碼。</span><br />
<br />
可以參考此連結文章了解<a href="http://mobiarch.wordpress.com/2012/07/17/testing-with-mock-location-data-in-android/">http://mobiarch.wordpress.com/2012/07/17/testing-with-mock-location-data-in-android/</a>Anonymoushttp://www.blogger.com/profile/10433873918988135141noreply@blogger.com1tag:blogger.com,1999:blog-9873545.post-36675643450965571172013-01-09T02:34:00.001+08:002013-01-09T03:24:33.914+08:00SlidingMenu開放原始碼專案<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFEtbsXjzVSoFPi-nuNtDtmW8T1BBTpTQMK7mo7jpnXAm5d6CzHg-BS9inbmxG3a47NefMqT6pKsLtGjT6xrAAJ7bZa7f4hbshpUsyR9fIdLdDuIynRkOOYqyplUF6XLZHp4pL/s1600/Screenshot_2013-01-09-00-42-12.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFEtbsXjzVSoFPi-nuNtDtmW8T1BBTpTQMK7mo7jpnXAm5d6CzHg-BS9inbmxG3a47NefMqT6pKsLtGjT6xrAAJ7bZa7f4hbshpUsyR9fIdLdDuIynRkOOYqyplUF6XLZHp4pL/s320/Screenshot_2013-01-09-00-42-12.png" width="180" /></a></div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6RTn3K9ijVJ7Dj5lRXsPy7st81Irq6IhQuTX8Grs-Y5cYRzyBAsxc6mIYhmi2DbqnrHjBv2JPvK4tSD4HAIioATUclEGpZ91EcBj4BRYlH1SWMxNw-4IwHVbL_rmNDAlvDrKG/s1600/Screenshot_2013-01-09-00-50-22.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6RTn3K9ijVJ7Dj5lRXsPy7st81Irq6IhQuTX8Grs-Y5cYRzyBAsxc6mIYhmi2DbqnrHjBv2JPvK4tSD4HAIioATUclEGpZ91EcBj4BRYlH1SWMxNw-4IwHVbL_rmNDAlvDrKG/s320/Screenshot_2013-01-09-00-50-22.png" width="180" /></a><br />
<br />
自從Android 3.0帶來了Fragment概念,<br />
除了對開發者需要面對多種size的Android裝置具有正面的意義外,<br />
讓Android Activity本來較為死板的換頁方式,帶來了更多變化,<br />
藉由在一個Activity上自由搭配多個Fragment,<br />
並結合越來越豐富的動畫效果,來切換不同的Fragment<br />
愈來愈多絢麗的頁面切換效果也逐漸出現在Android app上。<br />
<br />
其中最常見到,具有豐富視覺效果的切換特效非SlidingMenu莫屬,<br />
SlidingMenu效果可以在Evernote或是feedly兩個我個人常用的軟體中見到。<br />
使用SlidingMenu藉由兩個Fragment間(也可以是兩個ViewGroup)的滑行效果<br />
來切換介面。<br />
<br />
<h4>
<b>SlidingMenu Open Source Project</b></h4>
要實現這樣的效果需要自己設定許多Animation 的參數,<br />
藉由盧育聖(ysl程式設計天堂部落格作者)的粉絲頁分享,<br />
才知道這樣的效果已經有別人寫好,並開放原始碼與其他開發人員共享,<br />
在GooglePlay上有一個使用範例可以在下方連結中下載<br />
<a href="https://play.google.com/store/apps/details?id=com.slidingmenu.example">SlidingMenu Demos</a><br />
<br />
如果你也想在App中呈現這樣的效果,<br />
不需要自己造輪子,<br />
可以在GitHub上找到完整開放原始碼專案。<br />
<a href="https://github.com/jfeinstein10/SlidingMenu">SlidingMenu 開放原始碼專案</a><br />
<h4>
整合到你的專案</h4>
<div>
要將SlidingMenu整合到你的專案當中,</div>
<div>
需要下列幾個步驟:</div>
<div>
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
將開放原始碼專案下載下來,並匯入Eclipse當中。(在這之前你應該要裝好了Andorid 開發環境)其中會兩個Project,SlidingMenuActivity是主要我們要使用的部份,另一個ExampleListActivity是上述Google Play中可以下載的到的SlidingMenu Demo專案。不妨把兩個專案都載入,這個Example專案可以讓你了解該怎麼使用這個原始碼專案。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLkauWVf_6Vh83aE26w9pDvg40YHgobeOR1tuXvSnOA_ul1XJgihWnfX3GTnp_QIMuYhIbtr2iuHsehiSaQbBYjjbYMuRDrq6U9kz6jOPceH4GKt9pE7w2b0numO96NHiRwN3d/s1600/%25E8%259E%25A2%25E5%25B9%2595%25E5%25BF%25AB%25E7%2585%25A7+2013-01-09+%25E4%25B8%258A%25E5%258D%25881.21.57.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="378" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLkauWVf_6Vh83aE26w9pDvg40YHgobeOR1tuXvSnOA_ul1XJgihWnfX3GTnp_QIMuYhIbtr2iuHsehiSaQbBYjjbYMuRDrq6U9kz6jOPceH4GKt9pE7w2b0numO96NHiRwN3d/s400/%25E8%259E%25A2%25E5%25B9%2595%25E5%25BF%25AB%25E7%2585%25A7+2013-01-09+%25E4%25B8%258A%25E5%258D%25881.21.57.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div>
<br /></div>
<div>
因為專案中有提供MapActivity所以Android SDK需選擇有Google APIs的版本,載入專案之後先進行Project > Clean的動作,以產生必要的R.java檔。</div>
<div>
如果您的專案只支援3.0以上的版本,引用SlidingMenuActivity專案之後(在Package Explorer中,選擇ProjectName按下右鍵 > Properties > Android > Library > Add ),在您的專案裡就可以使用當中所提供的SlidingMenuActivity了。</div>
<h4>
Example 專案</h4>
<div>
如果你想要測試Example專案,這時應該還存在著錯誤,因為這個Example專案在Fragment和Action Bar的部份是使用Support Library來支援的,因此我前面才說,如果你專案只支援Android 3.0以上,那就不需要接下來的動作。</div>
<div>
但如果你的專案必須支援Android2.X甚至到Android1.6以上,那我們還需要進行一些設定。</div>
<div>
<br /></div>
<h4>
匯入ActionBarSherlock Open Source專案</h4>
<div>
<a href="http://actionbarsherlock.com/">下載</a>並在Eclipse當中匯入ActionBarSherlock專案,這個專案主要讓所有的Android版本都能夠使用只有在Android 3.0以上才支援的Action Bar的功能。其中有數個sample專案,但我們只需要匯入library這個專案(除非你想深入了解ActionBarSherlock要怎麼用)。</div>
<div>
<br /></div>
<div>
在SlidingMenuActivity當中引用ActionBarSherlock專案。 </div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxm-0dpYIFblEfM13GK5xepKDF45wFABOi0EfDrwUWfQPohK5Rw8dKupW3NbvBc8VO8DP_d_aybPFFYDUdyZZeIN21IWLPWuHyM-egr7as1Sfe7za0KvGkGcoErH_WRBNaJ0Q_/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7+2013-01-09+%E4%B8%8A%E5%8D%882.05.24.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="381" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxm-0dpYIFblEfM13GK5xepKDF45wFABOi0EfDrwUWfQPohK5Rw8dKupW3NbvBc8VO8DP_d_aybPFFYDUdyZZeIN21IWLPWuHyM-egr7as1Sfe7za0KvGkGcoErH_WRBNaJ0Q_/s400/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7+2013-01-09+%E4%B8%8A%E5%8D%882.05.24.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
因為Example專案當中使用了SlidingFragmentActivity,因此需要將SlidingFragmentActivity做些修改,以支援Android3.0以下的版本。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
修改SlidingMenuActivity中的SlidingFragmentActivity.java</div>
<div class="separator" style="clear: both; text-align: left;">
將原本extends FragmentActivity改成SherlockFragmentActivity</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhO-ksXktD0-8d2M6f1Iv4yvykpmSDSYE7I0Xr_GwxJdWGViWl2Cd_2W4rsDaJUWk7lATGQ42asTiYyZ6xyq1-UgoaEXSiqhQdp8vRHZrqUMkeo2wPckNhehWIxivi_Xa_Xl97N/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7+2013-01-09+%E4%B8%8A%E5%8D%882.07.01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhO-ksXktD0-8d2M6f1Iv4yvykpmSDSYE7I0Xr_GwxJdWGViWl2Cd_2W4rsDaJUWk7lATGQ42asTiYyZ6xyq1-UgoaEXSiqhQdp8vRHZrqUMkeo2wPckNhehWIxivi_Xa_Xl97N/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7+2013-01-09+%E4%B8%8A%E5%8D%882.07.01.png" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
完成後做一次Project > Clean,之後Example專案就可以順利執行了。</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5k-jlX7-f2SmKkjffE4yKE0094o3QeUMWubqtSty3EpxjivqFOvdedwWal_gf9gACnUeCf0l0M3dMFnGlrqx0R_CFS_zDqRk9tSo-1xhU5u6gHEwc7XDGORQfE4VTqKSu9DU5/s1600/Screenshot_2013-01-09-02-30-57.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5k-jlX7-f2SmKkjffE4yKE0094o3QeUMWubqtSty3EpxjivqFOvdedwWal_gf9gACnUeCf0l0M3dMFnGlrqx0R_CFS_zDqRk9tSo-1xhU5u6gHEwc7XDGORQfE4VTqKSu9DU5/s400/Screenshot_2013-01-09-02-30-57.png" width="225" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
透過這個Example專案,可以很輕易的了解如何使用SlidingMenu 專案,並製作出很具視覺效果的滑動切換頁面動畫了。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<br />
<br />Anonymoushttp://www.blogger.com/profile/10433873918988135141noreply@blogger.com0tag:blogger.com,1999:blog-9873545.post-58172225422684093982012-09-24T09:07:00.000+08:002012-09-25T08:38:16.271+08:00Navier HUD新的介紹影片前幾天剛完成的音樂,(音樂製作部分<a href="http://asnippets.blogspot.tw/2012/09/garageband-lets-rock-roll.html">參考這裡</a>)<br />
今天就拿來做新的影片,<br />
兩分鐘的影片,我做了八個多小時才完成,<br />
累翻了~~<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /><iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/4ZSwvMpCaVk?feature=player_embedded' frameborder='0'></iframe></div>
<br />Anonymoushttp://www.blogger.com/profile/10433873918988135141noreply@blogger.com24tag:blogger.com,1999:blog-9873545.post-33515785888495705122012-09-23T02:49:00.001+08:002012-09-24T20:18:29.830+08:00GarageBand - Let's rock & roll<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUJuqKjnT4ZA_d3ya6L4AgVpmiHxTpyGvCXYmEOGz5dR_ZGKEHbrHog-MrKp5z9GNsL5unI8RCV-5tnBR7Ujc0kxSeL4rs2wWTlpxfoSK-3FAKqaAPVaS4k8tJlk8QSA0JIBJI/s1600/287961_2_Rock_N_Roll.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="246" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUJuqKjnT4ZA_d3ya6L4AgVpmiHxTpyGvCXYmEOGz5dR_ZGKEHbrHog-MrKp5z9GNsL5unI8RCV-5tnBR7Ujc0kxSeL4rs2wWTlpxfoSK-3FAKqaAPVaS4k8tJlk8QSA0JIBJI/s400/287961_2_Rock_N_Roll.jpg" width="400" /></a></div>
<br />
首先,向每個獨立軟體開發者至上深深的敬意!<br />
因為獨立軟體開發者們實在是太強大了,(感覺良好中)<br />
在其他有正式編制的公司,或可以有數名夥伴的軟體開發者,<br />
可以找來有美術專長的人才,來負責美美的軟體和網頁介面,<br />
也可以找來具有音樂專長的人才,來負責合適各個種情況的音樂,<br />
有時候還需要具有影片編輯專長的人才,做出漂亮的商業影片!<br />
<br />
獨立軟體開發者,所有事情一手包辦,<br />
上從軟體Coding、網頁設計一直到宣傳影片、海報、音樂,<br />
全部自己來,不過這也沒辦法,<br />
誰叫我們那麼強大什麼都會XD<br />
以後就算不做獨立開發者,去業界工作,<br />
薪水也要要求從八萬起跳才行(謎:卡早睡才有眠,不要再做白日夢了)<br />
<br />
好吧,正經一點,<br />
我要跟各位介紹當有音樂需求時,怎麼快速製作出超IMBA的背景音樂!(謎:IMBA都拿出來用了,可見有多厲害)<br />
主角是GarageBand:一套簡單操作,卻又超強大的音樂軟體,<br />
<br />
先等等,在這之前先說明一下來龍去脈,<br />
獨立軟體開發者什麼時候會需要自己製作音樂呢?<br />
如果您是Android 或 iOS開發者,總免不了要做一些自己App的介紹影片吧!<br />
當然你可以選擇放棄這個非常有用的宣傳工具,<br />
只因為你沒辦法獨立剪輯出一個有基本水準的宣傳影片,<br />
但你現在只要有手機、相機可以錄影,再加上簡易的編輯軟體,<br />
都可以簡易的做出影片,<br />
所以你不該放棄這麼棒的宣傳工具,畢竟人們是視覺的動物,<br />
況且影片放在Youtube上還可以賺廣告費(這真是太神奇了)<br />
<br />
既然要編輯影片,並且同時賺取廣告費,<br />
你可能會遇上最大的困難點,可能就是背景音樂!<br />
一部好的宣傳影片是不可能不需要背景音樂的,<br />
因此Youtube在今年提供了<a href="http://www.youtube.com/audioswap_main">AudioSwap</a>功能,<br />
讓你可以簡易的把上傳到Youtube的影片,<br />
從資料庫當中挑選一個合適的背景音樂,<br />
從此你的影片就會有超美妙的配樂!<br />
<br />
正想稱讚Google 大無私的為影片提供者提供這麼棒的服務時,<br />
仔細看一下使用AudioSwap的條件,<br />
如果影片使用了AudioSwap置換了背景音樂,<br />
就等於宣告了,放棄使用這支影片賺錢的權力!<br />
廣告賺錢的獲益者變成是提供背景音樂的人囉~<br />
哇~那有了再好聽的背景音樂,如果不能賺錢,<br />
身為強大的獨立軟體開發者當然不能忍阿~<br />
<br />
但我們又不是天才,剛好會打爵士鼓,剛好又會彈貝斯,剛好又會電子琴,<br />
只會彈彈吉他的四大和弦就該偷笑了,<br />
於是只好請出GarageBand來,幫助我們無腦做出好音樂!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-Gdu7PmC5q768XqOF57_hcIb2Ja5UCZH1iRbPfKXry9DOK6A-pfaDUAm6P2ICCHSqKUZFgQ37zOPM7AUFmDMjokAH5ihG8mqZ3ZgTuk5XMCxL8gKfaopOT_C92OXJtLz2ttn6/s1600/%E6%9C%AA%E5%91%BD%E5%90%8D.tiff" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="220" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-Gdu7PmC5q768XqOF57_hcIb2Ja5UCZH1iRbPfKXry9DOK6A-pfaDUAm6P2ICCHSqKUZFgQ37zOPM7AUFmDMjokAH5ihG8mqZ3ZgTuk5XMCxL8gKfaopOT_C92OXJtLz2ttn6/s400/%E6%9C%AA%E5%91%BD%E5%90%8D.tiff" width="400" /></a></div>
<br />
GarageBand 內建在每台MAC電腦當中,是免費軟體(但是要先買mac Orz..)<br />
但很多mac使用者可能連碰都沒碰過,或跟不知道他這麼容易用!<br />
甚至可以使用GarageBand來教你彈吉他或彈鋼琴,<br />
我們把重點放在製作Loop背景音樂的功能上!<br />
<br />
開啟GarageBand之後建立一個新計畫案,選擇Loops的計畫案<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAifPKQGZciBe3Y6e1zhe_pOM4YDBUkdH-3_X2eWB0yr2PGQRMNKzp-itEHeL5QeqzPSTCBvOa_henySzHzyeETuSNVi5VbNlyDuLXtG3ZSY3c_yF4ngIMRFPgiE76AP0JweVk/s1600/%E6%9C%AA%E5%91%BD%E5%90%8D1.tiff" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="220" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAifPKQGZciBe3Y6e1zhe_pOM4YDBUkdH-3_X2eWB0yr2PGQRMNKzp-itEHeL5QeqzPSTCBvOa_henySzHzyeETuSNVi5VbNlyDuLXtG3ZSY3c_yF4ngIMRFPgiE76AP0JweVk/s400/%E6%9C%AA%E5%91%BD%E5%90%8D1.tiff" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
設定儲存檔名與拍子、速度和音調,這部份製作時可以修改</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghjY_WXhrQm_WnhLCaLIlbx5lqw0BGeISVhuntElHEYi-u3sAH9rko43Lzgok71PWII34TvSZ3qiyfsDoG0fF-I1RBsL6hQKE_cDuF9wjyAradbiMACZV4VdDOc3wvuMv5p04x/s1600/%E6%9C%AA%E5%91%BD%E5%90%8D+2.tiff" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="270" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghjY_WXhrQm_WnhLCaLIlbx5lqw0BGeISVhuntElHEYi-u3sAH9rko43Lzgok71PWII34TvSZ3qiyfsDoG0fF-I1RBsL6hQKE_cDuF9wjyAradbiMACZV4VdDOc3wvuMv5p04x/s400/%E6%9C%AA%E5%91%BD%E5%90%8D+2.tiff" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
操作畫面如下,右方是GarageBand所提供的Loop clip篩選器,</div>
<div class="separator" style="clear: both; text-align: left;">
藉由篩選器可以快速幫助你找到合適的音軌,也不需要擔心版權問題。</div>
<div class="separator" style="clear: both; text-align: left;">
只要將挑選喜歡的音軌拉到中間深灰色的部份即可建立移到音軌。</div>
<div class="separator" style="clear: both; text-align: left;">
最下方則是一些參數的調整。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCFU54CeAV2_Ywchn9n4j7MT91APQp0GwY1uezzPror-lviAsqtQ8vdePeL9ZcUBGBkE_XcNIzWAVBr8Xtsdw9FmAAOSUXmhcwxK132OOuEJlNzDyktLjoTrw9-HMbkpVizUCW/s1600/%E6%9C%AA%E5%91%BD%E5%90%8D3.tiff" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="248" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCFU54CeAV2_Ywchn9n4j7MT91APQp0GwY1uezzPror-lviAsqtQ8vdePeL9ZcUBGBkE_XcNIzWAVBr8Xtsdw9FmAAOSUXmhcwxK132OOuEJlNzDyktLjoTrw9-HMbkpVizUCW/s400/%E6%9C%AA%E5%91%BD%E5%90%8D3.tiff" width="400" /></a></div>
<br />
在開始前,先稍微規劃一下你的音樂配置,<br />
首先我希望我所製作的音樂節奏速度為接近hiphop的音樂類型,<br />
因此我將拍速設定為98(預設120),且使用A大調,<br />
設定方法是在下方面板選擇計畫案>拍數 使用滑鼠滾輪來調整<br />
您可以多測試適合您的音樂設定。<br />
<br />
通常音樂都會有三個主要的音軌,就是節拍、低音或和弦及主旋律,<br />
因此我也將我的專案規劃為簡單三個音軌,<br />
通常先由節奏來找起。通常節拍的樂器大部分是由鼓來呈現的,<br />
所以只要透過右方的篩選器找到適當的鼓節奏拉到中間來即可。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0jlGz6AN-BJYUw0HxELa7IUKfJeDHSRyR5APQzV7RcrN48OxXSYHhJrEGIw0R61jS8b9P6gCM8cp5X1vL55N8E5JmPILj3eXqFmtewc9kVFfEin83AB58nXzlrJPABJOFSmnf/s1600/%E6%9C%AA%E5%91%BD%E5%90%8D4.tiff" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="250" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0jlGz6AN-BJYUw0HxELa7IUKfJeDHSRyR5APQzV7RcrN48OxXSYHhJrEGIw0R61jS8b9P6gCM8cp5X1vL55N8E5JmPILj3eXqFmtewc9kVFfEin83AB58nXzlrJPABJOFSmnf/s400/%E6%9C%AA%E5%91%BD%E5%90%8D4.tiff" width="400" /></a></div>
<br />
我找到了RnB beat' 06 這個音軌,並打算全部使用這個鼓節拍來貫穿整首,<br />
我預計這段音樂需要有32個小節,這個鼓節拍長度是8小節,<br />
因此我將其複製了四次(按著alt+滑鼠右鍵拖曳即可複製)<br />
<br />
接著低音(根音)基本上會使用較低沈的樂器,如貝斯,<br />
因此我也挑選了一組bass音軌Funky Pop Bass 06 來貫穿整首,<br />
但貝斯我打算由第四小節才開始進入,之前只會有鼓聲。<br />
<br />
最後的旋律部分則需要較多的變化,不像節奏與低音可以使用一個clip貫穿整首<br />
因此挑選了幾個吉他音軌Acoustic Picking 06 等來做為主旋律,<br />
編輯方式都和鼓組相同,只要拖曳與複製就可以了。<br />
需注意的是Bass和主旋律的和弦要有一致才行 Orz...<br />
<br />
若和弦不一致聽起來會很奇怪!!如果你不了解和弦<br />
那...你還是可以只憑藉你天生的音樂細胞,<br />
自己來決定好不好聽。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRbgiRFCTaKOzq7kBhWfnR3fevzybrwKNLhkNbtvbnaU0FiLXwT4l5YM_ebwlSSmvbgCpTULAKRoAV173wKnhWb_WyKoz67Y6kBIfxIpMYm19Smcp_n1UnkZho4NtkfhmnwWvY/s1600/%E6%9C%AA%E5%91%BD%E5%90%8D5.tiff" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="247" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRbgiRFCTaKOzq7kBhWfnR3fevzybrwKNLhkNbtvbnaU0FiLXwT4l5YM_ebwlSSmvbgCpTULAKRoAV173wKnhWb_WyKoz67Y6kBIfxIpMYm19Smcp_n1UnkZho4NtkfhmnwWvY/s400/%E6%9C%AA%E5%91%BD%E5%90%8D5.tiff" width="400" /></a></div>
<br />
完成後只要由共享>輸出到磁碟就可以把你的作品存為mp3囉!<br />
如果你夠熟悉這個軟體,那前後可能不需要二十分鐘,<br />
就可以完成一首夠水準的背景音樂囉~<br />
<br />
獻上我的作品如下,弄的還不錯吧哈哈(得意中)<br />
<br />
<a href="https://dl.dropbox.com/u/20807202/loop1.mp3">作品成果</a><br />
<br />
<br />
<br />
如此一來,我們自己的影片就可以搭配上自己做的音樂,<br />
不需要再去找可能侵犯到版權的音樂片段囉!酷吧~Anonymoushttp://www.blogger.com/profile/10433873918988135141noreply@blogger.com2tag:blogger.com,1999:blog-9873545.post-79662373910287874592012-09-20T20:30:00.001+08:002012-09-20T20:30:49.283+08:00Google Checkout 開始提供台灣開發者電匯服務<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6YHHcYNeU5N-jNHYbL7t59jjKiTLHnLrlZsCS-XlE0wRtxiGLqwt41Y8G5ijeBa_gx3yx0EE9KdtMfilpabBA32zt76GahC1rMt7F-w6nsS_FG1tvbNPHWJQi2xV3NEJwTZ3V/s1600/%E6%93%B7%E5%8F%96.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="288" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6YHHcYNeU5N-jNHYbL7t59jjKiTLHnLrlZsCS-XlE0wRtxiGLqwt41Y8G5ijeBa_gx3yx0EE9KdtMfilpabBA32zt76GahC1rMt7F-w6nsS_FG1tvbNPHWJQi2xV3NEJwTZ3V/s400/%E6%93%B7%E5%8F%96.PNG" width="400" /></a></div>
<br />
一直以來台灣開發者在開發付費程式時,都需要多申請一個Adsense帳號來領取款項,這個情況就快要改變了! 今天(2012/09/20)收到了來自Google Checkout的通知,巴西、俄羅斯、阿根廷、台灣在下個月完成最後一次透過Google Adsense帳號來取款後,會改為帳號電匯的方式,不需要將Google Checkout和Adsense綁在一起了。<br />
<br />
透過Adsense來取得款項有甚麼不好呢? 首先須了解Adsense原本的作用。Google Adsense提供給網頁、部落格的經營者一個可以放置圖文廣告來賺取金錢的途徑,網頁經營者經過Google 審核之後,即可以在網頁中放置廣告,當使用者點擊後就可以獲得一些金額,這些金額是透過廣告主競標的方式來決定的,除了點擊計價之外,每千次廣告瀏覽,也會提供給網頁經營者一些利潤。這樣看起來也沒甚麼不好,但問題就在於寫Android app 的開發者,不一定會經營部落格。<br />
<br />
Android app的付費購買獲利通通需要透過Google Checkout來收費,過去沒有直接電匯服務的時候,在台灣的開發者還需要Adsense帳號來收取這筆款項,所以...這是逼Android的開發者一定要去搞網頁寫自己的部落格,否則你申請不到Adsense帳號,就收不到錢! 並且在後面幾年,Adsense帳號資格越來越嚴格,不是說隨便寫幾篇文章的部落格,就可以申請過。申請Adsense的網頁必須要內容豐富,並且要成立一段時間才行。這樣不合理的設定,讓許多有心成為Android開發者的人,設下了一道牆。請先成為部落客,不然Android上賺的錢你就拿不到~<br />
<br />
即使申請到了Adsense帳號,你還要成天擔心這個Adsense 帳號會因為久疏於經營或是有心的使用者違規亂點(單一使用者點擊多次)你的廣告,而遭到停權! 所以申請到Adsense帳號,我可以不用不放置廣告嗎? 也不行! 因為申請Adsense的條款與政策就提到不使用Adsense可能導致停權的後果。<br />
<br />
所幸,Google已經聽到了許多來自台灣等地區的開發者心聲了,終於開始開放直接電匯的方式,直接將Android的所得匯到開發者所指定的帳戶! Android上的收益再也不需要透過Adsense來領取了。<br />
<br />
於是在這個大App時代,只要有心人人都可以成為開發者!! 一起來成為Android開發者吧~Anonymoushttp://www.blogger.com/profile/10433873918988135141noreply@blogger.com3tag:blogger.com,1999:blog-9873545.post-81981493742507709012012-09-13T04:34:00.000+08:002012-09-13T15:16:36.625+08:00Android 開發過程中的 "Dirty hack"最近一直在讀一些Open source的程式碼,<br />
為了實現我在未來所要完成的一些工作和想法,<br />
有時候很佩服這些願意把程式碼分享給其他人的程式設計師,<br />
至少在目前我還很小氣的不想把程式碼分享給其他人Orz,<br />
<br />
應該很多人和我一樣,覺得讀別人的程式碼很痛苦,<br />
但是讀這些程式碼真的會讓寫程式的功力和邏輯想法變得不一樣,<br />
況且這些願意分享的Open source專案的作者,<br />
也都有一定的實力與經驗,才有勇氣把自己的程式碼放出來,<br />
很難想像如果我把自己的程式碼攤在大家面前時那是什麼感覺,<br />
可能一堆人"幹譙"說寫這麼爛也敢拿出來,<br />
或者根本就沒人對我的程式碼有興趣XD<br />
<br />
我在這份開放原始碼的專案中,<br />
其中一行註解看到了Android開發者的無奈XD<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgB7_754OWtHukUZ0okbUjmclolpSEOYvHmTzHlJiApboKvfjCQIT__SBCwNn7mR-TdRS62gEuFa5hIKpNwvnXJ2bsjK9NqE6Ug44w3f_Zhx4EuH1wdESiFDaJKbnUSqFdcnMSO/s1600/%E6%9C%AA%E5%91%BD%E5%90%8D.tiff" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="113" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgB7_754OWtHukUZ0okbUjmclolpSEOYvHmTzHlJiApboKvfjCQIT__SBCwNn7mR-TdRS62gEuFa5hIKpNwvnXJ2bsjK9NqE6Ug44w3f_Zhx4EuH1wdESiFDaJKbnUSqFdcnMSO/s400/%E6%9C%AA%E5%91%BD%E5%90%8D.tiff" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
作者為了HTC Flyer做了一些客製化的程式碼,</div>
<div class="separator" style="clear: both; text-align: left;">
然後在程式碼上方註解 "//dirty hack for the HTC Flyer"</div>
<div class="separator" style="clear: both; text-align: left;">
看起來是HTC Flyer在觸控事件發生時所傳回的MotionEvent上,</div>
<div class="separator" style="clear: both; text-align: left;">
沒有提供足夠的觸控資訊,通常裝置可以粗略判斷觸控的物質是手指、觸控筆或其他,</div>
<div class="separator" style="clear: both; text-align: left;">
並將此資訊提供給程式進行接下來的邏輯運算,</div>
<div class="separator" style="clear: both; text-align: left;">
顯然HTC Flyer的感觸Sensor沒有把這個資料正確的回傳,</div>
<div class="separator" style="clear: both; text-align: left;">
最後只能作者自己想辦法~</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
其實我一開始並不知道Dirty hack實際的意義是什麼,</div>
<div class="separator" style="clear: both; text-align: left;">
於是上網Google一下在這個簡體網站舉了例子,</div>
<div class="separator" style="clear: both; text-align: left;">
做了精闢的字義說明!</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<a href="http://zhihurss.tuita.com/blogpost/23556272">http://zhihurss.tuita.com/blogpost/23556272</a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFKpQqcCgYxawk4E_F_2RoPty64LCst4oULnHKrMZupLZkI-c_uvl9Yu66Jcrbf2MA8mNxa5tiO0RrkUzBqyoNlm_VFcnzFh9X5-4jsk1iid8VXVrwh6oBwuPbSHb0h3dYgxoO/s1600/%E6%9C%AA%E5%91%BD%E5%90%8D1.tiff" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFKpQqcCgYxawk4E_F_2RoPty64LCst4oULnHKrMZupLZkI-c_uvl9Yu66Jcrbf2MA8mNxa5tiO0RrkUzBqyoNlm_VFcnzFh9X5-4jsk1iid8VXVrwh6oBwuPbSHb0h3dYgxoO/s400/%E6%9C%AA%E5%91%BD%E5%90%8D1.tiff" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
想必看完之後會發現,<br />
原來許多在Android開發過程所寫的程式碼就是在做Dirty hack,<br />
因為Android裝置廠商眾多,<br />
實在沒辦法確認所寫的Code真的能在所有裝置上面順利運行,<br />
有時候真的要等到有使用者在評分版上抱怨的時候,<br />
開發者才會知道,原來這款手機會有問題,<br />
但即使知道了有問題,如果開發者手邊沒有這款手機,<br />
那開發者有80%的機率還是沒辦法知道發生問題的原因,<br />
因為別款手機都沒問題阿ˊ__ˋ<br />
<br />
如果手邊有發生問題的手機,開發者就可以為這些手機量身訂做解決方案,<br />
也就是上面說到的"Dirty hack" ~ ~a<br />
<br />
在寫Navier HUD時就有發生部分手機在利用Android API取得GPS座標時,<br />
竟不會同時回傳速度,<br />
遇到這種時候只好自己利用兩點距離和時間自己算速度才有辦法解決了,<br />
下次我一定會記得在這些Code上面註解這些是"Dirty hack" XDD<br />
<br />
所以各位App愛用者,<br />
要購買App前一定要先確認是否在您的手機上會有問題,<br />
當遇到App某些功能在您的手機上運作不正常時,<br />
如果那個App是免費的,請記得評分時手下留情Orz<br />
並記得寫信告知作者您的手機型號和問題!<br />
請體諒Android App的作者沒辦法購買所有的Android裝置來測試呀~<br />
<br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/10433873918988135141noreply@blogger.com13tag:blogger.com,1999:blog-9873545.post-60225547596977672632012-08-31T12:11:00.001+08:002012-08-31T12:11:43.211+08:00Android Asset Studio 網頁介紹 (二)<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBfbmdTyCdo15QGfSCxyJzdVvM7X38d7w9_aLuAhxOF-hD1VzA17GEgCZPyQxrHS8zeGqKOsstbYCwaFvy48S9EhdSjkE6r94dD9sh3bKOeElV1re_5G2gWLoQGS6BWCCwh9RK/s1600/unnamed.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="223" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBfbmdTyCdo15QGfSCxyJzdVvM7X38d7w9_aLuAhxOF-hD1VzA17GEgCZPyQxrHS8zeGqKOsstbYCwaFvy48S9EhdSjkE6r94dD9sh3bKOeElV1re_5G2gWLoQGS6BWCCwh9RK/s400/unnamed.jpg" width="400" /></a></div>
<br />
續前篇Android Asset Studio網站製作ICON的介紹,該網站也可以協助我們製作擬手機畫面的螢幕截圖邊框。<br />
<br />
當我們完成一個App之後,第一個吸引使用者去下載App的方式便是提供程式操作畫面,一般來說,我們只要在Android手機上同時按下電源鍵+音量減低鍵就可以將目前手機上的畫面取下,但此時我們所剪下的畫面為單純的螢幕截圖,如果能拍下包含手機的畫面,則使用者會更有真正操作手機時的想像空間。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfrLjL7ZHNMGy0s5QEm64k_ZItLLUDeW18_5QtB17d-YeP4OdOjfEpzZho_VYsmk9XzjfhlH7nHIY9JcDCc1-lKw4hz5zeWm9tpXLCw6pIhhRIsbHNOI2CaxzfsHjLb0o9PaYR/s1600/%E6%9C%AA%E5%91%BD%E5%90%8D+2.tiff" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="177" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfrLjL7ZHNMGy0s5QEm64k_ZItLLUDeW18_5QtB17d-YeP4OdOjfEpzZho_VYsmk9XzjfhlH7nHIY9JcDCc1-lKw4hz5zeWm9tpXLCw6pIhhRIsbHNOI2CaxzfsHjLb0o9PaYR/s400/%E6%9C%AA%E5%91%BD%E5%90%8D+2.tiff" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
這時,我們可以利用相機來進行手機畫面拍攝,但拍攝玩的畫面可能會有去背或修整後製的需求,導致耗時費力。這時,我們可以利用手機的截圖畫面加上Android Asset Studio上面的Device Frame Generator工具來產生美麗的操作畫面,也不需要自己處理影像。<br />
<br />
第一步驟,執行App並將畫面切換到要擷取的畫面中,手機同時按下電源鍵+音量減低鍵,取得螢幕截圖,將手機連接電腦將螢幕截圖取出至電腦中。<br />
<br />
第二步驟,將截圖照片檔案拖曳到網頁中所支援的手機圖示上,就可以立刻將螢幕截圖嵌入手機的邊框當中,迅速做出漂亮的手機App運行畫面,並且可以調整陰影和螢幕光影反射。<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNoSazcLNy-vwBlJN-FHSNdqGi0LHa7ESY8cf4c8Zn5nabPlhdpJCkPRQuj-GbTW_eaxNsTT28Sf3Fj6TBENPvzxuYPQLn7IXwBHymtbmJeTcWti9jeHP9dBeaO0t0oEL3L5mm/s1600/%E6%9C%AA%E5%91%BD%E5%90%8D3.tiff" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="370" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNoSazcLNy-vwBlJN-FHSNdqGi0LHa7ESY8cf4c8Zn5nabPlhdpJCkPRQuj-GbTW_eaxNsTT28Sf3Fj6TBENPvzxuYPQLn7IXwBHymtbmJeTcWti9jeHP9dBeaO0t0oEL3L5mm/s400/%E6%9C%AA%E5%91%BD%E5%90%8D3.tiff" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
只要簡單的兩個步驟,就可以做出比之前自己使用photoshop所合成的運行畫面品質還好的圖片,只是要注意的是所提供的螢幕截圖必須符合該手機的解析度,譬如筆者以Galaxy Nexus來截圖,則原始的圖檔可以直接拖曳到Galaxy Nexus圖示上,卻不能拖曳到其他解析度不同的裝置當中。目前該工具所支援的裝置有八台目前較暢銷的機種。善用此工具可以幫開發者節省不少時間呢!</div>
<br />Anonymoushttp://www.blogger.com/profile/10433873918988135141noreply@blogger.com4tag:blogger.com,1999:blog-9873545.post-79098005399457112092012-08-31T11:29:00.000+08:002012-08-31T11:29:37.284+08:00Android Asset Studio 網頁介紹<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPx8OD7WaoBodMdcA2oj0T2Juux9zq4xg_cduUvafHBNw29XgN9cbLwyYWO33Azj08vv3mIxEWN3hoNF4-iMVFBeeK7pcAnhqYwmwnFuh2qnCcoIOWdsw4Ws1AKpdeZw9TuEcb/s1600/iconography_actionbar_style.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPx8OD7WaoBodMdcA2oj0T2Juux9zq4xg_cduUvafHBNw29XgN9cbLwyYWO33Azj08vv3mIxEWN3hoNF4-iMVFBeeK7pcAnhqYwmwnFuh2qnCcoIOWdsw4Ws1AKpdeZw9TuEcb/s400/iconography_actionbar_style.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
個人軟體開發者,常會遇到的問題之一,常常是需要花許多時間來設計與處理App 使用者介面所需要的圖式,這些圖示包含軟體執行的icon、按鈕icon、提示icon、menu和tab上的icon、以及各式背景等。如果你說撰寫的app還需要支援各種不同的螢幕解析度,那這些事情又更複雜了。由沒有什麼工具是可以協助使用者同時簡化這些圖示設計工作,也可以產生簡潔又美觀的介面呢?<br />
<br />
android-ui-utils 計畫,就在協助開發者們,關於介面圖示與背景的建立與產生。<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0PHbMpZRpqBjm3sVOJQAtK19ApwJLiJrr0wS0cUR5UhBbylcPatN4GlnRNGAOfAvk0KC8pQVzW4tBfNc_m_vghaaFfJDzKB3zmRI7t4Ph2rMGeD-DXpD09ug4yhqxTpePAc7O/s1600/%E4%B8%8B%E8%BC%89.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0PHbMpZRpqBjm3sVOJQAtK19ApwJLiJrr0wS0cUR5UhBbylcPatN4GlnRNGAOfAvk0KC8pQVzW4tBfNc_m_vghaaFfJDzKB3zmRI7t4Ph2rMGeD-DXpD09ug4yhqxTpePAc7O/s400/%E4%B8%8B%E8%BC%89.png" width="261" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div>
<br /></div>
<div>
<a href="http://android-ui-utils.googlecode.com/hg/asset-studio/dist/index.html">Android Asset Studio 網頁連結</a><br />
<br />
Android Asset Studio 網頁提供了ICON Generator工具,Other Generator工具及Community Tool三個項目。ICON Generator可以協助開發者建立大大小小的圖示,並且這些工具的操作也大同小異,讓你可以在幾個選項之間就產生了各式大小的圖示,如果你有使用Eclipse來開發Android手機程式,你會發現Launch ICON Generator被整合到Android 開發工具當中了,利用這個工具你就可以快速產生一個Launch ICON。<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhoAOf6vOhQfv7rdIvbK1Z_hnysS6CulpUcvYy9yM-oubzmSvG5h64YJALvwKWtxCCCptZYxs4HUsIoC4SWSZPiz2i0Qx_c5B5VpMhXO_ivsDYAYPvnHobCrxqpUyxKI4nb7UO/s1600/%E6%9C%AA%E5%91%BD%E5%90%8D1.tiff" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="372" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhoAOf6vOhQfv7rdIvbK1Z_hnysS6CulpUcvYy9yM-oubzmSvG5h64YJALvwKWtxCCCptZYxs4HUsIoC4SWSZPiz2i0Qx_c5B5VpMhXO_ivsDYAYPvnHobCrxqpUyxKI4nb7UO/s400/%E6%9C%AA%E5%91%BD%E5%90%8D1.tiff" width="400" /></a></div>
ICON Generator 當中除了Launch ICON Generator還有Action bar and tab icon、notification icon等等,你可能會覺得我的App要有獨特的ICON才能顯示出與眾不同的特色,但有時候如果一些常用的圖示能夠讓使用者一看到,就了解功能,例如下列幾個圖示<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPx8OD7WaoBodMdcA2oj0T2Juux9zq4xg_cduUvafHBNw29XgN9cbLwyYWO33Azj08vv3mIxEWN3hoNF4-iMVFBeeK7pcAnhqYwmwnFuh2qnCcoIOWdsw4Ws1AKpdeZw9TuEcb/s1600/iconography_actionbar_style.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPx8OD7WaoBodMdcA2oj0T2Juux9zq4xg_cduUvafHBNw29XgN9cbLwyYWO33Azj08vv3mIxEWN3hoNF4-iMVFBeeK7pcAnhqYwmwnFuh2qnCcoIOWdsw4Ws1AKpdeZw9TuEcb/s320/iconography_actionbar_style.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
我們何苦去挖空心思,設計這些習已成俗的線條與圖示呢?我們要做的只是將這些ICON轉換成合乎App色調與背景的圖示就行了。使用者也不需要再猜想這些按鈕是什麼功能,由既有的軟體使用經驗就可理解這些功能了。<br />
<br />
至於Android Asset Studio該如何使用呢,以Launch ICON 產生器為例<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUfAFRske03SePBUV-39K1puydvBSGC2tTB0zjgny0zJqgBLQ8xn_2mPaGQhmjYulklqBWoF0q9DB5h6MObBmPgHYE2tT7RKdD4anmrl5R7ijVFcYxX-tN5c1oGklgdGNAVJPn/s1600/%E6%9C%AA%E5%91%BD%E5%90%8D2.tiff" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUfAFRske03SePBUV-39K1puydvBSGC2tTB0zjgny0zJqgBLQ8xn_2mPaGQhmjYulklqBWoF0q9DB5h6MObBmPgHYE2tT7RKdD4anmrl5R7ijVFcYxX-tN5c1oGklgdGNAVJPn/s400/%E6%9C%AA%E5%91%BD%E5%90%8D2.tiff" width="302" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
第一步驟是選擇圖示的來源,可以重上傳既有image檔案,或是點選CLIPART選擇一個既有的圖示,另外也可以由TEXT以輸入的文字來當做圖示<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhiYi7FLUD5bKlPzrRBqMGH2vNXSJN4pXDTGPQMZwVcV93f2ESFkv2WsGnC1M4NitB8y5RQuY0j9WopdNIq2otRrZdy_4mPLvkGnmDMhKi9psI1tVZiiD9bcy-qHEbT60nI0BD/s1600/%E6%9C%AA%E5%91%BD%E5%90%8D.tiff" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhiYi7FLUD5bKlPzrRBqMGH2vNXSJN4pXDTGPQMZwVcV93f2ESFkv2WsGnC1M4NitB8y5RQuY0j9WopdNIq2otRrZdy_4mPLvkGnmDMhKi9psI1tVZiiD9bcy-qHEbT60nI0BD/s400/%E6%9C%AA%E5%91%BD%E5%90%8D.tiff" width="356" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
製作過程中,可以調整的選項包含前景與背景顏色、前景圖示的透明度、邊框空間、背景形狀等等。調整後,網頁會自動產生適合不同大小的圖示,可以選擇直接儲存zip檔,或直接產生合適的網頁格式。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
其他icon的產生方式也同 Launch ICON 的產生方式類似,只要以滑鼠選擇適當設定之後,就能產生符合各種解析度的圖示了。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<br /></div>
Anonymoushttp://www.blogger.com/profile/10433873918988135141noreply@blogger.com0tag:blogger.com,1999:blog-9873545.post-41883625894642926872012-07-23T11:56:00.001+08:002013-10-13T21:13:54.507+08:00Eclipse Color Themes plug-in<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLeDcH79zBKTlusoTQdXnCtTl2AdUOhZWc7S3t4YAfDIQbWpINnY0R7IeYFX365yFHS4Ez2bMm7tmAtneh95BCAMI1RksMbsic-KVP8FPZTroOlrBz3au9PBPbFA4S929nwdd9/s1600/%E6%9C%AA%E5%91%BD%E5%90%8D.tiff" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="333" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLeDcH79zBKTlusoTQdXnCtTl2AdUOhZWc7S3t4YAfDIQbWpINnY0R7IeYFX365yFHS4Ez2bMm7tmAtneh95BCAMI1RksMbsic-KVP8FPZTroOlrBz3au9PBPbFA4S929nwdd9/s400/%E6%9C%AA%E5%91%BD%E5%90%8D.tiff" width="400" /></a></div><br />
<br />
你也和我一樣一天到晚和 Eclipse IDE 為伍,<br />
<br />
每天在程式碼的海中游泳嗎?<br />
<br />
從開始成為Android app開發者開始,<br />
<br />
我幾乎每天都要打開 Eclipse 來寫程式,<br />
<br />
有一天我突然想到,我每天都要這樣長時間盯著白色光亮背景的編輯畫面,<br />
<br />
其實對眼睛是非常傷的事情,<br />
<br />
如果Eclipse背景可以改成其他深顏色就更好了。<br />
<br />
因此我就在Eclipse偏好設定裡找相關的顏色設定,<br />
<br />
希望把背景色調成黑色,<br />
<br />
您可以在Eclispe>偏好設定>General>Appearance <br />
<br />
當中進行背景、文字顏色的設定。<br />
<br />
<br />
於是當我將背景顏色改成黑色後,發現字也是黑色,<br />
<br />
因此Code全部都看不到了Orz,<br />
<br />
所以後改了Code的顏色,又發現註解的顏色不適當,<br />
<br />
如果你很有耐心,決心要改一個適合自己的顏色配置,<br />
<br />
我保證,你這樣要設好,至少得花一整天的時間!<br />
<br />
真的是「痛苦太多,而收穫太少」阿!<br />
<br />
<br />
所以我要介紹你一個Eclipse好用的外掛,<br />
<br />
可以用來拯救你的靈魂之窗的外掛!<br />
<br />
當當當當 ~~就是「Eclipse Color Themes」!!<br />
<br />
<br />
你可以在官方網站看到很多已經完成的顏色配置!<br />
<br />
網址<a href="http://eclipsecolorthemes.org/">http://eclipsecolorthemes.org/</a><br />
<br />
你要做的就是在你的Eclipse當中安裝這個外掛,<br />
<br />
然後再網站裡挑一個你看起來最順眼的配置就行了!<br />
<br />
Step 1 :<br />
<br />
在Eclipse>Help>Eclipse MarketPlace搜尋「Eclipse Color Themes」<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJg1Iircj7TFAqvzHyMfSf0QN1i3UQuUyCtU1QRXBJS0kH8xJSGd7VQ83n7mEf3Xb6C8kZFI_AmOnyPDw-MUFLuBdAAaZwAywjMGdfGvlAmAqWRUUFUdltUVOpygG9-m7xEZjz/s1600/1.tiff" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJg1Iircj7TFAqvzHyMfSf0QN1i3UQuUyCtU1QRXBJS0kH8xJSGd7VQ83n7mEf3Xb6C8kZFI_AmOnyPDw-MUFLuBdAAaZwAywjMGdfGvlAmAqWRUUFUdltUVOpygG9-m7xEZjz/s400/1.tiff" width="277" /></a></div><div class="separator" style="clear: both; text-align: left;">按下Install安裝它!</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">Step 2:</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">在網站裡選一個你喜歡的顏色配置,</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">點進去並下載該配置的Eclispe Preference檔案,</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">接著到 Eclipse>Files>Import>Preference </div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">選擇下載的epf檔,之後就大功告成了</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">外掛其實已經有附一些配置可供選擇</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">只要到 Eclipse>偏好設定>General>Apprearance>Color Theme 當中選擇就行了</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">如此一來就不用花時間在顏色配置上,</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">又能依照心情變化顏色的配置囉!</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">改完顏色之後,是不是眼睛感覺到爽快多了呢?</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">我的工作環境改完後就變下面這樣啦! 真是太棒了呢!</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhd0qHG4coEhI-qnj1Scu3Qy028ggX-zsp1AaWB6tF5qGqZkwABVY0C422WmU6eqVN6bdrs5FaWxTzhLoQrj_K62wbLZ5Zrdi1v23Vc8zuaP2yXy0wdCP_K4SZ3wkkAl0XXMNqJ/s1600/2.tiff" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="361" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhd0qHG4coEhI-qnj1Scu3Qy028ggX-zsp1AaWB6tF5qGqZkwABVY0C422WmU6eqVN6bdrs5FaWxTzhLoQrj_K62wbLZ5Zrdi1v23Vc8zuaP2yXy0wdCP_K4SZ3wkkAl0XXMNqJ/s400/2.tiff" width="400" /></a></div><div class="separator" style="clear: both; text-align: left;"><br />
</div><br />
<br />
Anonymoushttp://www.blogger.com/profile/10433873918988135141noreply@blogger.com0tag:blogger.com,1999:blog-9873545.post-86066248206666589472012-07-17T13:26:00.004+08:002012-07-17T13:32:28.251+08:00上路測試Navier HUD新元件<iframe allowfullscreen="" frameborder="0" height="315" src="http://www.youtube.com/embed/OvtHtOu79ho" width="420"></iframe><br />
<br />
上路測試一些Navier HUD中的新元件<br />
<br />
版面配置為右邊是「路線指示」和「導航進度」<br />
<br />
版面配置左邊包含「數位速度表」、「平均速度」、「加速度動態圖」、「gps狀態圖」和<br />
<br />
「大速度動態圖」^__^<br />
<br />
測試影片提供給各位參考!<br />
<br />
背景音樂為Secrets In Stereo : AgainAnonymoushttp://www.blogger.com/profile/10433873918988135141noreply@blogger.com5tag:blogger.com,1999:blog-9873545.post-46045074753393218252012-07-12T14:35:00.001+08:002012-07-12T14:38:23.667+08:00ViewFlipper Bug因為有部分手機車架設計的關係,<br />
<br />
有些車架電源接口朝左,有些朝右,<br />
<br />
又因為Navier HUD是強制將畫面設定為Landscape<br />
(android:screenOrientation ="landscape")<br />
<br />
這時如果車架電源接口是朝左的話,<br />
<br />
Navier HUD畫面會變成上下相反,<br />
<br />
解決這個問題的方法,本來很單純,<br />
<br />
<br />
<br />
就是把畫面設定改成 android:screenOrientation ="sensorLandscape" 就行了<br />
<br />
問題是,sensorLandscape參數只支援Android2.3以上的版本,<br />
<br />
<span style="background-color: white;">2.3以下的版本會變成沒有將畫面鎖為橫向!</span><br />
<br />
<br />所以...我該為了這個參數放棄使用Android2.3以前版本的使用者嗎?<br /><br />不,我一個使用者都不想放棄!<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgk9GffulPdHIEiKBlAfPyQBPVC_LDHE_NPD5iqEozizT6rCPb5Vd2QxTgCi9aIL3CcRV3bRHdaAVQ0Mq2bd2lvIg4Qm0XPDVXtIlSEJG5YzjHb7BaRu4QNJH6qJC92r4EN18Fp/s1600/%E6%9C%AA%E5%91%BD%E5%90%8D.tiff" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="395" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgk9GffulPdHIEiKBlAfPyQBPVC_LDHE_NPD5iqEozizT6rCPb5Vd2QxTgCi9aIL3CcRV3bRHdaAVQ0Mq2bd2lvIg4Qm0XPDVXtIlSEJG5YzjHb7BaRu4QNJH6qJC92r4EN18Fp/s400/%E6%9C%AA%E5%91%BD%E5%90%8D.tiff" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
觀察Navier HUD的使用者版本分布,</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
仍有接近八分之一的使用者是Android2.3以前的版本</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
所以只好另外想辦法!</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
既然沒辦法在Manifest檔中使用參數,</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
那就直接在Activity的onResume()時,檢查手機的手持方向,</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
然後hardcode轉換顯示方向</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;"><span class="Apple-tab-span"> </span><span class="s1">public</span> <span class="s1">static</span> <span class="s1">void</span> checkLanscapeOrientation(Activity context){</span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;"><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span> Display display = ((<span class="s2">WindowManager</span>) context.getSystemService(context.<span class="s3">WINDOW_SERVICE</span>)).getDefaultDisplay();</span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s1">int</span> orientation = display.getRotation();</span></div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;"><br /></span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s1">try</span>{</span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s1">if</span>(orientation==Surface.<span class="s4">ROTATION_270</span>)</span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>{</span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>context.setRequestedOrientation(ActivityInfo.<span class="s4">SCREEN_ORIENTATION_REVERSE_LANDSCAPE</span>);</span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>}<span class="s1">else</span>{</span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>context.setRequestedOrientation(ActivityInfo.<span class="s4">SCREEN_ORIENTATION_LANDSCAPE</span>);</span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>}</span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>}<span class="s1">catch</span>(Exception e){</span></div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>}</span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;"><span class="Apple-tab-span"> </span>}</span></div>
<br />
<br />
將上述方法放置於onResume()當中,來改編顯示方向<br />
<br />
本以為應該沒有問題了!<br />
<br />
無奈又碰上ViewFlipper 元件的Bug<br />
<br />
當Activity當中有使用ViewFlipper時,做Orientation改變時,<br />
<br />
可能會使App FC!<br />
<br />
這個錯誤由Android2.1~ Android 4.0都還有,<br />
<br />
Android 4.1似乎解決了,因為我手機刷了Android 4.1並且沒碰到這個問題,<br />
<br />
所以我一直沒發現有問題,直到許多人在評論上提到,<br />
<br />
我才知道ˊˋ<br />
<br />
<br />
目前只好再把Orientation設回landscape,<br />
<br />
對那些車架電源接口是朝左的使用者說聲抱歉@@<br /><br />目前還無法解決此問題!<br />
<br />Anonymoushttp://www.blogger.com/profile/10433873918988135141noreply@blogger.com3tag:blogger.com,1999:blog-9873545.post-41348790670609764482012-06-25T12:27:00.000+08:002012-06-25T12:29:35.104+08:00MapView in multiple activities在開發Android App時,可以非常簡便的來開發與使用地圖,<br /><br />只要import com.google.android.maps 當中的相關元件就可以了開心使用,<br /><br />但因為MapView是很耗記憶體的元件,<br /><br />因此Google在設計MapView時,將MapView設計成<br /><br />所有使用到MapView的Activity會參考到同一個MapView資源,<br /><br />使用同一塊快取記憶體,以避免大量的記憶體使用造成的Memory leak。<br /><br />所以在你所開發的程式中,所使用多個MapView其實都參照到同一個<br /><br />不同只在於你在MapView上所加的Overlay不同、控制器不同、zoom等參數不同而已。<br /><br />原本立意良善的設計,有時卻會帶來意外的困擾,<br /><br />在Navier HUD當中使用到MapView的Activity目前有兩個,<br /><br />一個是使用者可以在地圖上點選建立目的地的地圖,<br /><br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTz54HYhYS6IdtIdbUCzq3u0zIN64JxqAbL5RSh7f0tFlzNHiSTTMAr61AiKMvbOywkooFmsQU_MUbnMpgqRudN31U7yxO9pfMaH6O-A2fd2FhSzF0d6SeUOw6ozeuYOeDAo-f/s1600/device-2012-06-18-204537.png"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTz54HYhYS6IdtIdbUCzq3u0zIN64JxqAbL5RSh7f0tFlzNHiSTTMAr61AiKMvbOywkooFmsQU_MUbnMpgqRudN31U7yxO9pfMaH6O-A2fd2FhSzF0d6SeUOw6ozeuYOeDAo-f/s400/device-2012-06-18-204537.png" /></a><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />另一個是顯示搜尋結果的地圖,<br /><br /><br /><br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgN0DpjGWbELDxr8bDqlbC0YRi10ehyB3nM8NNhwYtLokVMTzkQ6Jcodb1ith8Vop3I5FPwzV9PIKMoYl-x25hucD23iCPnU0BQF_x1Tz_RRKivqF1uY_OJtWhpxX_qvBAY-g1A/s1600/device-2012-06-18-211416.png"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgN0DpjGWbELDxr8bDqlbC0YRi10ehyB3nM8NNhwYtLokVMTzkQ6Jcodb1ith8Vop3I5FPwzV9PIKMoYl-x25hucD23iCPnU0BQF_x1Tz_RRKivqF1uY_OJtWhpxX_qvBAY-g1A/s400/device-2012-06-18-211416.png" /></a><br /><br /><br />在舊的版本中(v1.3.1及之前)當您搜尋一個地點進入搜尋結果後,<br /><br />在以back鍵回到目的地地圖時,<br /><br />這時拖拉地圖,會發現地圖下方有一點不正常的顯示情況(地圖閃爍且看到背景)<br /><br />原本應該是填滿地圖的畫面,在拖拉時變得顯示不正常了。<br /><br />經過一天一夜爬文,可以確定造成此錯誤的原因就是,<br /><br />雖然在兩個Activity當中引用兩個MapView,<br /><br />但是因為兩個Activity當中的排版有些許差異,<br /><br />因此在回到第一個畫面時還帶著第二個畫面的MapView排版屬性。<br /><br />這裡複習一下Activity的生命週期,當由第一個Activity進入第二個Acitivity時,<br /><br />第一個Activity會呼叫OnPause(),並將Activity放置在Activity Stack當中,<br /><br />直到由第二個Activity返回時,<br /><br />由Stack中取回狀態並呼叫OnResume()回到第一個Activity。<br /><br />而通常我們會把設定畫面layout的程式碼setContentView()擺在onCreate()當中,<br /><br />所以在OnResume()時並不會重新讀取MapView的Layout,<br /><br />因為共用MapView的關係,回到畫面1時還帶著畫面2的Layout參數,<br /><br />而造成畫面看起來不正常。直到使用者用兩指縮放地圖後才會正常。<br /><br />解決這個問題最快的方式可以將兩個Activity的MapView長寬都設成match_parent,<br /><br />但這樣設在Navier HUD會造成畫面2的FlipView處理OnFling()異常,<br /><br />可能要修改排版方式才能解決Orz,<br /><br />但最後終於自己試出一個最快最方便的解決方式,<br /><br />連排版都不用變更,<br /><br />就是在畫面1的OnResume()時,將MapView的visibility設為GONE,<br /><br />然後再設回VISIBLE,地圖就會重新處理Layout,<br /><br />結果就正常顯示了。<br /><br /><br /><span style="font-family: 'Courier New', Courier, monospace;">mapView.setVisibility(View.GONE);<br /> mapView.setVisibility(View.VISIBLE);</span><br /><br /><br />此錯誤會在下次更新時修正(v1.3.2)<br /><br />Anonymoushttp://www.blogger.com/profile/10433873918988135141noreply@blogger.com0tag:blogger.com,1999:blog-9873545.post-1840382978951377492012-06-18T21:37:00.002+08:002012-06-18T21:40:02.000+08:00Navier HUD 的地點管理介紹<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjraE9oGDpH6lPk_8IXULbFZC0xb1ojFwdB4mVFMXlVV6hh92GA8gJF4RYYH3edC1ogcTeC5S8zmuGYpw4dfL7EuQJUQa7n8OyVgsH7IJKADVA8oB82xOZKwBFSeP1I7U4OLzK/s1600/device-2012-06-18-204537.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjraE9oGDpH6lPk_8IXULbFZC0xb1ojFwdB4mVFMXlVV6hh92GA8gJF4RYYH3edC1ogcTeC5S8zmuGYpw4dfL7EuQJUQa7n8OyVgsH7IJKADVA8oB82xOZKwBFSeP1I7U4OLzK/s400/device-2012-06-18-204537.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
在Navier HUD 中選擇一個<a href="http://asnippets.blogspot.tw/2012/05/navier-hud_16.html">導航面板</a>之後,</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
畫面會來到目的地選擇地圖,</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
這個畫面當中包含了Google 地圖、左下方四個按鈕、</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
右下方一個地點文字搜尋以及地點語音搜尋按鈕。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
使用者可以直接在地圖上利用兩指縮放與拉動來找到您的目的地,</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
只要點一下地圖,就會在這個地點插上旗子,作為目的地。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
藍色小圓點則是使用者的目前位置。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
當插上旗子後,上方會出現關於這個地點的大約地址</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
這個地址可能會有錯誤,不過只要您確認位置是正確的就不需要在意。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<h3>
</h3>
<h3>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrlsXJZxbqpHrb2u1rs3W3yW1C1QIs5d36_nkr5DTa5idYnM57g2MBpXjxVcubcXLhk9txED8rofM2_XXIbjFjo0BZj-QnzfWlG1nk1gbhHmi-X-K075WggW7s344rUx3HuQnM/s1600/focus50.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrlsXJZxbqpHrb2u1rs3W3yW1C1QIs5d36_nkr5DTa5idYnM57g2MBpXjxVcubcXLhk9txED8rofM2_XXIbjFjo0BZj-QnzfWlG1nk1gbhHmi-X-K075WggW7s344rUx3HuQnM/s1600/focus50.png" /></a></h3>
<h3>
<br /></h3>
<h3>
目前位置按鈕</h3>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
預設情況地圖中央會對準並固定在目前位置,<br />
<br />
也就是當你移動時地圖也會同時移動,<br />
<div>
<br /></div>
<div>
總之你的位置會固定在地圖中央,<br />
<br />
但當拖動或縮放地圖後,就會取消將目前位置固定在地圖中央,<br />
<br />
這時只要按下左下角第一個按鈕,<br />
<br />
就會立刻回到目前位置。<br />
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlFdWqr_MG3lzYrX2Nb4x86h9iznIU8VNZWvgNvT_Sx1VvbYAxHnZSOHaDNUwRoLzD3DUojoxkQaQLJCAYiv92DYkfwXOB5U8PikCA5HGwg8hjl8uVxwWJhj86OrfXO2J7FR5m/s1600/pin50.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlFdWqr_MG3lzYrX2Nb4x86h9iznIU8VNZWvgNvT_Sx1VvbYAxHnZSOHaDNUwRoLzD3DUojoxkQaQLJCAYiv92DYkfwXOB5U8PikCA5HGwg8hjl8uVxwWJhj86OrfXO2J7FR5m/s1600/pin50.png" /></a></div>
<h3>
目的地位置按鈕</h3>
<br />
當地圖上插上旗子後,就可以隨時按下目的地位置按鈕查看旗子插在哪裡。<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5KFzpI3yxkOr8k7CVI2ruoB48WL66RHljdSIa6hsEdinMVDHeF_eRvcb9HLkgYF5-_m4yDoGoBzx6KDFD-Fgl4FkhVqwgZ6Xl5C5SmOeu9scjj09VXbUwEwciRTlJH_8fqP6K/s1600/btn2_search.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5KFzpI3yxkOr8k7CVI2ruoB48WL66RHljdSIa6hsEdinMVDHeF_eRvcb9HLkgYF5-_m4yDoGoBzx6KDFD-Fgl4FkhVqwgZ6Xl5C5SmOeu9scjj09VXbUwEwciRTlJH_8fqP6K/s1600/btn2_search.png" /></a></div>
<br />
<h3>
地點文字搜尋</h3>
<div>
除了由地圖上找以外,也可以例用關鍵字來搜尋地點,</div>
<div>
<br /></div>
<div>
只要在放大鏡圖示左方的文字輸入區域輸入地點關鍵字,</div>
<div>
<br /></div>
<div>
就會幫你找出與你目前位置最相近的幾個符合關鍵字的地點。</div>
<div>
<br /></div>
<div>
你可以輸入如:台北101、便利商店、加油站或中山北路等形式</div>
<div>
<br /></div>
<div>
系統會幫你找出<span style="color: #e06666;">離目前地圖中心點</span>最近的地點,最多八筆資料。</div>
<div>
<br /></div>
<div>
並且將結果標示在地圖上。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEif37T3f1dqElZIbqQOuaCxlv31-f81HGN0a7PwKPahhUgyKjqlu7fk0dW_n5tdSDe5RWB-s4uH7VVVaFQHaK8dPhuMyi0te4dTClxQmsZ0oYNvkDTRv4J31M4mXbQlyYLQIzZF/s1600/device-2012-06-18-211416.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEif37T3f1dqElZIbqQOuaCxlv31-f81HGN0a7PwKPahhUgyKjqlu7fk0dW_n5tdSDe5RWB-s4uH7VVVaFQHaK8dPhuMyi0te4dTClxQmsZ0oYNvkDTRv4J31M4mXbQlyYLQIzZF/s400/device-2012-06-18-211416.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div>
<br /></div>
<div>
你可以利用手指左右滑動下方地點資訊,來找到不同的地點,</div>
<div>
<br /></div>
<div>
利用星星+的按鈕可以將此位置記錄到我的最愛當中。</div>
<div>
<br /></div>
<div>
<br /></div>
<h3>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjv8UkScw_Uaei7NMTAln9C4-nusHf-oidlBucO-Rli3NHaTSWKtTgv43ZMh2QtVIn0l32QEuoWU7W4SbNz9r4UvoxzMJnqZfxoOHHEgCIz8SWp9kLLYLhDO9uhaZtPLlSmpqrG/s1600/mic.png" imageanchor="1" style="background-color: white; margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjv8UkScw_Uaei7NMTAln9C4-nusHf-oidlBucO-Rli3NHaTSWKtTgv43ZMh2QtVIn0l32QEuoWU7W4SbNz9r4UvoxzMJnqZfxoOHHEgCIz8SWp9kLLYLhDO9uhaZtPLlSmpqrG/s1600/mic.png" /></a>地點語音搜尋</h3>
<div>
在駕駛過程中,可能不方便打字,</div>
<div>
<br /></div>
<div>
可以利用語音的方式說出關鍵字,來進行地點搜尋,</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-M6LsO6Ev6k0ELt-LEhnYU8SkCAUlZ9-u1NVkIiGOANt7-2b6_pNLR1QGy3XOQ347W5KK7jyeUf7-RWZWgsLXjXugdonsJFwHICeobgXVxO6Bg7V2hJwPj8Q_adyFyAm_KWuo/s1600/poster5.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-M6LsO6Ev6k0ELt-LEhnYU8SkCAUlZ9-u1NVkIiGOANt7-2b6_pNLR1QGy3XOQ347W5KK7jyeUf7-RWZWgsLXjXugdonsJFwHICeobgXVxO6Bg7V2hJwPj8Q_adyFyAm_KWuo/s400/poster5.jpg" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<h3>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-0bByeSnkzrt4JTWdV5U9Y5CHykqOXP8h-j7Y1pkJeXlx-LHIys33_-EyuUwdzHo74QlhJw0HL4kySazsgfIxwjbN2v_2n9RqFvkvHF7rjn8lF6P3kldqf0Sebme_CmI8Ls3Q/s1600/star50.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-0bByeSnkzrt4JTWdV5U9Y5CHykqOXP8h-j7Y1pkJeXlx-LHIys33_-EyuUwdzHo74QlhJw0HL4kySazsgfIxwjbN2v_2n9RqFvkvHF7rjn8lF6P3kldqf0Sebme_CmI8Ls3Q/s1600/star50.png" /></a><b>我的最愛</b></h3>
<div class="separator" style="clear: both; text-align: left;">
當你將地點設成我的最愛後,可以在我的最愛當中看見,</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJFniC6R9Y2tZ33JhBpphveN0rMvJkrfWHcReGTrxfHSEdXqfrP8JfVKLpsPIBgyd3zbt5hGXp7-HhOT0QgDz3I04loLiRL233oia1hMTLcYYRL8TAJxPGBoEiieh9dPiLZMev/s1600/poster4.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJFniC6R9Y2tZ33JhBpphveN0rMvJkrfWHcReGTrxfHSEdXqfrP8JfVKLpsPIBgyd3zbt5hGXp7-HhOT0QgDz3I04loLiRL233oia1hMTLcYYRL8TAJxPGBoEiieh9dPiLZMev/s400/poster4.jpg" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
只要在地點項目上長按,就可以進行編輯名稱或刪除地點的操作。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
只要善加利用我的最愛,就可以將常用的目的地建立於其中,</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
這些目的地可以綁定你在程式中所選擇的Google帳號,</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
當你有新的Android裝置時,只要使用同樣的帳號,</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
就可以取回我的最愛地點列表。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
直接點選地點項目則啟動導航到此地點。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<h3>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDNb2jTNOzQPhsx8MRpZqs68qs_YuIX2No4RknOT6U4GKwElup2_uysSuy8Phnb7-2EeP8burYBQ8GBVCdmNNrpUIGeG-oK_xAE3XABsJCgDDNmNrj7oty3lXsSFDAro-zVblG/s1600/history50.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDNb2jTNOzQPhsx8MRpZqs68qs_YuIX2No4RknOT6U4GKwElup2_uysSuy8Phnb7-2EeP8burYBQ8GBVCdmNNrpUIGeG-oK_xAE3XABsJCgDDNmNrj7oty3lXsSFDAro-zVblG/s1600/history50.png" /></a>歷史紀錄</h3>
<div>
這裡記錄著您曾經導航過的地點,</div>
<div>
<br /></div>
<div>
你可以經由長按地點項目來進行重新命名、刪除、</div>
<div>
<br /></div>
<div>
將地點設為我的最愛、以及刪除全部幾項工作。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
直接點選地點項目則啟動導航到此地點。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
透過這些功能,你就可以簡單的紀錄常用到的目的地囉!</div>
<div>
<br /></div>
</div>Anonymoushttp://www.blogger.com/profile/10433873918988135141noreply@blogger.com0tag:blogger.com,1999:blog-9873545.post-30337550639333156982012-06-08T12:00:00.003+08:002014-12-30T00:42:06.667+08:00Navier HUD change log<h3>
Localization</h3>
<div>
<ul>
<li><span style="font-size: x-small;">English (Supported by Martin Vrieling )</span></li>
<li><span style="font-size: x-small;">Dutch (Supported by Martin Vrieling )</span></li>
<li><span style="font-size: x-small;">Portuguese (Supported by Rafael Rosário )</span></li>
<li><span style="font-size: x-small;">Czech (Supported by Oldřich Havlík )</span></li>
<li><span style="font-size: x-small;">TURKISH (Supported by Özgür KAYA)</span></li>
<li><span style="font-size: x-small;">GREEK (Supported by John Souroufis)</span></li>
<li><span style="font-size: x-small;">SPANISH (Supported by Hernan de Soto)</span></li>
<li><span style="font-size: x-small;">POLISH (Supported by drblade)</span></li>
<li><span style="font-size: x-small;">ITALIAN (Supported by Luca Tornatola)</span></li>
<li><span style="font-size: x-small;">RUSSIAN (Supported by Сергей Рязанов )</span></li>
<li><span style="font-size: x-small;">FRENCH (Supported by Antoine Cadoret )</span></li>
<li><span style="font-size: x-small;">GERMAN (Supported by Marc Hillesheim )</span></li>
<li><span style="font-size: x-small;">ARABIC (Supported by Majid AL-Dharrab)</span></li>
<li><span style="font-size: x-small;">SLOVENIAN (Supported by popotnik)</span></li>
<li><span style="font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"></span>CROATIAN (Supported by Damir Karic)</span></li>
<li><span style="font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"></span>FINNISH (Supported by Markku Lahti)</span></li>
<li><span style="font-size: x-small;">繁/簡中文 </span></li>
</ul>
<div>
If you can help me to correct/translate UI description to your native language, please contact me by the following e-mail <a href="mailto:lu.shangchiun@gmail.com">lu.shangchiun@gmail.com</a><br />
<h3>
---------------------</h3>
</div>
</div>
<div>
<br /></div>
<div>
<br /></div>
<h3>
Latest update</h3>
<div>
@ 2.3.5<br />
<br />
<ul>
<li></li>
<li>- Minor bug fixes</li>
<li>- Add three premium-only parts, include 3D ROUTE, ROAD NAME, WIDE_ROUTE_DIRECTION, DISTANCE_TO_TURN</li>
<li>- Route re-plan issue has been fixed</li>
</ul>
</div>
<div>
<ul></ul>
<br />
<h3>
<br />
</h3>
</div>
Anonymoushttp://www.blogger.com/profile/10433873918988135141noreply@blogger.com