2018年2月21日 星期三

[Android] 離開App寫法 (Quit App)

問題:我想在Android App裡寫個離開(exit/ quit)功能,該怎麼寫呢?

參考:掘金1掘金2CSDNStackOver1龍崗山上的倉鼠StackOverflow2StackOverflow3DevAndroid1DevAndroid2DevAndroid3DevAndroid4

說明:
首先,Google不建議開發者自己殺掉整個App Process,而是交由系統處理,只要畫面全部finish()即可,而且有在各畫面的onDestroy()處理掉該處裡的東西(Thread、Handler、interface...),這樣gc在整理時應該會順利清除。
甚至建議開發者不要在App裡加離開按鈕。

看來真有人照做,我看LINE、FB、FB Messenger都是在Root Activity(最下層的)時再按返回,就回到桌面,但其實process沒死,點icon再開,不會從啟動畫面(splash screen)進去。但如果從多工鍵(Overview Button)進去滑掉他的Task(這才真的殺掉process),下次就會重啟。

另外,Play商店、GMail、YouTube不管有沒有滑掉,離開再點icon都是從同樣畫面進去,只是這三隻也都沒離開鈕,都是在Root Activity時再按返回,就回到桌面了。


但是,Dev是每個都那麼強嗎?不會少處理造成MemoryLeak而無法回收嗎?
或是說工程師的潔癖就是不要留太多垃圾等打掃阿姨(GC)來收呀 XD

如果,你不聽Google言,一定要做Quit App,就看掘金1掘金2這兩篇選個方法做吧
裡面方法實在太多種了:

簡單說,殺掉process的方式有以下兩種,效果看來一樣..
System.exit(0); 跟 android.os.Process.killProcess(android.os.Process.myPid());
只是在做這件事之前,你要先把Activities關閉,才不會造成重啟。

所以啦,

  • 如果你的Quit()寫在RootActivity,或只有一個Activity,只要把自己finish()然後再exit(0),就好了。
  • 如果你的Quit()寫在非RootActivity也可調用,那你就finish()所有Activities,然後再exit(0)吧。這方法很多,以下推幾種:
    如果你min=API 21+,可以用finishAndRemoveTask();
    如果你min=16+且只有一個Task,可以用finishAffinity();
    如果你min<16或有多個Tasks,那可用List保存Activities法。




2018年2月20日 星期二

[Android] OkHttp3 TLS 1.2 連線寫法

問題:我有WebService連線要用 TLS1.2,那用OkHttp要怎麼寫呢?

參考:OkHttp WikiOkHttp IssuesDevAreaDevAndroid-SSLSocketDevAndroid-SSLContext

說明:
根據DevAndroid-SSLSocket的表格,API16+可支援TLS1.2但不是預設,到API20+才是,那這是甚麼意思呢?

就是說:
  • 你Build.VERSION.SDK_INT<16就完全不能用TLS1.2。
  • 你Build.VERSION.SDK_INT是16~19可以用,但要多寫一些code。
  • 你Build.VERSION.SDK_INT>=20可以用,而且不用多寫code。
有沒有覺得MIN>20好棒呀 XD

那<16的支援方式我就不管了,畢竟現在2018了,新專案還要MIN 15也太低了..


那16~19的寫法簡單說,
  1. 要extends SSLSocketFactory寫一個處理TLS的Factory,叫Tls12SocketFactory 好了,可看OkHttp IssuesDevArea的寫法

  2. 針對Build.VERSION.SDK_INT16~19的要多做以下:
    Tls12SocketFactory tlsSocketFactory = new Tls12SocketFactory(sc.getSocketFactory());
    client.sslSocketFactory(tlsSocketFactory , Platform.get().trustManager(tlsSocketFactory));

    OkHttp Issues中,的client.sslSocketFactory只有第1個參數的寫法已經deprecated了,還是要有第2參數X509TrustManager,可從Factory中取出。

  3. client要再設啥connectionSpecs可再設。
而20+的寫法就是少掉第1、2點即可。


其他關於OkHttp的HTTPS設定,可看OkHttp Wiki



2018年2月6日 星期二

[Android] 2018/2月份 版本分布





  1. 最重要的,API21+破82%了,如果有新App要做,可以考慮min用21(5.0)了,因為5.0才開始原生支援Material Design呀....還有JobScheduler呀...
  2. 另外,API18+破95%了,只是API19+也有94.3%,MIN真不能用21+的就用19+吧 XD
  3. OREO(8.X)升為1.1%,出現在榜單5個月。
  4. 牛軋糖(7.X)+破29%,出現在榜單已16個月了...
  5. 棉花糖(6.X)以下全部下降。
  6. 牛軋糖(7.X)以上持續上升。
  7. 還有5.7%的使用中裝置不能玩PMGO熊大農場



話說,旅行青蛙(旅かえる)只要16+(Android 4.1)就能跑,真的有那麼舊的機器測嗎?

[Android] WebService處理

問題:
我想在App裡處理WebService,跟主機發Http Request(Get/Post),等Response回來,然後parse完結果,秀在UI上,發現有好多工具套件,該怎麼選?

參考:
比較:QuorastromzhangStackOverflow1PacketZoomMediumGetIt01黑客派
分析:SmashingMagzine簡書
教學:CSDN1泡在網上的日子JournalDev綠豆湯DevAndroid1bng86DevAndroid2
GitHub:okHttpVolleyRetrofit

說明:這題有幾個部分要處理喔~

  1. App跟Http主機溝通的元件
  2. UI端跟Http處理元件的溝通
  3. 解析Response回來的結果
這篇就只講"1.App跟Http主機溝通的元件",不然太長了..

先說結論:選OkHttp,如果不喜歡包OkHttp,那就用Volley,完全不喜歡第三方包就HttpURLConnection。

看網路找的結果現在大概會有以下選擇:
  • HttpURLConnection:官方內建元件。
  • OkHttp:Square社製作,網路上大推的元件。
  • Volley:Google社製作,網路上大推的元件。
  • Retorfit:Square社製作,網路上大推的元件。
其實這4個只有前2個是真的Http處理元件,後2個是包裝簡化使用的結果,

如果很早就在寫Android的朋友應該有用過apache的HttpClient,只是它在Android 6.0(API 23)被移除了,所以還在用org.apache.http.legacy的朋友應該可以考慮轉OkHttp,因為Square有做OkHttp Apache HttpClient Implementation,可以減少轉換痛苦。

[更新] HttpClientURLConnection的實作都被OkHttp廢棄(deprecated)了,用舊版應該是可,只是若有BUG沒人修了,原本用法可參考:HttpClient用OKURLConnection用OK
建議使用純okhttp3的寫法囉~

如果喜歡用Volley的,底層連接也可改用okHttp已增進效能,參考簡書這篇,只是看來有點煩。

OkHttp大致上
好處:
壞處:
  • 需額外引入com.squareup.okhttp3:okhttp



複雜的都不想說,有疑問可看參考。

再說一次結論:選OkHttp,如果不喜歡包OkHttp,那就用Volley,完全不喜歡第三方包就HttpURLConnection。

Retorfit的話,建議先用過OkHttp再用會比較理解囉

當然,這四種選哪種都很好查到範例跟資源啦...
而且都能完成GET/POST/HTTPS/憑證綁定(certificate pinning) 等工作...吧 XD

2018年2月5日 星期一

[Android] RecyclerView 分隔線(divider)製作

問題:用RecyclerView做了一個垂直List,但每項中間要加分隔線,要怎麼做?

參考:
DividerItemDecoration法:DevAndroid簡書1StackOverflow1
自己寫ItemDecoration法:StackOverflow2簡書2
拿別人寫好的來用:GitHub1GitHub2GitHub3 (太多,只寫三個,第一個是看簡書有人推的,後兩個是GitHub超過500★的)

說明:
在RecyclerView裡設分隔線的正途是addItemDecoration,在項目的小View Layout裡做分隔線是邪道(雖然比較簡單 XD)

  • 好啦,那之前都要自己繼承ItemDecoration寫實做,有點難懂,但SupportLibV7 25版後加了DividerItemDecoration,如果用API 25版後編App,可以先用這個試試,詳細用法參考DevAndroid簡書1
  • 如果上面的效果不太理想,或自己編版SDK太舊,或想要更活,就自己寫或用別人寫好的ItemDecoration囉~

嘛...我自己試的結果是,用shape當drawable給DividerItemDecoration,粗細跟顏色都能調,只是會加到最後一個item的下方還有線,如果要解這問題,就要自己實作ItemDecoration了(參考StackOverflow2),如不在意那就OK。

[Android] RecyclerView OnItemClick實作

問題:
我想用RecyclerView來做List點項目開新頁,但是沒有內建項目點擊(OnItemClick)事件,怎辦?

參考:
多方法比較派:30Sparks掘金
OnClickListener派:Little RobotsAndroidPubStackOverflowCSDN1CSDN2冰封承諾CSDN3
OnItemTouchListener派:segmentfault木楊

說明:
從參考資料看來,處理點擊項目分為兩大派:OnClickListener派、跟OnItemTouchListener,


OnClickListener派 ─ 寫法比較簡單,但是其中又分好幾支派:
  • 整個RecyclerView傳進一個Support Class處理,在onChildViewAttachedToWindow時加上OnClickLisener,詳見Little Robots
  • 在onBindLoopViewHolder時加上OnClickLisener,最常見的簡單作法,詳見StackOverflowCSDN3
  • 在onCreateViewHolder時加上OnClickLisener,通常是怕Bind觸發太多次,在那處理效能會變低,詳見冰封承諾
  • 在ViewHolder的Constructor(建構子)裡加上OnClickLisener,理由跟上面一樣,而且code在ViewHodler看起來Adapter裡的code會少一點,詳見AndroidPubCSDN1CSDN2


OnItemTouchListener派 ─ 寫法比較複雜,但是會覺得自己用官方介面比較厲害(誤)。

只是這方法要寫兩個class,一個繼承OnItemTouchListener處理項目觸碰事件、另一個繼承SimpleOnGestureListener分析觸碰的手勢是不是點擊(Click),詳見segmentfault木楊


這幾種方法的話,
我還是比較偏好在ViewHolder的Constructor(建構子)裡加上OnClickLisener,因為簡單;
如果要重複使用那我推薦Little Robots的方案


其中,ItemClick事件的傳遞大部分都用interface傳到外面的Fragment或是Activity,只是也找到用RxJava傳的方法,但RxJava這裡還沒寫到,就先跳過囉,有興趣自己Google相關範例。

[Android] ListView vs RecyclerView 垂直單欄簡單表單

問題:
我要做一個垂直的單欄表單,點項目開新頁,該用ListView 還是 RecyclerView做比較好?

參考:DevAndroidAndroidPub簡書StackOverflow1StackOverflow2

說明:

結論先說,RecyclerView是大家都推的方式,雖然有些缺點且較使用複雜,但都可解。但是如果學習時間不夠或不想學習,就用ListView吧...

綜合參考來源,用RecyclerView,只考慮做垂直的單欄表單 (Vertical single column list)的優缺點分列如下:

優(Pros):

  • 強制要求用ViewHolder提高效能,ListView要自己做。
  • 可用DiffUtil做資料集差異更新,ListView要自己做。
  • 內建指定位置項目更新notifyItemChanged,ListView要自己做。
  • 內建局部更新動畫setItemAnimator,ListView要自己做。

缺(Cons):

  • 學習難度較高,因為太活了,要設定較多 = =;。
  • 沒有內建onItemClickListener,RecyclerView要自己做(這個真的希望內建呀..)
  • 沒有內建頭尾項目 HeaderView、FooterView,RecyclerView要自己做。
  • 沒有內建無資料畫面setEmptyView,RecyclerView要自己做。
  • 分隔線(divider)製作較複雜,RecyclerView官方正途方法要用ItemDecoration。
  • 要加入v7包recyclerview項目,如果很討厭引用的話 XD

當然,其他很多人提到的是RecyclerView跟Layout分開,可做直的(Vertical)、橫的(Horizontal)、格子的(Grid)、不對齊的格子(StaggeredGrid),但是太活也是個問題呀 XD
一般同一資料集只會用一種,除非可設定版面變換的。

結論再說一次,RecyclerView是未來寫Android一定會用到的元件,所以能學的時候就學吧,但是拿來做簡單ListView又太麻煩,時間不允許就繼續用ListView,或是上網找找有沒有用RecyclerView做出ListView所有功能實作的包裝範例囉~

關於項目點擊分隔線實作,應該會另外寫一篇,不然太長囉~