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

Quoi de neuf avec Android ?

Quoi de neuf avec Android ?

Mis à jour dans Android 11, les outils, et les bibliothèques

Chuck Greb

June 20, 2020
Tweet

More Decks by Chuck Greb

Other Decks in Technology

Transcript

  1. GDG Location
    GDG Ratoma
    Quoi de neuf avec
    Android ?
    Charles “Chuck” Greb
    Co-lead GDG Ratoma
    @ecgreb

    View Slide

  2. GDG Location
    GDG Ratoma
    Alors … quoi de neuf?
    Quoi de neuf de «Quoi de Neuf avec Android?»
    Android 11
    Outils
    Bibliothèques

    View Slide

  3. GDG Location
    GDG Ratoma
    UI

    View Slide

  4. GDG Location
    GDG Ratoma
    Window Insets
    ● Plus d'informations sur les
    différents types de contenu
    affichés
    ○ Barre d'état, navigation, IME, ...

    View Slide

  5. GDG Location
    GDG Ratoma
    WindowInsets
    // get WindowInsets object from listener
    view.setOnApplyWindowInsetsListener { view, insets ->
    }

    View Slide

  6. GDG Location
    GDG Ratoma
    WindowInsets
    // get WindowInsets object from listener
    view.setOnApplyWindowInsetsListener { view, insets ->
    // See if the IME is visible
    val imeVisible = insets.isVisible((WindowInsets.Type.ime()))
    }

    View Slide

  7. GDG Location
    GDG Ratoma
    WindowInsets
    // get WindowInsets object from listener
    view.setOnApplyWindowInsetsListener { view, insets ->
    // See if the IME is visible
    val imeVisible = insets.isVisible((WindowInsets.Type.ime()))
    if (imeVisible) {
    val imeInsets = insets.getInsets(WindowInsets.Type.ime())
    // ...
    }
    }

    View Slide

  8. GDG Location
    GDG Ratoma
    IME Animations
    ● Synchroniser les animations du
    clavier avec les modifications du
    contenu de l'application
    ○ Écouter les changements
    ■ ET / OU
    ○ Conduire directement
    l'animation du clavier logiciel

    View Slide

  9. GDG Location
    GDG Ratoma
    IME Animations

    View Slide

  10. GDG Location
    GDG Ratoma
    editText.setWindowInsetsAnimationCallback(animCallback)
    val animCallback = object : WindowInsetsAnimation.Callback(DISPATCH_MODE_STOP) {
    override fun onProgress(p0: WindowInsets, p1: MutableList
    ): WindowInsets {
    ...
    }
    // Optional overrides
    override fun onPrepare(animation: WindowInsetsAnimation) { ... }
    override fun onEnd(animation: WindowInsetsAnimation) { ... }
    override fun onStart(animation: WindowInsetsAnimation,
    bounds: WindowInsetsAnimation.Bounds
    ): WindowInsetsAnimation.Bounds { ... }
    }
    IME Animations
    En écoutant des modifications du clavier

    View Slide

  11. GDG Location
    GDG Ratoma
    IME Animations
    editText.windowInsetsController?.
    controlWindowInsetsAnimation(
    WindowInsets.Type.ime(), /* animate the keyboard */
    -1, /* infinite duration */
    linearInterpolator, /* linear motion */
    cancellationSignal, /* allows cancellation */
    animationControlListener /* ready/cancelled/finished */
    )
    Animation directe du clavier

    View Slide

  12. GDG Location
    GDG Ratoma
    WindowInsetsAnimation app:
    goo.gle/insetsanimsample

    View Slide

  13. GDG Location
    GDG Ratoma
    Conversations

    View Slide

  14. GDG Location
    GDG Ratoma
    Conversations
    // Create and post shortcut
    val person = Person.Builder().build()

    View Slide

  15. GDG Location
    GDG Ratoma
    Conversations
    // Create and post shortcut
    val person = Person.Builder().build()
    val shortcutInfo = ShortcutInfoCompat.Builder(this, "sampleShortcut").
    setPerson(person).
    setLongLived(true).
    // ...
    build()

    View Slide

  16. GDG Location
    GDG Ratoma
    Conversations
    // Create and post shortcut
    val person = Person.Builder().build()
    val shortcutInfo = ShortcutInfoCompat.Builder(this, "sampleShortcut").
    setPerson(person).
    setLongLived(true).
    // ...
    build()
    ShortcutManagerCompat.pushDynamicShortcut(shortcutInfo)

    View Slide

  17. GDG Location
    GDG Ratoma
    Conversations
    // Create and post shortcut
    val person = Person.Builder().build()
    val shortcutInfo = ShortcutInfoCompat.Builder(this, "sampleShortcut").
    setPerson(person).
    setLongLived(true).
    // ...
    build()
    ShortcutManagerCompat.pushDynamicShortcut(shortcutInfo)
    // Create notification with shortcut
    val style = NotificationCompat.MessagingStyle(person).
    addMessage(...).
    // ...

    View Slide

  18. GDG Location
    GDG Ratoma
    Conversations
    // Create and post shortcut
    val person = Person.Builder().build()
    val shortcutInfo = ShortcutInfoCompat.Builder(this, "sampleShortcut").
    setPerson(person).
    setLongLived(true).
    // ...
    build()
    ShortcutManagerCompat.pushDynamicShortcut(shortcutInfo)
    // Create notification with shortcut
    val style = NotificationCompat.MessagingStyle(person).
    addMessage(...).
    // ...
    NotificationCompat.Builder(this, "foo").
    setShortcutId(shortcutInfo.id).
    // ...
    build()

    View Slide

  19. GDG Location
    GDG Ratoma
    Bubbles

    View Slide

  20. GDG Location
    GDG Ratoma
    Bubbles
    ● Notifications qui peuvent s'afficher comme
    des bulles
    ● Android 10 : Option de développeur
    ○ Android 11 : Elles sont arrivées
    ● Meilleur que System Alert Window!
    ● Créé avec Notification API
    ○ avec plus de metadata
    ○ et son propre Activity

    View Slide

  21. GDG Location
    GDG Ratoma
    Bubbles : Manifest
    Manifest:
    android:name=".bubbles.BubbleActivity"
    android:theme="@style/AppTheme.NoActionBar"
    android:label="@string/title_activity_bubble"
    android:resizeableActivity="true"
    />

    View Slide

  22. GDG Location
    GDG Ratoma
    Bubbles : Code
    // Create Intent to launch
    val intent = Intent(context, BubbleActivity::class.java)
    val bubbleIntent = PendingIntent.getActivity(context, 0, intent,...)

    View Slide

  23. GDG Location
    GDG Ratoma
    Bubbles : Code
    // Create Intent to launch
    val intent = Intent(context, BubbleActivity::class.java)
    val bubbleIntent = PendingIntent.getActivity(context, 0, intent,...)
    // Create metadata
    val shortcutInfo = ... /* probably already using for notifications */
    val bubbleMetadata = Notification.BubbleMetadata.Builder(shortcutInfo.id)

    View Slide

  24. GDG Location
    GDG Ratoma
    Bubbles : Code
    // Create Intent to launch
    val intent = Intent(context, BubbleActivity::class.java)
    val bubbleIntent = PendingIntent.getActivity(context, 0, intent,...)
    // Create metadata
    val shortcutInfo = ... /* probably already using for notifications */
    val bubbleMetadata = Notification.BubbleMetadata.Builder(shortcutInfo.id)
    // Create Notification with metadata
    val builder: Notification.Builder =
    Notification.Builder(context, CHANNEL_ID)
    // ...
    .setBubbleMetadata(bubbleMetadata)
    .setCategory(...)
    .setShortcutId(...)

    View Slide

  25. GDG Location
    GDG Ratoma
    Quoi de neuf avec System UI
    Android Samples on Github:
    user-interface-samples/ BubblesKotlin
    140: Bubbles!

    View Slide

  26. GDG Location
    GDG Ratoma
    Privacy
    Android 11 enables state of the art privacy and
    security features, protecting users and their data
    from access by malicious apps, while
    simultaneously making access of that data more
    transparent to the user.

    View Slide

  27. GDG Location
    GDG Ratoma
    Data Access Auditing
    • Listen for when user-permission-required
    data is accessed
    • Great for large apps or use of external
    libraries

    View Slide

  28. GDG Location
    GDG Ratoma
    ● Callbacks invoqués lors de l'accès
    aux données protégé par des
    permissions d’utilisateur
    Data Access Auditing

    View Slide

  29. GDG Location
    GDG Ratoma
    Data Access Auditing
    val appOpsCallback = object : AppOpsManager.OnOpNotedCallback() {
    override fun onNoted(syncNotedAppOp: SyncNotedAppOp) { ... }
    override fun onSelfNoted(syncNotedAppOp: SyncNotedAppOp) { ... }
    override fun onAsyncNoted(asyncNotedAppOp: AsyncNotedAppOp) { ... }
    }

    View Slide

  30. GDG Location
    GDG Ratoma
    Data Access Auditing
    val appOpsCallback = object : AppOpsManager.OnOpNotedCallback() {
    override fun onNoted(syncNotedAppOp: SyncNotedAppOp) { ... }
    override fun onSelfNoted(syncNotedAppOp: SyncNotedAppOp) { ... }
    override fun onAsyncNoted(asyncNotedAppOp: AsyncNotedAppOp) { ... }
    }
    val appOpsManager =
    getSystemService(AppOpsManager::class.java) as AppOpsManager
    appOpsManager.setOnOpNotedCallback(mainExecutor, appOpsCallback)

    View Slide

  31. GDG Location
    GDG Ratoma
    One-Time Permissions

    View Slide

  32. GDG Location
    GDG Ratoma
    ● Plus restrictif dans Android 11
    ● D’abord, demandez la permission de premier plan
    ● Puis demandez la permission d'arrière-plan
    ○ L’utilisateur arrive à Settings
    Background Location

    View Slide

  33. GDG Location
    GDG Ratoma
    • Android 10 : l'attribut de manifest Location
    était obligatoire
    • Android 11 : les nouveaux attributs de
    manifest sont obligatoire
    ○ Camera
    ○ Microphone
    Foreground Services

    View Slide

  34. GDG Location
    GDG Ratoma
    Foreground Service Type

    ...

    ...

    View Slide

  35. GDG Location
    GDG Ratoma
    But Wait, There’s More!
    ● Restrictions sur la visibilité des packages
    ● Scoped storage
    ● Auto-reset permissions

    View Slide

  36. GDG Location
    GDG Ratoma
    Developer Goodies

    View Slide

  37. GDG Location
    GDG Ratoma
    Wi-Fi Debugging
    Parce qu'il n'y a jamais assez de ports USB

    View Slide

  38. GDG Location
    GDG Ratoma
    Wi-Fi Debugging
    Parce qu'il n'y a jamais assez de ports USB

    View Slide

  39. GDG Location
    GDG Ratoma
    Nullability
    Annotations
    ● @RecentlyNullable, @RecentlyNonNull
    ○ Warnings
    ● @Nullable, @NonNull
    ○ Errors

    View Slide

  40. GDG Location
    GDG Ratoma
    Crash Reasons
    Reporting
    ● API a interroger pourquoi l’appli s'est
    plantée
    ○ télécharger les rapports

    View Slide

  41. GDG Location
    GDG Ratoma
    Crash Reasons Querying
    // Returns List of ApplicationExitInfo
    val reasonsList = activityManager.getHistoricalProcessExitReasons(
    packageName, pid /* 0 for all matches */, max /* 0 for all */)

    View Slide

  42. GDG Location
    GDG Ratoma
    Crash Reasons Querying
    // Returns List of ApplicationExitInfo
    val reasonsList = activityManager.getHistoricalProcessExitReasons(
    packageName, pid /* 0 for all matches */, max /* 0 for all */)
    for (info in reasonsList) {
    // Log/store/upload info.reason
    // REASON_LOW_MEMORY, REASON_CRASH, REASON_ANR, etc.
    }

    View Slide

  43. GDG Location
    GDG Ratoma
    ● Android 10 : HWASan
    ○ Memory issue debugging
    ● GWP-ASan
    ○ Catches memory issues (for native apps)
    ○ On user devices in the field
    ○ Low overhead (runtime and memory)
    ○ Reports uploaded to Play dashboard
    GWP-ASan

    View Slide

  44. GDG Location
    GDG Ratoma
    GWP-ASan

    ...

    View Slide

  45. GDG Location
    GDG Ratoma
    GWP-ASan

    ...

    // Bad memory access caught by GWP-ASan triggers exit + report
    *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
    Build fingerprint: 'google/sargo/sargo:10/RPP3.200320.009/6360804:userdebug/dev-keys'
    Revision: 'PVT1.0'
    ABI: 'arm64'
    Timestamp: 2020-04-06 18:27:08-0700
    pid: 16227, tid: 16227, name: 11.test.gwpasan >>> android11.test.gwpasan <<<
    uid: 10238
    signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 0x736ad4afe0
    Cause: [GWP-ASan]: Use After Free on a 32-byte allocation at 0x736ad4afe0
    backtrace:
    #00 pc 000000000037a090 /apex/com.android.art/lib64/libart.so (art::(anonymous namespace)::ScopedCheck::CheckNonHeapValue(char, art::(anonymous namespace)::JniValueType)+448)
    #01 pc 0000000000378440 /apex/com.android.art/lib64/libart.so (art::(anonymous namespace)::ScopedCheck::CheckPossibleHeapValue(art::ScopedObjectAccess&, char, art::(anonymous namespace)::JniValueType)+204)
    #02 pc 0000000000377bec /apex/com.android.art/lib64/libart.so (art::(anonymous namespace)::ScopedCheck::Check(art::ScopedObjectAccess&, bool, char const*, art::(anonymous namespace)::JniValueType*)+612)
    #03 pc 000000000036dcf4 /apex/com.android.art/lib64/libart.so (art::(anonymous namespace)::CheckJNI::NewStringUTF(_JNIEnv*, char const*)+708)
    #04 pc 000000000000eda4 /data/app/android11.test.gwpasan/lib/arm64/libmy-test.so (_JNIEnv::NewStringUTF(char const*)+40)
    #05 pc 000000000000eab8 /data/app/android11.test.gwpasan/lib/arm64/libmy-test.so (native_get_string(_JNIEnv*)+144)
    #06 pc 000000000000edf8 /data/app/android11.test.gwpasan/lib/arm64/libmy-test.so (Java_android11_test_gwpasan_MainActivity_nativeGetString+44)
    ...
    deallocated by thread 16227:
    #00 pc 0000000000048970 /apex/com.android.runtime/lib64/bionic/libc.so (gwp_asan::AllocationMetadata::CallSiteInfo::RecordBacktrace(unsigned long (*)(unsigned long*, unsigned long))+80)
    #01 pc 0000000000048f30 /apex/com.android.runtime/lib64/bionic/libc.so (gwp_asan::GuardedPoolAllocator::deallocate(void*)+184)
    #02 pc 000000000000f130 /data/app/android11.test.gwpasan/lib/arm64/libmy-test.so (std::__ndk1::_DeallocateCaller::__do_call(void*)+20)
    ...
    #08 pc 000000000000ed6c /data/app/android11.test.gwpasan/lib/arm64/libmy-test.so (std::__ndk1::basic_string, std::__ndk1::allocator >::~basic_string()+100)
    #09 pc 000000000000ea90 /data/app/android11.test.gwpasan/lib/arm64/libmy-test.so (native_get_string(_JNIEnv*)+104)
    #10 pc 000000000000edf8 /data/app/android11.test.gwpasan/lib/arm64/libmy-test.so (Java_android11_test_gwpasan_MainActivity_nativeGetString+44)
    ...
    allocated by thread 16227:
    #00 pc 0000000000048970 /apex/com.android.runtime/lib64/bionic/libc.so (gwp_asan::AllocationMetadata::CallSiteInfo::RecordBacktrace(unsigned long (*)(unsigned long*, unsigned long))+80)
    #01 pc 0000000000048e4c /apex/com.android.runtime/lib64/bionic/libc.so (gwp_asan::GuardedPoolAllocator::allocate(unsigned long)+368)
    #02 pc 000000000003b258 /apex/com.android.runtime/lib64/bionic/libc.so (gwp_asan_malloc(unsigned long)+132)
    #03 pc 000000000003bbec /apex/com.android.runtime/lib64/bionic/libc.so (malloc+76)
    #04 pc 0000000000010414 /data/app/android11.test.gwpasan/lib/arm64/libmy-test.so (operator new(unsigned long)+24)
    ...
    #10 pc 000000000000ea6c /data/app/android11.test.gwpasan/lib/arm64/libmy-test.so (native_get_string(_JNIEnv*)+68)
    #11 pc 000000000000edf8 /data/app/android11.test.gwpasan/lib/arm64/libmy-test.so (Java_android11_test_gwpasan_MainActivity_nativeGetString+44)
    ...

    View Slide

  46. GDG Location
    GDG Ratoma
    ADB Incremental
    ● Installations plus rapides via command-line
    ● APKs énorme (i.e. games)
    ○ Jusqu'à 10x faster

    View Slide

  47. GDG Location
    GDG Ratoma
    ADB Incremental
    // First: sign APK, create APK Signature Scheme v4 file
    // Then, run ADB incremental
    $ adb install --incremental

    View Slide

  48. GDG Location
    GDG Ratoma
    Changements de
    fonctionnement
    ● La plupart de changements sont
    limités a targetSdk R
    ● Essayez les changements avec les
    bascules de fonctionnement
    ○ Command-line
    ○ Nouveau panneau de Développeur
    Options

    View Slide

  49. GDG Location
    GDG Ratoma
    Toggling Behavior Changes
    // adb shell am compat (enable|disable) (CHANGE_ID|CHANGE_NAME) \
    PACKAGE_NAME
    $ adb shell am compat disable DEFAULT_SCOPED_STORAGE \
    com.android.samples.android11playground

    View Slide

  50. GDG Location
    GDG Ratoma
    L’infographie & médias

    View Slide

  51. GDG Location
    GDG Ratoma
    NDK Image Decoders
    ● All decoders available from native
    code
    ○ JPEG, GIF, PNG, WebP, …
    ● No more
    ○ JNI up-calling
    ○ Bundling decoder libraries
    ○ Bulking APK size

    View Slide

  52. GDG Location
    GDG Ratoma
    /* Create a decoder. */
    AImageDecoder* decoder = nullptr;
    AImageDecoder_createFromAAsset(assetDescriptor, &decoder);
    NDK ImageDecoder

    View Slide

  53. GDG Location
    GDG Ratoma
    /* Create a decoder. */
    AImageDecoder* decoder = nullptr;
    AImageDecoder_createFromAAsset(assetDescriptor, &decoder);
    /* Set up the target format */
    AImageDecoder_setAndroidBitmapFormat(decoder, ANDROID_BITMAP_FORMAT_RGBA_8888);
    NDK ImageDecoder

    View Slide

  54. GDG Location
    GDG Ratoma
    /* Create a decoder. */
    AImageDecoder* decoder = nullptr;
    AImageDecoder_createFromAAsset(assetDescriptor, &decoder);
    /* Set up the target format */
    AImageDecoder_setAndroidBitmapFormat(decoder, ANDROID_BITMAP_FORMAT_RGBA_8888);
    /* Create a buffer for the decoded image */
    const AImageDecoderHeaderInfo* headerInfo = AImageDecoder_getHeaderInfo(decoder);
    int32_t height = AImageDecoderHeaderInfo_getHeight(headerInfo);
    size_t stride = AImageDecoder_getMinimumStride(decoder);
    std::vector bits (height * stride);
    NDK ImageDecoder

    View Slide

  55. GDG Location
    GDG Ratoma
    NDK ImageDecoder
    /* Create a decoder. */
    AImageDecoder* decoder = nullptr;
    AImageDecoder_createFromAAsset(assetDescriptor, &decoder);
    /* Set up the target format. */
    AImageDecoder_setAndroidBitmapFormat(decoder, ANDROID_BITMAP_FORMAT_RGBA_8888);
    /* Create a buffer for the decoded image */
    const AImageDecoderHeaderInfo* headerInfo = AImageDecoder_getHeaderInfo(decoder);
    int32_t height = AImageDecoderHeaderInfo_getHeight(headerInfo);
    size_t stride = AImageDecoder_getMinimumStride(decoder);
    std::vector bits (height * stride);
    /* Decode! */
    AImageDecoder_decodeImage(decoder, bits.data(), stride, bits.size());
    github.com/android/ndk-samples

    View Slide

  56. GDG Location
    GDG Ratoma
    Animated HEIF
    ● Chargez des images animées à partir
    de fichiers HEIF
    ● AnimatedImageDrawable
    ○ Comme GIFs animées
    ○ Mais plus petites !

    View Slide

  57. GDG Location
    GDG Ratoma
    Animated HEIFs
    val file = File("someHeifFile")
    val source = ImageDecoder.createSource(file)

    View Slide

  58. GDG Location
    GDG Ratoma
    Animated HEIFs
    val file = File(“someHeifFile”)
    val source = ImageDecoder.createSource(file)
    // Perform off main thread
    val drawable = ImageDecoder.decodeDrawable(source);
    if (drawable is AnimatedImageDrawable) {
    drawable.start()
    }

    View Slide

  59. GDG Location
    GDG Ratoma
    NDK: OpenSL ES
    @Deprecated
    ● Oboe for the win !
    ● Unbundled C++ library
    ○ High-performance audio
    ○ Works back to API 16
    ○ Open source
    github.com/google/oboe

    View Slide

  60. GDG Location
    GDG Ratoma
    135: Audio Podcast

    View Slide

  61. GDG Location
    GDG Ratoma
    Variable refresh rate
    ● For apps with their own rendering loop
    ○ e.g., games
    ● 60 frames per second used to be a given
    ○ Now some devices support 90, 120 Hz
    ○ Enables more flexible backoff rates
    ● Surface.setFrameRate()
    120
    fps
    60

    View Slide

  62. GDG Location
    GDG Ratoma
    NDK Thermal API
    ● Monitor device thermal status change
    ○ React to thermal issues
    ● No need for JNI up-calls

    View Slide

  63. GDG Location
    GDG Ratoma
    NDK Thermal API
    // Create a thermal listener
    void nativeThermalListener(void *appCtx, AThermalStatus status) {
    ...
    switch (status) {
    case ATHERMAL_STATUS_SHUTDOWN:
    ...
    case ATHERMAL_STATUS_EMERGENCY:
    ...
    case ATHERMAL_STATUS_CRITICAL:
    ...
    ...
    }
    }

    View Slide

  64. GDG Location
    GDG Ratoma
    NDK Thermal API
    // Create a thermal listener
    void nativeThermalListener(void *appCtx, AThermalStatus status) {
    ...
    switch (status) {
    case ATHERMAL_STATUS_SHUTDOWN:
    ...
    case ATHERMAL_STATUS_EMERGENCY:
    ...
    case ATHERMAL_STATUS_CRITICAL:
    ...
    ...
    }
    }
    // Register the listener
    AThermalManager *manager = AThermal_acquireManager();
    AThermal_registerThermalStatusListener(manager, NativeThermalListener, appCtx);

    View Slide

  65. GDG Location
    GDG Ratoma
    NDK Thermal API
    // Create a thermal listener
    void nativeThermalListener(void *appCtx, AThermalStatus status) {
    ...
    switch (status) {
    case ATHERMAL_STATUS_SHUTDOWN:
    ...
    case ATHERMAL_STATUS_EMERGENCY:
    ...
    case ATHERMAL_STATUS_CRITICAL:
    ...
    ...
    }
    }
    // Register the listener
    AThermalManager *manager = AThermal_acquireManager();
    AThermal_registerThermalStatusListener(manager, NativeThermalListener, appCtx);
    // ...
    AThermal_unregisterThermalStatusListener(manager, nativeThermalListener, appCtx);
    AThermal_releaseManager(manager);

    View Slide

  66. GDG Location
    GDG Ratoma
    But Wait, There’s More!

    View Slide

  67. GDG Location
    GDG Ratoma
    NNAPI v1.3
    ● New operations
    ○ IF, WHILE, QUANTIZED_LSTM,
    HARD_SWISH
    ● New quantization scheme
    GPU DSP NPU
    Graphics
    Processing
    Unit
    Digital Signal
    Processor
    Neural
    Processing
    Unit
    ● New advanced execution control
    ○ Fenced compute
    ○ Memory domain input/output
    ○ Quality of Service(QoS)

    View Slide

  68. GDG Location
    GDG Ratoma
    5G
    ● APIs to optimize 5G experience
    ○ Metered network state
    ○ Bandwidth estimates

    View Slide

  69. GDG Location
    GDG Ratoma
    5G
    val manager = getSystemService(ConnectivityManager::class.java)
    manager.registerDefaultNetworkCallback(object: ConnectivityManager.NetworkCallback() {
    override fun onCapabilitiesChanged(network: Network,
    capabilities: NetworkCapabilities) {
    if (capabilities.hasCapability(
    NetworkCapabilities.NET_CAPABILITY_NOT_METERED)) {...}
    ...
    if (capabilities.linkDownstreamBandwidthKbps > FAST_NETWORK) {...}
    }
    })

    View Slide

  70. GDG Location
    GDG Ratoma
    Biometric authenticator strength

    View Slide

  71. GDG Location
    GDG Ratoma
    Biometric authenticator strength
    val manager: BiometricManager? = getSystemService(BiometricManager::class.java)
    val strength = BiometricManager.Authenticators.BIOMETRIC_STRONG
    if (manager?.canAuthenticate(strength) != BiometricManager.BIOMETRIC_SUCCESS) {
    // Takes user to enroll biometrics security.
    val intent = Intent(Settings.ACTION_BIOMETRIC_ENROLL)
    intent.putExtra(Settings.EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED, strength)
    startActivity(intent)
    } else {
    // Authenticate user!
    }

    View Slide

  72. GDG Location
    GDG Ratoma
    L'intégration d’autofill au clavier
    ● Voir autofill contenu dans le clavier
    ○ Claviers logiciels
    ○ Les applis de mot de passe
    ● Sécurité - le clavier obtient l’UI a présenter les données,
    mais pas les données eux-même

    View Slide

  73. GDG Location
    GDG Ratoma
    Autofill

    View Slide

  74. GDG Location
    GDG Ratoma
    Autofill : Keyboards
    // Implement InputMethodService methods
    // Autofill request from IME
    override fun onCreateInlineSuggestionsRequest(uiExtras: Bundle):
    InlineSuggestionsRequest? {
    // ...
    }

    View Slide

  75. GDG Location
    GDG Ratoma
    Autofill : Keyboards
    // Implement InputMethodService methods
    // Autofill request from IME
    override fun onCreateInlineSuggestionsRequest(uiExtras: Bundle):
    InlineSuggestionsRequest? {
    // ...
    }
    // Autofill response
    override fun onInlineSuggestionsResponse(response: InlineSuggestionsResponse):
    Boolean {
    // ...
    }

    View Slide

  76. GDG Location
    GDG Ratoma
    Autofill : Password Apps
    // AutofillServices handle onFillRequest(), create FillResponse with InlinePresentation
    override fun onFillRequest(...) {
    }

    View Slide

  77. GDG Location
    GDG Ratoma
    Autofill : Password Apps
    // AutofillServices handle onFillRequest(), create FillResponse with InlinePresentation
    override fun onFillRequest(...) {
    val datasetBuilder = Dataset.Builder()
    val inlinePresentation = InlinePresentation(...)
    datasetBuilder.setValue(..., inlinePresentation, ...)
    }

    View Slide

  78. GDG Location
    GDG Ratoma
    Autofill : Password Apps
    // AutofillServices handle onFillRequest(), create FillResponse with InlinePresentation
    override fun onFillRequest(...) {
    val datasetBuilder = Dataset.Builder()
    val inlinePresentation = InlinePresentation(...)
    datasetBuilder.setValue(..., inlinePresentation, ...)
    responseBuilder = FillResponse.Builder()
    val fillResponse = responseBuilder.addDataset(datasetBuilder.build()).
    // ...
    .build()
    // ...
    }

    View Slide

  79. GDG Location
    GDG Ratoma
    Non-Platform

    View Slide

  80. GDG Location
    GDG Ratoma
    Jetpack
    ● 70+ bibliothèques
    ● mises à jour chaque deux semaines
    ● Neuf / récent
    ○ Hilt: Dependency injection (Dagger)
    ○ Paging 3.0: Tout Kotlin, avec coroutines
    ○ CameraX Beta
    ○ … et plus !

    View Slide

  81. GDG Location
    GDG Ratoma
    Jetpack Compose
    ● Nouvelle UI Toolkit pour Android
    ● Reactive, Kotlin-based
    ● Pre-alpha, développé en plein air (open source)

    View Slide

  82. GDG Location
    GDG Ratoma
    Android Studio
    ● 4.0 : Stable
    ○ Motion Editor
    ○ LayoutInspector
    ● 4.1 : Beta
    ○ Database Inspector (Room, SQLite)
    ● 4.2 : Canary
    ○ Wireless debugging with Android 11
    ○ Jetpack Compose development

    View Slide

  83. GDG Location
    GDG Ratoma
    Google Play
    ● Nouvelle Play console : complètement repensé
    ○ plus claire, plus facile à utiliser
    ○ policy status section
    ○ acquisition reports
    ○ team management
    ● Maintenant en Beta
    ○ play.google.com/console

    View Slide

  84. GDG Location
    GDG Ratoma
    Plus d’informations
    Launch videos goo.gle/android11

    View Slide

  85. GDG Location
    GDG Ratoma
    Plus d’informations
    Launch videos
    11 Weeks of Android
    goo.gle/android11
    d.android.com/11weeksofandroid

    View Slide

  86. GDG Location
    GDG Ratoma
    Plus d’informations
    Launch videos
    11 Weeks of Android
    Android 11 Meetups
    goo.gle/android11
    d.android.com/11weeksofandroid
    d.android.com/android11/meetups

    View Slide

  87. GDG Location
    GDG Ratoma
    Plus d’informations
    Launch videos
    11 Weeks of Android
    Android 11 Meetups
    Now in Android
    goo.gle/android11
    d.android.com/11weeksofandroid
    d.android.com/android11/meetups
    articles: medium.com/androiddevelopers/tagged/now-in-android
    videos: youtube.com/androiddevelopers
    podcast: nowinandroid.googledevelopers.libsynpro.com/

    View Slide

  88. GDG Location
    GDG Ratoma
    Merci !

    View Slide