星期三, 3月 19, 2014

Holo style : the Android style



我是一位Android開發者,獨立開發者,
從UI設計到程式開發一手包辦,
很多會寫程式的人,程式的部份可以自己搞定,
但多數人會卡在『糟糕;我沒有美術的天份』這裡,
認為自己弄不出夠水準的介面設計。

於是會將程式介面外包給設計師來做,
本來術業有專攻,那也沒什麼不好。
問題是,有些介面設計師手拿iPhone, iPad,
連Android手機都沒用過,
你怎麼能期待他比你更知道Android的介面應該是什麼樣子呢?

星期四, 2月 20, 2014

Hangout 造成發送與接收SMS問題


Google 在Android 4.4改以Hangout來取代原本預設的簡訊App,因此在App如果有寫到傳送或接收SMS功能時,在Kitkat上或是有安裝Hangout的舊版本(Android 4.3及以下)手機上,可能會運作不正常。

在接收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"。此時解決方法是在Broadcast Receiver上加上priority,並將priority設為大於3,如此一來便能解決收不到"android.provider.Telephony.SMS_RECEIVED"的問題。請參考此討論

<receiver android:name="com.google.android.apps.babel.sms.AbortSmsReceiver" android:permission="android.permission.BROADCAST_SMS" android:enabled="false">
    <intent-filter android:priority="3">
        <action android:name="android.provider.Telephony.SMS_RECEIVED" />
    </intent-filter>
</receiver>
在傳送SMS時在Kitkat上Google 已經把簡訊App拿掉,因此已以往Intent的方式來發送SMS可能會遇到找不到預設App的問題,解決方式如下:請參考此討論

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) //At least KitKat
    {
        String defaultSmsPackageName = Telephony.Sms.getDefaultSmsPackage(activity); //Need to change the build to API 19

        Intent sendIntent = new Intent(Intent.ACTION_SEND);
        sendIntent.setType("text/plain");
        sendIntent.putExtra(Intent.EXTRA_TEXT, smsText);

        if (defaultSmsPackageName != null)//Can be null in case that there is no default, then the user would be able to choose any app that support this intent.
        {
            sendIntent.setPackage(defaultSmsPackageName);
        }
        activity.startActivity(sendIntent);

    }
    else //For early versions, do what worked for you before.
    {
        Intent sendIntent = new Intent(Intent.ACTION_VIEW);
        sendIntent.setData(Uri.parse("sms:"));
        sendIntent.putExtra("sms_body", smsText);
        activity.startActivity(sendIntent);
    }

星期二, 10月 15, 2013

Code Lab - Communication among Android devices : A chat room


此Android程式練習是為成大資工系-電腦通訊網路課程 所設計的一個Code Lab,目的在介紹Android之間的裝置通訊,以及在Android上面如何實作一個聊天室應用,其中包含在Server端的HttpServerlet以及GCM Api的使用。
此App運用可以上安裝此App的所有使用者彼此間進行聊天。
課程時間:3小時

投影片下載

星期三, 10月 09, 2013

Code Lab - RESTful App on Android : A POI Map

此Android程式練習是為成大資工系-電腦通訊網路課程 所設計的一個Code Lab,目的在介紹REST架構的運作原理,以及在Android上面如何實作包含Google Map、Http Request、AsyncTask及UI Adapter應用。

此App運用DEH API來開發一個簡易的LBS服務,查詢地圖中心附近2公里內所包含的景點有哪些。

課程時間:3小時
投影片下載
在Google Play下載:
Get it on Google Play

星期三, 10月 02, 2013

CoWallet

Coming soon on Google Play!

CoWallet makes expense management of a group easier.



星期三, 6月 26, 2013

Suunto Ambit:一支和Navier HUD操作邏輯酷似的錶


不久前買了一支手錶Suunto Ambit,原本只是期待有個功能穩定具有GPS軌跡記錄功能的手錶,不過卻發現其操作邏輯和Navier HUD的使用邏輯相當接近。

荷蘭廠商Suunto將Suunto Ambit其定位為適合專業登山及運動的電子錶,以硬體規格來看,這隻錶具有GPS接收器、氣溫計、氣壓(高度)計、羅盤四種Sensor,並且可以無線連接心律帶,因而能夠提供GPS定位、軌跡記錄、提供氣溫、垂直水平移動速度、距離、高度等資訊,並具有100米防水的規格,也就是你絕對可以帶著去進行大部分水中的活動,並絕對可以提供大部分運動時的需求。


透過Movecounts帳號,可以輕易的將運動記錄保留下來,並分享到其他社群網站當中。並且在Movescount網頁中調教你的手錶設定


只要安裝Moveslink這個軟體,並將手錶連接到電腦上,就能進行資料同步。

但以上都不是重點,以下才是重點XDDD

到底哪裡和Navier HUD有夠相似呢?以下兩點說明:

自定資訊顯示面板

Suunto Ambit中提供了幾種預設的運動模式,也可以自行調整或新增運動模式,每種運動模式能夠顯示最多八個畫面的內容,每個畫面可以自行調整要顯示哪些資訊。




舉個例子,我希望在我跑步這個模式當中,能夠有五個畫面來顯示我需要的訊息,其中第一個畫面要顯示包含跑步累積時間、累積的距離、以及我的心律。第二個畫面則要顯示跑步的速度、平均速度及當時的氣溫。第三個畫面顯示我的上坡累計里程和下坡累計里程、目前時間...

當我在執行跑步的模式時,我就能透過按鈕來切換到不同的畫面,查看我所定義的畫面。因此你可以調整各種運動所需要取得的內容,來因應當運動的需求。

這樣的概念與Navier HUD可以依照需求來新增與編輯所需的面板,並且為每個面板加入適當的元件,邏輯一致。但Navier HUD因為手機畫面較大,能夠調整元件的位置較自由。Suunto Ambit則因為所配備的Sensor而能夠有更多移動資訊來源。

路線導航

Suunto Ambit因為具備GPS Sensor,因此也具備了簡單的導航功能,由於手錶操作限制,在使用導航功能之前,你需要在Movecounts先規劃完路線,並連接手錶與電腦將路線匯入之後,就可以開啟導航功能。


和Navier HUD同樣,你得先在地圖上找出要走的路,啟動導航之後,你只會看到該走的路線,而不包含其他的叉路。

除了這些以外,Suunto Ambit也把App的概念帶進來,在Suunto Ambit當中所指的App,其實是以簡單的Script將本來已經有的數值資料,經過額外的計算產生另一個你所想要知道的資料。

舉例來說,我常常一次跑步跑5公里,所以當我在跑步時想知道依我現在跑步的速率,以及累計的里程數來算,究竟還要跑多少時間才能跑完5公里?或者單車騎士在行進過程到底做了多少次衝刺?

這些資料在原本的手錶當中並沒有提供,使用者卻可以利用撰寫程式碼來建立符合自己需求的App,將計算結果放到某個運動模式的畫面中,並可以選擇把它分享在App Zone當中。


如果你懶得自己寫,或者不會寫程式,可以直接到App Zone當中找到適合你使用的App,其中已經有多達一千多個App,有很大的機會有其他人已經寫了你需要的計算了。

這真是一支很酷的手錶,並且耗電也在可接受的範圍(沒使用GPS時,可以使用約30天,連續使用GPS且設定每秒一筆資料時,可以支撐八小時,和一般軌跡記錄器差不多),還有很多功能小細節沒有講,只好自己去體驗。這絕對不是勸拜文,如果你不小心拜了,也要記得連Navier HUD一起拜阿阿阿...


星期六, 4月 13, 2013

抬頭顯示DIY





常常有使用者問說在白天的時候,使用Navier HUD時是不是會看不清楚?
是的,如果在大太陽下把手機放擋風玻璃下肯定會看不清楚,
但如果需要在白天也能使用抬頭顯示,其實還是有方法可以自己DIY做到,

反光隔熱紙


只要到汽車用品店購買一張反光隔熱紙,貼在手機映射的位置上,
就能讓抬頭顯示影像在白天更清楚。
一般市售隔熱紙都是一大張,因此需要依照自己的手機大小,動手裁切成適合的尺寸。
我覺得在駕駛座左下角是最適合的位置,也不會擋到視野。

止滑墊


且為了避免手機會在前方會滑來滑去,
您可能還需要一個小小的止滑墊,也是在汽車用品店可以買到,

車充與電源線


在使用抬頭顯示時,通常會把手機亮度開到最大,這時螢幕耗電量將大增,
因此如果是長途使用時,會需要以車充來補充電源,車充在便利商店就可以買到。


如此一來,配合上Navier HUD您就有一個專業的抬頭顯示環境囉。

在這裡下載Navier HUD
Android app on Google Play

星期三, 3月 13, 2013

Google Partner Day 2013

真高興能夠有機會參與Google Partner Day活動,這是我第一次參加,今年舉辦地點在台北寒舍艾美酒店,活動著實讓我獲益良多,
活動主要分成兩個部分,Adsense和AdMob,我當然是選聽AdMob的部份

多"螢"為活動主題

寒舍酒店的場地


廣告類型和位置擺放的注意事項


Sam Lu 聊成功經驗

這張圖很清楚的解釋使用px與dp在不同解析度螢幕的差異

包含WhosCall的營運長和Sam Lu、Google代表等成員的座談


與會者的App Logo,Navier HUD也在上面

我認為其中最有幫助的是討論到如何讓自己的App被Google Play feature的部份,
雖然現在我的app還沒有被feature過,不過我有信心那只是不久之後的事情罷了(自以為..) :D
參加完活動又點燃了我的雄心壯志了

2013我們一起成長吧



星期日, 2月 17, 2013

在Android 上模擬GPS位置


最近在大翻修Navier HUD,
為了加入一些過去做不到的特色,
這些功能不是靠小改版就能處理的,
因此把過去沒加入的遺珠之憾透過這一次翻修,
整理整個架構。
Google Map也使用新版本來寫,
但在Google Map v2 API 無法在模擬器上執行,
地圖的部分會變成下圖那樣一片黑
並要求你更新Google Play Services
只是基於安全政策,模擬器是沒辦法更新Google Play Service的

本來那也沒什麼,因為只要使用實機來測試就行了,
在模擬器上執行有個好處,
就是可以使用DDMS來餵模擬器kml或gpx格式的GPS資料,
如果已經有了預先記錄好的GPS 經緯度資料,
就可以拿來測試。
一旦模擬器開不了地圖,這些GPS就沒用武之地了。

如果程式碼中沒有使用到Google API元件
可以參考此文章的作法
http://nemanjakovacevic.net/blog/2012/12/how-to-make-android-google-maps-v2-work-in-android-emulator/

但如果需要使用Google API,上面的方法就沒用拉。
既然實機不能用DDMS餵資料,
最後只好自己寫程式餵自己APP資料拉。

那在實機上怎麼餵假的GPS資料呢?
這時會需要實作一個Mock Location Provider
如下程式碼


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
public class MockLocationProvider {
 String providerName;
 Context ctx;

 public MockLocationProvider(String name, Context ctx) {
  this.providerName = name;
  this.ctx = ctx;

  LocationManager lm = (LocationManager) ctx
    .getSystemService(Context.LOCATION_SERVICE);
  lm.addTestProvider(providerName, false, false, false, false, false,
    true, true, 0, 5);
  lm.setTestProviderEnabled(providerName, true);
 }

 public void pushLocation(double lat, double lon) {
  LocationManager lm = (LocationManager) ctx
    .getSystemService(Context.LOCATION_SERVICE);

  Location mockLocation = new Location(providerName);
  mockLocation.setLatitude(lat);
  mockLocation.setLongitude(lon);
  mockLocation.setAltitude(0);
  mockLocation.setTime(System.currentTimeMillis());
  lm.setTestProviderLocation(providerName, mockLocation);
 }

 public void shutdown() {
  LocationManager lm = (LocationManager) ctx
    .getSystemService(Context.LOCATION_SERVICE);
  lm.removeTestProvider(providerName);
 }
}

使用下列方式來餵一個假GPS位置,如果是模擬連續收到數個GPS位置可以以一個迴圈來提供位置,並mock.wait(int milisec)來處理時間間隔

1
2
3
mock = new MockLocationProvider(LocationManager.GPS_PROVIDER, _context);

mock.pushLocation(point.lat, point.lng);

在AndroidManifest.xml需加入允許假位置的權限

android:name="android.permission.ACCESS_MOCK_LOCATION";

在測試的手機上必須在設定>開發人員選項>允許模擬位置 打勾


最後,在釋出正式版本之前,記得要註解掉假GPS部分的程式碼。

可以參考此連結文章了解http://mobiarch.wordpress.com/2012/07/17/testing-with-mock-location-data-in-android/

星期三, 1月 09, 2013

SlidingMenu開放原始碼專案

 

自從Android 3.0帶來了Fragment概念,
除了對開發者需要面對多種size的Android裝置具有正面的意義外,
讓Android Activity本來較為死板的換頁方式,帶來了更多變化,
藉由在一個Activity上自由搭配多個Fragment,
並結合越來越豐富的動畫效果,來切換不同的Fragment
愈來愈多絢麗的頁面切換效果也逐漸出現在Android app上。

其中最常見到,具有豐富視覺效果的切換特效非SlidingMenu莫屬,
SlidingMenu效果可以在Evernote或是feedly兩個我個人常用的軟體中見到。
使用SlidingMenu藉由兩個Fragment間(也可以是兩個ViewGroup)的滑行效果
來切換介面。

SlidingMenu Open Source Project

要實現這樣的效果需要自己設定許多Animation 的參數,
藉由盧育聖(ysl程式設計天堂部落格作者)的粉絲頁分享,
才知道這樣的效果已經有別人寫好,並開放原始碼與其他開發人員共享,
在GooglePlay上有一個使用範例可以在下方連結中下載
SlidingMenu Demos

如果你也想在App中呈現這樣的效果,
不需要自己造輪子,
可以在GitHub上找到完整開放原始碼專案。
SlidingMenu 開放原始碼專案

整合到你的專案

要將SlidingMenu整合到你的專案當中,
需要下列幾個步驟:


將開放原始碼專案下載下來,並匯入Eclipse當中。(在這之前你應該要裝好了Andorid 開發環境)其中會兩個Project,SlidingMenuActivity是主要我們要使用的部份,另一個ExampleListActivity是上述Google Play中可以下載的到的SlidingMenu Demo專案。不妨把兩個專案都載入,這個Example專案可以讓你了解該怎麼使用這個原始碼專案。



因為專案中有提供MapActivity所以Android SDK需選擇有Google APIs的版本,載入專案之後先進行Project > Clean的動作,以產生必要的R.java檔。
如果您的專案只支援3.0以上的版本,引用SlidingMenuActivity專案之後(在Package Explorer中,選擇ProjectName按下右鍵 > Properties > Android > Library > Add ),在您的專案裡就可以使用當中所提供的SlidingMenuActivity了。

Example 專案

如果你想要測試Example專案,這時應該還存在著錯誤,因為這個Example專案在Fragment和Action Bar的部份是使用Support Library來支援的,因此我前面才說,如果你專案只支援Android 3.0以上,那就不需要接下來的動作。
但如果你的專案必須支援Android2.X甚至到Android1.6以上,那我們還需要進行一些設定。

匯入ActionBarSherlock Open Source專案

下載並在Eclipse當中匯入ActionBarSherlock專案,這個專案主要讓所有的Android版本都能夠使用只有在Android 3.0以上才支援的Action Bar的功能。其中有數個sample專案,但我們只需要匯入library這個專案(除非你想深入了解ActionBarSherlock要怎麼用)。

在SlidingMenuActivity當中引用ActionBarSherlock專案。 


因為Example專案當中使用了SlidingFragmentActivity,因此需要將SlidingFragmentActivity做些修改,以支援Android3.0以下的版本。

修改SlidingMenuActivity中的SlidingFragmentActivity.java
將原本extends FragmentActivity改成SherlockFragmentActivity
完成後做一次Project > Clean,之後Example專案就可以順利執行了。

透過這個Example專案,可以很輕易的了解如何使用SlidingMenu 專案,並製作出很具視覺效果的滑動切換頁面動畫了。