2017年5月31日 星期三

Android Studio 使用WebP縮圖減少APK Size。

Android Studio 可以將 PNG, JPG, BMP, GIF 轉為 WebP,可有效縮小圖檔大小。
Android 4.0(API 14) 以上就可以支援WebP
但含透明的圖片,需要Android 4.2.1(API 17)才支援。
你可以轉一個檔案,或將整個資料夾一起轉。

右鍵點擊圖檔或資料夾,點擊 Convert to WebP
這裡可設定壓縮比


下圖可以看到檔案縮小了,圖檔也看不出2張有什麼差異。



也可以從這裡下載Webp轉檔工具
https://developers.google.com/speed/webp/

參考
https://developer.android.com/studio/write/convert-webp.html

Android 9-Patch 建立自動調整大小以適應視圖內容與螢幕尺吋的圖片

Android 可以使用9-Patch建立自動調整大小以適應視圖內容與螢幕尺吋的圖片,
例:我要把這個圖檔當作我的背景圖,裡面放文字用。紫色區塊需要隨著裡面的字變多而延展。



做成像下圖的效果:



作法很簡單:
在android studio,右鍵點擊要建立NinePatch的png圖檔,然後點擊 Create 9-path file。
點擊9-patch檔案,在android studio 打開,會出現如下畫面

在4個邊邊的灰白相間的線,點一下加上黑線,這個黑線代表可延展區塊
要取消黑線的話,按住shift再點一下黑線就可以了。
勾選下方的Show patchs,可以看到粉紅色的區塊為可延展區塊,綠色區塊為不可延展區塊。



另外如果你build 看到這樣的訊息:some file crunching failed ,代表你的 9-patch 檔案有問題
開啟9-patch檔案,勾選 Show bad patches,就可以看到錯誤在哪裡了


完整程式碼:https://github.com/evanchen76/NinePatchSample

參考:https://developer.android.com/studio/write/draw9patch.html

2017年5月30日 星期二

Android Notification 的幾種樣式

推播內容加上一張小圖片




推播內容加上大圖加上下方的按鈕



//載入bitmap
Bitmap largeIcon = BitmapFactory.decodeResource(getResources(), R.mipmap.user);
//設定大圖Style
NotificationCompat.BigPictureStyle bitStyle = new NotificationCompat.BigPictureStyle();
bitStyle.bigPicture(largeIcon);
//設定按鈕
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.addAction(R.mipmap.ic_launcher, "Reply", replyIntent)



推播內容使用客製的View



//new RemoteViews 載入客製layout
RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.notification_view);
//設定使用CustomView
notificationBuilder.setCustomBigContentView(remoteViews);



客製view
notification_view.xml


完整程式碼:https://github.com/evanchen76/PushNotificationSample

參考:https://developer.android.com/guide/topics/ui/notifiers/notifications.html

2017年5月27日 星期六

Android Canvas 繪製幾何圖形

Canvas的意思就是畫布
Paint 代表了Canvas上的畫筆
以下範列記錄幾種Canvas繪製幾何圖向的方法

canvas.drawArc (扇形)
canvas.drawCircle(圓)
canvas.drawOval(橢圓)
canvas.drawPoint(點)
canvas.drawRect(矩形)
canvas.drawRoundRect(圓角矩形)
canvas.drawLine(線)
cnavas.drawPath(路徑)

DrawCircle


DrawArc


DrawOval


DrawLine



DrawPath


DrawPoints


DrawRect


DrawRoundRect


完整程式碼: https://github.com/evanchen76/CanvasSample

2017年5月24日 星期三

Android Gradle productFlavors 匯出不同版本APK


在開發android app時,我們可能會有如下的需求:

正式版與測試版,會有正式版連線的API與測試版連線的API,
或是測試環境與正式環境有不同的ApplicatoinId時,
這時就可以使用Gradle productFlavors,依不同的版本設定不同的參數

在Gradle裡加上productFlavors ,將版本分為dev、prod
dev、prod各使用不同的applicationId

productFlavors {
    dev {
        applicationId "evan.chen.app.productflavorsample.dev"        
resValue "string""version_type""Free Version"    }

    prod {
        applicationId "evan.chen.app.productflavorsample"       
resValue "string""version_type""Pro Version"    }
}

接著建立一個Constants裡放API的網址。



public class Constants {
    public static final String API_URL "http://staging-api.evanchenapp.com";
}




public class Constants {
    public static final String API_URL "http://api.evanchenapp.com";
}


MainActivity 取得 API_URL

public class MainActivity extends AppCompatActivity {

    @Override    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Log.d("Log""Url:" + Constants.API_URL);
    }
}

最後,在Build Variants選擇build的版本就可以了

2017年5月23日 星期二

android Keyguard 呼叫螢幕解鎖驗證

android 的 Keyguard 可以用來呼叫螢幕解鎖來驗證,
運用在有做自動登入時,避免使用者手機被偷,可以在app的重要功能再次要求解鎖

以下這個範例,
按下Verify按鈕時,會依照你的手機設定的解鎖方式開啟驗證(PIN、Password、Pattern、Fingerprint)



要使用Keyguard,API Level 21 以上。

先檢查手機是否有開啟螢幕鎖定。 在Activity 叫起驗證頁,可以客制Title、Description



接收解鎖結果:


完整程式:

參考:

2017年5月12日 星期五

Android MVP Pattern (Model View Presenter)

MVP (Model View Presenter)是由MVC (Model View Controller)演變而來。
在MVC的架構,通常會把layout(xml)當成View,Activity當成Controller,
事實上,Activity 卻是Controller 與View 的混合,於是Activity既要做處理View,也負責商業邏輯。使得Activity越來越肥。

MVC ->  MVP 的最大差異在於 Activity的商業邏輯移到Presenter,Activity 專心於View

MVP:
Model - 提供資料、儲存資料 例:SharedPreferences、呼叫API
View - 負責展示UI,如 Activity、Fragment
Presenter - 負責邏輯處理

來看看這個範例,輸入帳號密碼後,按下「LOGIN」顯示登入成功或失敗。


新增LoginActivty 為MVP 中的View
新增LoginContract ,裡面放了ILoginView、ILoginPresenter 2個Interface
新增LoginPresenter,負責商業邏輯,與Model互動。
建立 User Model,負責檢查帳號是否正確。(範例單純hard code判斷,一般在此與API 登入)



LoginActivity ( View )


LoginPresenter (Presenter)
User (Model)




完整程式
https://github.com/evanchen76/MVP-Pattern

2017年5月10日 星期三

Android ViewAnimation

ViewAnimation,可以在各種View 上做透明度、大小、位置、旋轉的動畫

可以透過xml定義,xml放於res/anim目錄下

4 種動畫效果


alpha 透明度
scale 大小縮放
translate 位置移動
rotate  旋轉

<alpha>

透明度變化的動畫效果(淡入淡出)

android:duration 動畫持續的時間(毫秒)
android:fromAlpha 動畫開始的透明度。0為完全透明,1為不透明。
android:toAlpha  動畫結束的透明度。0為完全透明,1為不透明。

2秒慢慢變為完全透明

<translate>

移動動畫效果

android:duration 動畫持續的時間(毫秒)
android:fromXDelta 起始位置偏移量
android:toXDelta 結束位置X偏移量
android:fromYDelta 起始位置Y偏移量
android:toYDelta 結束位置Y偏移量

以上的值可設定%設定相對View的百分比位置,或%P來設定相對Parent View的百分比位置

移動至XY,View的一倍距離。

<scale>

縮放的動畫效果

android:duration 動畫持續的時間(毫秒)
android:fromXScale 起始的X座標縮放倍數 
android:toXScale 結束的X座標縮放倍數
android:fromYScale 起始的Y座標縮放倍數 
android:toYScale 結束的Y座標縮放倍數
android:pivotX 縮放時不變的X坐標,用百分比表示,0%表示左邊緣,50%為中間,100%表示右邊緣)
android:pivotY 縮放時不變的Y坐標,用百分比表示,0%表示上邊緣,50%為中間,100%表示下邊緣)

放大3倍,pivotX="50%" 代表中心點在中間

<rotate>

旋轉的動畫效果

android:duration 動畫持續的時間(毫秒)
android:fromDegrees 旋轉開始的角度
android:toDegrees 旋轉結束的角度
android:pivotX 旋轉中心點的X座標,
android:pivotY 旋轉中心點的Y座標

pivot 值可設定%設定相對View的百分比位置,或%P來設定相對Parent View的百分比位置

旋轉720度,即2圈。pivotX="50%" 代表中心點在中間

啟動這些動畫的方式,在Activity呼叫View.startAnimation
AnimationListener
implements Animation.AnimationListener ,動畫開始、結束、重複的事件。

完整程式
https://github.com/evanchen76/AnimationSample

參考
https://developer.android.com/guide/topics/graphics/view-animation.html

Android 工具 logger

來介紹一個非常好用的android studio Log工具

這是系統預設的Log方式,是不是看得很痛苦


使用Logger


Gradle
compile 'com.orhanobut:logger:1.15'

Log 的結果,類別、方法都幫你寫在log,非常清楚。


json、Exception 也可以log


Array, Map, Set, List 都可以log,
更多詳細的介紹可以到github上看。github上介紹的很詳細喔。



2017年5月9日 星期二

android 開發手機選擇

如果你的公司要開發app需要購買開發用手機。
有幾個考慮的方向,可以參考看看囉

  • 不同螢幕大小
  • 不同OS版本
  • 不同手機廠牌
  • 有低階手機
  • 手機及平版

不同螢幕大小

算是比較不重要的,不過還是建議有幾隻不同大小的手機。

OS版本的選擇

不同OS的分佈,算是最重要的。
至少4.x, 5.x, 6.x, 7.x 各要有一隻
可參考 android developer dashboard 的最新分佈 


























不同手機廠牌的選擇

如果你開發的app跟硬體有很大的相關,就儘量多選幾個不同的廠牌,
例如你的app有自行寫拍照功能、遊戲 等等。
但主要還是選擇你的app市場的使用者主要使用的廠牌。

有低階手機

至少有一隻低階手機,可以讓你較早發現效能問題。

手機及平版

你的app在手機及平版是否有不一樣的設計?


舊的手機,例如android 4.x,你可能較難買到新品,可以考慮到通訊行買二手的,這些通訊行也都是可以開發票的。

另外要記得,小心不要把你的測試手機os升級了,
android 如果os升級是無法再回復的

那要買幾台才夠呢?
在app剛開始要開發時,就跟公司說你要買10幾隻手機,有些公司老闆可能不會接受。
可以考慮先買5隻開發用的手機(大概就可以包含4.x~7.x及主流廠牌),
但這些都只是開發用的手機選擇喔,要測試的話應該就不是我講的這麼簡單了。









開發 android app 的資安注意事項


開發 android app  有幾個關於資安的注意事項,大家可參考囉。
  1. 不要儲存敏感資料,如非儲存不可,儲存於作業系統保護之區域並加密。加密的key和編碼過的文件不要放在一起
  2. 用於加解密之key,android 存放於so或Android Keystore Provider
  3. 用來加密的key,可再加上使用者的密碼
  4. 傳輸重要參數應加密
  5. Log.d、NSLog在release版不要使用。
  6. 檢查作業系統是否被破解(root)
  7. 使用Sqlite應注意Client SQL Injection
  8. 檢查app權限uses permission是否適當
  9. 如有html5 需注意LocalStorage儲放XSS攻擊程式與shell code
  10. 遠端刪除功能防止手機遺失。
  11. 加解密method應為private。
  12. 只允許連到指定的連結(如果你的專案允許的話)
  13. android 開啟程式碼混淆ProGuard,避免被反組譯太容易看到程式碼
  14. 如無需要,關閉 Allow Backup,不允許android備份至雲端或電腦。
  15. 傳輸GCM資訊應使用HTTPS
  16. android:debuggable relase版不可為true
  17. 執行時檢查是否 debug 模式,android.os.Debug.isDebuggerConnected(),防止使用者反向編譯後再重新執行 PackageManager.GET_SIGNATURES
  18. 重要交易採用多因素認證(例簡訊傳送認證碼)
  19. 作業系統的保護是不安全的
  20. 上位或公司的政策「簡單勝於安全」可能是照成安全問題的原因,例如每次都要輸入密碼太麻煩

參考資料

Android Custom Component

如下圖,這是一個購物車常見的購買份數選擇。
將「減」按鈕、「加」按鈕及中間的數值,做成一個Component
這樣的好處是你的Activity會比較乾淨,加減Button的Click事件及邏輯在component處理,而不在Activity。

在做單元測試時,也會較方便,單獨針對這個Component測試就好。



新增一個 NumberSelect Layout


這個Layout裡有一個「-」Button、「+」Button、TextView數字

設定custom attributes


在 values 裡新增 attrs.xml ,分別是min_value最小值、max_value最大值、default_value預設值。


在Layout 設定屬性


attrs.xml 這裡設定好了之後,就可直接在layout上設定defaultValue、minValue、maxValue屬性。


建立NumberSelect.java


這段程式有點長,見下方的說明。

在init 裡,取得在layout的min_value、max_value、default_value屬性。



設定addButton、minusButton,加減份數時,異動中間的數值及設定callback



使用custom component


activity_main.xml 加入NumberSelect Custom Component



完整程式


https://github.com/evanchen76/ComponentSample

參考

Custom Components