Extended
Singapore
Preparing apps for
Android Q
Saurabh Arora, Rakuten Viki
@saurabh_arora90
Where are we?
➢ Decade of Android (10.0)
➢ Beta 4
➢ Final API’s
➢ API Level 29
Extended
Singapore
What's New
Privacy & User
Security Experience
Extended
Singapore
Privacy & Security
Background Activity Starts
➢ Affects - All apps running on Q (irrespective of target SDK)
➢ Exceptions:
○ Bound services such as accessibility, auto-fill, etc.
○ Receives a PendingIntent from system
○ App had SYSTEM_ALERT_WINDOW permission
○ App called finish() on activity very recently
➢ Recommended approach - Notification Triggered activity
val notificationBuilder = NotificationCompat.Builder(this, CHANNEL_ID)
....
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_CALL)
val fullScreenIntent = Intent(this, CallActivity::class.java)
val fullScreenPendingIntent = PendingIntent.getActivity(this, 0,
fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT)
val notificationBuilder = NotificationCompat.Builder(this, CHANNEL_ID)
....
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_CALL)
.setFullScreenIntent(fullScreenPendingIntent, true)
➢ Gotcha’s:
○ System decides b/w notification & activity
■ Notification - User using the device
■ Activity - Device Idle / when user interacts with notification
○ Declare USE_FULL_SCREEN_INTENT permission
Hardware Identifiers
➢ Affects - All apps running on Q (irrespective of target SDK)
○ Exception thrown if Target SDK is Q
○ null returned if Target SDK < Q
➢ Avoid:
○ IMEI - TelephonyManager.getDeviceId()
○ Mac Address
○ ANDROID_ID - Settings.Secure.ANDROID_ID
Hardware Identifiers
➢ Alternatives
○ Advertising ID
○ Instance ID - FirebaseInstanceId
○ Globally-unique IDs (GUIDs) - UUID.randomUUID().toString()
Background Location
➢ Distinguish b/w foreground &
background
➢ Location permission has 3 options
Background Location Requests
➢ Affects - Depends
Background Location Requests
➢ Foreground Service
➢ Background Service
<service
android:name="MyNavigationService"
android:foregroundServiceType="location" ... >
...
</service>
<manifest>
<uses-permission
android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission
android:name="android.permission.ACCESS_BACKGROUND_LOCATION"
/>
</manifest>
ActivityCompat.requestPermissions(this,
arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_BACKGROUND_LOCATION),
your-permission-request-code
➢ Gotcha’s:
○ System schedules reminders
○ User can revoke permission
○ Always check access
Extended
Singapore
User Experiences
Settings Panel
➢ Bottom sheet for system settings
➢ Encourage app engagement
➢ Currently Supported:
○ ACTION_INTERNET_CONNECTIVITY
○ ACTION_WIFI
○ ACTION_NFC
○ ACTION_VOLUME
➢ AndroidX wrapper
Gesture Navigation
Gesture Navigation
➢ Affects - All apps running on Q (irrespective of target SDK)
➢ Recommended approach
○ Draw Edge to Edge
○ Override system gestures
➢ Draw Behind Navigation Bar
➢ Draw behind Status bar
➢ Strongly recommended
<style name="AppTheme">
......
<item name="android:navigationBarColor">
@android:color/transparent
</item>
</style>
view.systemUiVisibility =
//Layout as if the navigation bar was hidden
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
or
//Layout as if the status bar was hidden
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
or
//Layout at its most extreme
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
➢ Overlap with system UI?
➢ Use insets
○ WindowInsets
root.setOnApplyWindowInsetsListener { _, insets ->
val fabLp = fab.layoutParams as
CoordinatorLayout.LayoutParams
fabLp.bottomMargin = fabOriginalBottomMargin +
insets.systemWindowInsetBottom
fab.layoutParams = fabLp
insets.consumeSystemWindowInsets()
}
➢ System Window Insets
➢ Clickable Views
➢ System Gesture Insets
○ New in Android Q
➢ Draggable Views
Insets.getSystemGestureInsets()
root.setOnApplyWindowInsetsListener { _, insets ->
val systemGestureInsets = insets.systemGestureInsets
top.layoutParams = top.layoutParams.apply {
height = systemGestureInsets.top
}
bottom.layoutParams = bottom.layoutParams.apply {
height = systemGestureInsets.bottom
}
....
}
➢ Override system gestures
➢ App gets touch event first
View.setSystemGestureExclusionRects(List<Rect> rects)
➢ Gotcha’s:
○ Seekar & Drawer Layout work of the box
○ Can opt out back gesture
○ Home is reserved
WindowInsets.getMandatorySystemGestureInsets()
Dark Mode
Dark Mode
➢ A new System Setting
○ Under Settings->Display->Theme
○ A Quick tile
○ Battery Saver Mode
➢ Supported by 1.1 App Compat
<!--App Compat Style-->
<style name="AppTheme" parent="Theme.AppCompat.DayNight">
<!--Material Components-->
<style name="AppTheme"
parent="Theme.MaterialComponents.DayNight">
<!--values/themes.xml-->
<style name="Theme.AppCompat.DayNight"
parent="Theme.AppCompat.Light">
<!--values-night/themes.xml-->
<style name="Theme.AppCompat.DayNight"
parent="Theme.AppCompat">
Dark Mode
➢ AppCompatDelegate.setDefaultNightMode()
○ MODE_NIGHT_YES
○ MODE_NIGHT_NO
○ MODE_NIGHT_FOLLOW_SYSTEM
○ MODE_NIGHT_AUTO_BATTERY
➢ Gotcha’s
<ConstraintLayout ....
background="#ABABAB">
<TextView ....
textColor="#FFFFFF">
<ConstraintLayout ....
background="@color/foo">
<TextView ....
textColor="@color/bar">
<!--values/colors.xml-->
<color name="foo">#ABABAB</color>
<ConstraintLayout ....
background="@color/foo">
<TextView ....
textColor="@color/bar">
<!--values/colors.xml-->
<color name="foo">#ABABAB</color>
<!--values-night/colors.xml-->
<color name="foo">#FAFAFA</color>
➢ Gotcha’s:
○ Check drawables and provide night resources
○ Vectors tint
<vector....
android:tint="?attr/textColorNormal"/>
➢ Gotcha’s:
○ Test RemoteViews
○ Configuration Change - uiMode
■ UI will lose context if not handled properly
■ Caution single orientation apps
■ Media apps should handle to continue playback
Extended
Singapore
Not Covered
➢ Sharing improvements
➢ Audio Playback Capture
➢ Bubbles
➢ Sharing improvements
➢ Audio Playback Capture
➢ Bubbles
➢ Non SDK Interfaces
Extended
Singapore
Thank Q
Questions?