Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Code sharing at Transit by Samuel Dionne

Code sharing at Transit by Samuel Dionne

How does Transit go about doing an application available for both Android and iOS. Why we decided to go with native and what hurdles did we ran into while doing it. Should everybody be following our route and if not how to identify that we’re ready for code sharing. We’ll look at different approaches available today to code sharing and how they differ from one another.

1b77dd441f657f5aefb3e21283b252e6?s=128

GDG Montreal

March 28, 2018
Tweet

Transcript

  1. None
  2. None
  3. ➔ All iOS native UI ➔ All iOS native business

    logic ➔ Online API using JSON serving raw data ➔ Offline data implemented with CoreData
  4. ➔ All Android (java) UI ➔ All Android (java) business

    logic ➔ Online API using JSON serving raw data ➔ No Offline capability
  5. ➔ Different issues on both platforms ➔ Same issues on

    both platforms ➔ Not able to port CoreData files to Android ➔ Hard to keep up with new features / cities launch
  6. None
  7. ➔ WebView ➔ Transpiling code ➔ Going native with C++

    ➔ Go home
  8. ➔ Slow app launch ➔ Not a good experience ➔

    Janky animations ➔ Fragmentation ➔ Custom views interaction
  9. ➔ Hard to do threading correctly ➔ StackTrace that doesn’t

    make sense ➔ No good framework available
  10. ➔ It works for games ➔ No need of framework

    ➔ Super easy integration on iOS ➔ Re-use same code on the server ➔ Use battle tested libraries ➔ Custom binary file format
  11. None
  12. None
  13. ➔ You have to do everything in C++ ➔ You

    have to manage pointers ➔ It’s hard to setup ➔ You can’t debug C++ code on Android
  14. None
  15. None
  16. None
  17. ➔ Crossing Java / C++ boundary too often ➔ Caching

    classes and method references ➔ Proguard obfuscating your references ➔ Gradle is rebuilding often
  18. Foo foo = new Foo(); foo.setBar(10); foo.setBaz(“yup”); 1. Foo class

    reference 2. Foo contructor reference 3. Call Foo constructor 4. setBar method reference 5. Call setBar 6. setBaz method reference 7. Create string 8. Call setBaz reference Foo foo = new Foo(10, “yup”); 1. Foo class reference* 2. Foo constructor reference* 3. Create String 4. Call Foo constructor
  19. Foo foo = new Foo(10, “yup”); 1. Foo class reference*

    2. Foo constructor reference* 3. Create String 4. Call Foo constructor
  20. Getting a class reference env->FindClass("mobi/dinoz/Foo") Getting a method reference env->GetMethodID(clazz,

    "setBar", "(I)V");
  21. Before proguard Foo foo = new Foo(); foo.setBar(10); foo.setBaz(“yup”); After

    proguard A a = new A(); a.AA(10); a.AB(“yup”);
  22. Before proguard Foo foo = new Foo(); foo.setBar(10); foo.setBaz(“yup”); After

    proguard A a = new A(); a.AA(10); a.AB(“yup”); env->FindClass("mobi/dinoz/Foo") env->GetMethodID(clazz, "setBar", "(I)V");
  23. ➔ Touching gradle file ➔ Touching CMakeList.txt ➔ Touching a

    .cpp or .h file ➔ Changing branch External tool like CCache helps a lot
  24. None
  25. None
  26. ➔ SmartPointers don’t know about Java ➔ Java object have

    their own lifecycle ➔ Link them together
  27. ➔ SmartPointers don’t know about Java ➔ Java object have

    their own lifecycle ➔ Link them together c++ shared_ptr<CppFoo>* pNew = new shared_ptr<CppFoo>; *pNew = item; jlong cppRef = reinterpret_cast<jlong>(pNew);
  28. java public class Foo { private long cppRef; public Foo(long

    cppRef) { this.cppRef = cppRef; } @Override protected void finalize() { // Call C++ to release the pointer } } ➔ SmartPointers don’t know about Java ➔ Java object have their own lifecycle ➔ Link them together c++ shared_ptr<CppFoo>* pNew = new shared_ptr<CppFoo>; *pNew = item; jlong cppRef = reinterpret_cast<jlong>(pNew);
  29. None
  30. ➔ Lot of business logic on device ➔ Performance requirements

    ➔ Need direct access to: ◆ Audio ◆ Camera ◆ Memory
  31. ➔ Languages ◆ Kotlin ◆ Swift ◆ C++ ◆ JavaScript

    ➔ Frameworks ◆ React Native ◆ Xamarin ➔ Flutter
  32. None