Sync on Android

6,182 views
5,944 views

Published on

Talk about standard synchronisation pattern on Android (SyncAdapter + Authenticator + ContentProvider). Presentation given at KrakDroid 2012 (http://www.krakdroid.pl). Video from the talk (in Polish): http://www.youtube.com/watch?v=8Oti4qf7P84.

Published in: Technology

Sync on Android

  1. 1. Sync ON ANDROIDJerzy Chalupskichalupjerzy@futuresimple.com
  2. 2. What we do in general...
  3. 3. What we do ALL THE TIME sync, sync, sync, sync
  4. 4. Sync ON ANDROID OVERVIEW ARCHITECTURECONTENT PROVIDER PITFALLS & PROTIPS
  5. 5. Sync ON ANDROID OVERVIEW ARCHITECTURECONTENT PROVIDER PITFALLS & PROTIPS
  6. 6. Not exactly the fresh topic... „Developing Android REST client applications” by Virgil Dobjanschi @Google I/O 2010
  7. 7. Not exactly the fresh topic... „Synchronizacja danych z serwisami webowymi w Androidzie” by Bartosz Filipowicz @KrakDroid 2011
  8. 8. Not exactly the fresh topic... „Synchronizacja danych z serwisami webowymi w Androidzie” by Bartosz Filipowicz @KrakDroid 2011 ...but there is still much confusion
  9. 9. AccountManager SyncManager UI AuthenticatorContentProvider SyncAdapter ContentResolver
  10. 10. „Wat? Why do I need to writeall this crap, sync is justfetching data from server” typical reaction
  11. 11. Sync provides data sharing
  12. 12. Sync provides data sharing offline mode
  13. 13. Sync provides data sharing offline mode responsive UI
  14. 14. Sync provides data sharing offline mode responsive UI GREAT UX
  15. 15. Sync ON ANDROID OVERVIEW ARCHITECTURECONTENT PROVIDER PITFALLS & PROTIPS
  16. 16. ContentProvider 101: CRUD CREATE insert() READ query() UPDATE update() DELETE delete()
  17. 17. ContentProvider 101: URI content://com.futuresimple.krakdroid.Provider/datasets/1
  18. 18. ContentProvider 101: URI content://com.futuresimple.krakdroid.Provider/datasets/1
  19. 19. ContentProvider 101: URI content://com.futuresimple.krakdroid.Provider/datasets/1
  20. 20. ContentProvider 101: URI content://com.futuresimple.krakdroid.Provider/datasets/1
  21. 21. ContentProvider 101: notifications content://com.futuresimple.krakdroid.Provider/datasets/1 content://com.futuresimple.krakdroid.Provider/solutions content://com.futuresimple.krakdroid.Provider/solutions/1 content://com.futuresimple.krakdroid.Provider/solutions/1/answers/1 content://com.futuresimple.krakdroid.Provider/solutions/1/answers/2 content://com.futuresimple.krakdroid.Provider/solutions/2/answers/1
  22. 22. ContentProvider 101: notifications content://com.futuresimple.krakdroid.Provider/datasets/1 content://com.futuresimple.krakdroid.Provider/solutions content://com.futuresimple.krakdroid.Provider/solutions/1 content://com.futuresimple.krakdroid.Provider/solutions/1/answers/1 content://com.futuresimple.krakdroid.Provider/solutions/1/answers/2 content://com.futuresimple.krakdroid.Provider/solutions/2/answers/1 ContentResolver.notifyChange(“content:// com.futuresimple.krakdroid.Provider/datasets/1”);
  23. 23. ContentProvider 101: notifications content://com.futuresimple.krakdroid.Provider/datasets/1 content://com.futuresimple.krakdroid.Provider/solutions content://com.futuresimple.krakdroid.Provider/solutions/1 content://com.futuresimple.krakdroid.Provider/solutions/1/answers/1 content://com.futuresimple.krakdroid.Provider/solutions/1/answers/2 content://com.futuresimple.krakdroid.Provider/solutions/2/answers/1 ContentResolver.notifyChange(“content:// com.futuresimple.krakdroid.Provider/solutions/1/answers/1”);
  24. 24. Sync ON ANDROID OVERVIEW ARCHITECTURECONTENT PROVIDER PITFALLS & PROTIPS
  25. 25. AccountManager SyncManager UI AuthenticatorContentProvider SyncAdapter ContentResolver
  26. 26. Authenticator Sync architecture CREATING NEW ACCOUNTAccountManager addAccount() UI SyncManager ContentResolver SyncAdapter ContentProvider
  27. 27. Authenticator Sync architecture CREATING NEW ACCOUNT addAccount()AccountManager addAccount() UI SyncManager ContentResolver SyncAdapter ContentProvider
  28. 28. Authenticator Sync architecture CREATING NEW ACCOUNT addAccount()AccountManager addAccount() UI SyncManager ContentResolver SyncAdapter ContentProvider
  29. 29. Authenticator Sync architecture SHOW SYNCED DATAAccountManager UI query() SyncManager ContentResolver query() SyncAdapter ContentProvider
  30. 30. Authenticator Sync architecture REQUEST SYNCAccountManager getAccountsByType() UI SyncManager ContentResolver SyncAdapter ContentProvider
  31. 31. Authenticator Sync architecture REQUEST SYNCAccountManager getAccountsByType() UI requestSync() SyncManager ContentResolver SyncAdapter ContentProvider
  32. 32. Authenticator Sync architecture REQUEST SYNCAccountManager getAccountsByType() UI requestSync() SyncManager ContentResolveronPerformSync() SyncAdapter ContentProvider
  33. 33. Authenticator Sync architecture EDIT DATAAccountManager UI insert() SyncManager ContentResolver insert() SyncAdapter ContentProvider
  34. 34. Authenticator Sync architecture EDIT DATAAccountManager UI insert() SyncManager ContentResolver notifyChange() insert() SyncAdapter ContentProvider
  35. 35. Authenticator Sync architecture EDIT DATAAccountManager UI insert() SyncManager ContentResolver notifyChange() insert() SyncAdapter ContentProvider
  36. 36. Authenticator Sync architecture EDIT DATAAccountManager getAccountsByType() UI insert() SyncManager ContentResolver notifyChange() insert() SyncAdapter ContentProvider
  37. 37. Authenticator Sync architecture EDIT DATAAccountManager getAccountsByType() UI insert() SyncManager ContentResolveronPerformSync() notifyChange() insert() SyncAdapter ContentProvider
  38. 38. Authenticator Sync architecture POST NEW DATAAccountManager UI SyncManager ContentResolveronPerformSync() SyncAdapter ContentProvider
  39. 39. Authenticator Sync architecture POST NEW DATA getAuthToken()AccountManager UI SyncManager ContentResolveronPerformSync() SyncAdapter ContentProvider
  40. 40. Authenticator Sync architecture POST NEW DATA getAuthToken()AccountManager UI SyncManager ContentResolver query()onPerformSync() query() SyncAdapter ContentProvider
  41. 41. Authenticator Sync architecture POST NEW DATA getAuthToken()AccountManager UI SyncManager ContentResolver query()onPerformSync() query() SyncAdapter POST ContentProvider
  42. 42. Authenticator Sync architecture GET NEW DATAAccountManager UI SyncManager ContentResolveronPerformSync() SyncAdapter ContentProvider
  43. 43. Authenticator Sync architecture GET NEW DATA getAuthToken()AccountManager UI SyncManager ContentResolveronPerformSync() SyncAdapter ContentProvider
  44. 44. Authenticator Sync architecture GET NEW DATA getAuthToken()AccountManager UI SyncManager ContentResolveronPerformSync() SyncAdapter GET ContentProvider
  45. 45. Authenticator Sync architecture GET NEW DATA getAuthToken()AccountManager UI SyncManager ContentResolver applyBatch()onPerformSync() applyBatch() SyncAdapter GET ContentProvider
  46. 46. Authenticator Sync architecture GET NEW DATA getAuthToken()AccountManager UI SyncManager ContentResolver applyBatch()onPerformSync() notifyChange() applyBatch() SyncAdapter GET ContentProvider
  47. 47. Authenticator Sync architecture GET NEW DATA getAuthToken()AccountManager onLoaderFinished() UI SyncManager ContentResolver applyBatch()onPerformSync() notifyChange() applyBatch() SyncAdapter GET ContentProvider
  48. 48. Authenticator Sync architecture WIN #1: NO REMOTE I/O IN UIAccountManager UI SyncManager ContentResolver SyncAdapter ContentProvider
  49. 49. Authenticator Sync architecture WIN #2: SYNC SCHEDULINGAccountManager UI SyncManager ContentResolver SyncAdapter ContentProvider
  50. 50. Sync ON ANDROID OVERVIEW ARCHITECTURECONTENT PROVIDER PITFALLS & PROTIPS
  51. 51. IDs in ContentProvider URIs content://com.futuresimple.krakdroid.Provider/datasets/1
  52. 52. IDs in ContentProvider URIs content://com.futuresimple.krakdroid.Provider/datasets/1 Plan A: Use local IDs! (BaseColumns._ID)
  53. 53. IDs in ContentProvider URIs content://com.futuresimple.krakdroid.Provider/datasets/1 Plan A: Use local IDs! (BaseColumns._ID) ISSUE: still need server-side IDs for relations
  54. 54. IDs in ContentProvider URIs content://com.futuresimple.krakdroid.Provider/datasets/1 Plan A: Use local IDs! (BaseColumns._ID) ISSUE: still need server-side IDs for relations ISSUE: conversions between server and local IDs
  55. 55. IDs in ContentProvider URIs content://com.futuresimple.krakdroid.Provider/datasets/15002900 Plan B: OK, use server-side IDs!
  56. 56. IDs in ContentProvider URIs content://com.futuresimple.krakdroid.Provider/datasets/15002900 Plan B: OK, use server-side IDs! ISSUE: what about offline mode?
  57. 57. IDs in ContentProvider URIs content://com.futuresimple.krakdroid.Provider/datasets/-42 content://com.futuresimple.krakdroid.Provider/datasets/15002900 Plan C: OK, let’s mix things up!
  58. 58. IDs in ContentProvider URIs content://com.futuresimple.krakdroid.Provider/datasets/-42 content://com.futuresimple.krakdroid.Provider/datasets/15002900 Plan C: OK, let’s mix things up! ISSUE: very tricky implementation
  59. 59. IDs in ContentProvider URIs content://com.futuresimple.krakdroid.Provider/datasets/GUID Plan D: GUID
  60. 60. IDs in ContentProvider URIs content://com.futuresimple.krakdroid.Provider/datasets/GUID Plan D: GUID ISSUE: needs support on the backend
  61. 61. ContentResolver requestSync() vs. notifyChange() requestSync(account, authority, extras) notifyChange(uri, observer, syncToNetwork)
  62. 62. ContentResolver requestSync() vs. notifyChange() requestSync(account, authority, extras) notifyChange(uri, observer, syncToNetwork)
  63. 63. Deleting an account From your app From system settings From 3rd party app
  64. 64. Deleting an account From your app “Where should I From system settings perform user data cleanup?” From 3rd party app
  65. 65. Deleting an account @Override getAccountRemovalAllowed()
  66. 66. Deleting an account @Override getAccountRemovalAllowed() CONS: depends on current Settings implementation. PROS: exactly the thing you need.
  67. 67. Deleting an account <receiver android:name=".auth.AccountBroadcastReceiver" android:enabled="true" > <intent-filter> <action android:name="android.accounts.LOGIN_ACCOUNTS_CHANGED" /> </intent-filter> </receiver>
  68. 68. Deleting an account <receiver android:name=".auth.AccountBroadcastReceiver" android:enabled="true" > <intent-filter> <action android:name="android.accounts.LOGIN_ACCOUNTS_CHANGED" /> </intent-filter> </receiver> CONS: only info about existing accounts. PROS: peace of mind.
  69. 69. Sync lifecycle Happy case:
  70. 70. Sync lifecycle Happy case: requestSync()
  71. 71. Sync lifecycle Happy case: onPerformSync() requestSync()
  72. 72. Sync lifecycle Happy case: onPerformSync() requestSync() onStatusChanged()
  73. 73. Sync lifecycle Not-so-happy case: onPerformSync() requestSync() onStatusChanged()
  74. 74. Sync lifecycle Not-so-happy case: onPerformSync() requestSync() onStatusChanged()
  75. 75. Sync lifecycle Not-so-happy case: onPerformSync() requestSync() cancelSync() + onStatusChanged()
  76. 76. Futureproof your sync
  77. 77. Futureproof your sync 1. Be lenient on GET
  78. 78. Futureproof your sync 1. Be lenient on GET 2. Be strict on POST
  79. 79. Futureproof your sync 1. Be lenient on GET 2. Be strict on POST 3. Have resync in v1.0
  80. 80. ?
  81. 81. Thanks.

×