2023年3月20日 星期一

Kotlin Multiplatform

 When I was in the Neo bank. What the mobile architecture I designed and participated also used shared lib layer to apply clean architecture. What we chose to is using kmm - kotlin multiplatform. 

 https://docs.google.com/presentation/d/e/2PACX-1vTsuwwY8Q2dFTE39jD_jCKACMNNpwyqIn61FwiwjAyEBFMlB8NTYIFQ2V1hL4AfXrbfbRBj27Xa_2-K/pub?start=false&loop=false&delayms=3000


As the result was great back then. There are advantages as following

1. the model serialization is same to all platforms. There were rarely defect only happened to one platform

2. The business logic also can be written in the same layer and applied the use cases.

3. Reduced the effort of debugging process. 


Cons are
1. Every time you modified the shared lib. Your main app also need to update to the lib version code.

2. Big change to the shared lib will also impact all platforms if there's no dependencies inversion or interface segregation on this shared lib. 

I would recommend enterprise project using this architecture since pros > cons as my prospective. Especially find the defect through the large scale systems wasn't that easy.

2021年10月26日 星期二

Frida, hook your android application.

 initialization

1. https://github.com/sensepost/objection install objection as the instruction.

2. patch your apk https://github.com/sensepost/objection/wiki/Patching-Android-Applications

3. adb install -t your apk

4. once you launch your app, the app will be white black and waiting for the `objection explore`

5. memory search xxxx


hook

https://medium.com/csg-govtech/how-you-should-secure-your-androids-app-biometric-authentication-10d9231215e4


useful command lines

  577  frida -U -f com.dbs.mbanking.tw -l android-keystore-audit/frida-scripts/fingerprint-bypass.js 

  578  adb shell pm path `package name`

  579  adb pull /data/app/~~6ohSJjUoGZa22X_AhKiKxA==/com.dbs.mbanking.tw-W2_ViQB4emAQjMRXvDkcSg==/base.apk

  580  objection patchapk --source base.apk 

  581  adb install -t base.objection.apk 


There's easier way to detect password

1. dump hprof file from your runtime app.

2. grep "keyword" xxx.hprof

you can dump hprof file via Profiler or using some commend line

https://github.com/hydrated/Android-Utilities/blob/master/DumpMemory/log_memory.sh

https://github.com/OWASP/owasp-mstg/blob/master/Document/0x05d-Testing-Data-Storage.md#overview-2

Starting 2021, mstg will scan sensitive data in memory. Either in Jvm or ios environment. The immutable String will be in the heap space and hard to be collected. So what you can do is don't use string to transit it until e2ee. In that case, you need to salting your password in the String instance or passing it always using char array. Here is an example of salting.

https://github.com/hydrated/Android-Utilities/blob/master/ReverseSpannableStringBuilder.java

Dbs MFE

 https://medium.com/dbs-tech-blog/micro-front-ends-the-conflict-terminator-5a447f0428a6

and yes, I am the co-author

2021年9月18日 星期六

Android memory accessibility

Android這十年來跟ios比一直有痛點,就是感覺比較容易crash,除了天生上java遇到null就是crash之外,另一個就是早期Android在設計的時候,針對記憶體存取,設計了一個看起來能讓許多app能跑在android上一個不錯的機制,可惜的是眾多developers並沒有遵守這個原則去開發。就是Activity state。

https://developer.android.com/topic/libraries/architecture/saving-states
https://developer.android.com/guide/components/activities/activity-lifecycle#asem



這個設計的用意是,當app在前景時,記憶體隨你用,當然你用到炸你app一樣crash。只是當你app進背景後,android會幫你保持activity/fragment stack而保持gc的權力,這樣下一個被launch的app依舊有full system的memory可以使用。當user又回到你的app時,整個stack/state馬上被resume。快速的回到你當初app的狀態。


用兩個平台對於進背景的app的不同來解釋這個機制。

ios,進背景後,application被系統回收,下次resume app後就從頭重新launch,一切都是fresh new。

android,進背景後,允許你存資料進state,依照系統對記憶體的需求回收你的activity and fragment,甚至singleton,回來以後只要application還沒被回收,你會被系統重新re-create last state,也就是說你當下在哪一頁系統就幫你把activity, fragment stack全都延續並且顯示最後一頁,如果你用來render UI的data不存在並且你沒有有效的fetch方式,app自然直接crash。所以後期android在某一版後終於也受不了,在系統層直接做了一個保護,當你的app crash後幫你重新launch app,保護了開發者們沒注意到的東西,但還是會有系統上的風險。




說的容易做的難,我本身已經有10+ app開發經驗了,我只能說目前只做了兩個uncrashable android app,剛好也只有這兩個android從0->1開始設計,第一個是幫axiata home pow做的android TV launcher,看起來應該是有個幾百萬使用者以及還在線,但是那個只是硬需。不會crash的方式就是資料全落地,所有的epg, channel, program全都在local資料庫,所有的UI rendering都depend on those data。每一頁都只要簡單的保持uid就能從資料庫中重新fetch當時最後的data,一切都很簡單,一切都很完美,這也是android後期一直在推崇你資料就落地,幾乎大部分的大app也都照做的。

第二個app,很遺憾,那個是neo bank的app,資料落地幾乎是死罪🤣。我也沒想過工作十年後又要回到十年前做的法,資料都得保持在記憶體,哈哈哈。不能用就不能用,那就是回到十年前android一開始的設計,把資料的保持用Saved instance state來作。不得不說真的很痛苦,每一頁activity,每一頁fragment都要寫functions,protocol來連接那個state,非常的unpractical。

好險當時我有七~八個志同道合的隊員,對於這個記憶體的保護很有堅持跟理想,在不斷的sprint遞疊跟演進後,我們發現了viewmodel有個stateviewmodel
https://developer.android.com/topic/libraries/architecture/viewmodel-savedstate

在此應該要先前情提要一下,當時那app是2019年尾開始開發,整個architecture都是用最新的jetpack mvvm,以至於後來這個stateviewmodel出來以後,我們當時每一頁activity,fragment用來保持state的那些functions,protocol全都不用寫了!stateviewmodel他就有能力保持他的記憶體配合Saved instance state,如此一來,拿爛手機的users們,不會轉帳到一半切換到其他app查轉出帳號,回來這個neo bank app後,整個記憶體被回收剛剛輸入過的資料全部規零,甚至crash得重新登入🤣

這就是整個android記憶體的故事了,十年來有著這些的故事,以及我知道目前市面上應該還是大部分的android dev都還不知道這些事情,或者知道了也不知道怎樣的architecture才能有效的解決android記憶體使用的問題。只能怪當初設計android的人太聰明(?)了,導致這十年來沒有太多android dev follow當時他們的想法。

很遺憾這篇不會有implementation detail。

甚至更精采的,可以參考sharedviewmodel,如果你有傳值的煩惱。


Ref.

https://developer.android.com/topic/libraries/architecture/viewmodel-savedstate

https://developer.android.com/topic/libraries/architecture/saving-states

https://developer.android.com/guide/components/activities/activity-lifecycle#asem

2021年1月20日 星期三

Android multiple modular developing

      My previous app was an android banking app. It is a neo bank. And it got tons of features relative to different financial products. I establish the basic architecture with mvvm + navigation component . One activity with fragments. Everything works perfectly thanks for jetpack. Easy to refactor and developing based on this architecture. Also a lot of interesting details with di, motionlayout, paging, navigation, coroutine, viewmodel. Again still work perfectly. 

     What makes this app more special is the multiple modular developing, we manage 8 engineers at the whole time, 10+ with out-source agencies developers. How do we avoid code conflicts and make codes more clear. I introduce the concept of the multiple modular developing. There are some modern software companies are already using them and share their experience on the internet. (#1)

     Basically design your app separated by features. and I believe those features are in 
distinguish UI layer in your app (If you are saying it's not, I serious doubt the UX and everything on that app). For example your app is a tab-layout, each tab represented a feature. Then you can separate your app into different features. The whole launch app was in the App module and each tabs' codes are lying each `Feature #` modules. And move the whole common codes(string res, network, database, utilities..etc) into the bottom layers of modules. So the basic diagram would looks like this.

     



 
     Furthermore as your app growth, the diagram can be designed more and more complicated like this






    There are pros and one con of this developing methods. 

  1. Good for you team members to know where they should focus on and totally ignore other teams simultaneously developing codes.
  2. All the features are reusable, disposable based on requirement. As long as you manager your project dependencies clean and compact. 
  3. Google play now support `Dynamic Feature` based on this architecture, maybe someday your pm has crazy thoughts on this feature.
  4. Test would be easier and single launch is possible if you design and mock it right.
     The con is. As the modules growth, the required build time of android studio takes longer. And there are some methods to avoid this.
  1. Use di to inject blank UI so other modules won't be involved during builds.
  2. Use local maven to store the local build of each modules. They won't be rebuild anymore. Only focus and rebuild on the module you work on.(#2)
     Here I shared a simple app demonstrate such a concept.
https://github.com/hydrated/CurrencySample


Appendix

#2



2020年6月10日 星期三

ViewParentCompat of NestedScrollingParent2 NestedScrollingChild2

日前在做MotionLayout發現example可以輕易的將scrolling event往外傳,然後MotionLayout接收後就自動Parse完畢trigger transition。覺得神奇。

https://github.com/android/views-widgets-samples/blob/master/ConstraintLayoutExamples/motionlayout/src/main/java/com/google/androidstudio/motionlayoutexample/utils/TouchFrameLayout.java


基本上Android開始把可以Scrolling的View用一個叫ViewParentCompat的東西作協調器,然後可以透過viewparentcompat中定義的parent child來互相傳達scrolling event

public class RecyclerView extends ViewGroup implements ScrollingView
        ,NestedScrollingChild2, NestedScrollingChild3 {

從RecyclerView中,是個child的角色,然後自己scrolling時,往外丟出scrolling event

RecyclerView.class
@Overridepublic boolean dispatchNestedPreScroll(int dx, int dy, 
        int[] consumed, int[] offsetInWindow, int type) {

    return getScrollingChildHelper().dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow,            type);}

ViewParentCompat如果是個Parent的角色,自然就會接收到scrolling event

ViewParentCompat.class
if (parent instanceof NestedScrollingParent2) {
    // First try the NestedScrollingParent2 API    
    ((NestedScrollingParent2) parent).onNestedPreScroll(target, dx,
         dy, consumed, type);}


那麼Parent就會收到callback onNestedPreScroll(xxxx
@Overridepublic void onNestedPreScroll(@NonNull View target, int dx,
        int dy, @NonNull int[] consumed, int type) {
    getMotionLayout().onNestedPreScroll(target, dx, dy, 
        consumed, type);}

接著把所有callback event導入MotionLayout,看起來就可以吳鳳接軌。


Beautiful, isn't it.