Android 17 Continue On: 4 APIs to ship cross-device handoff in 2026
Summary. Google released Android 17 on 16 June 2026 as API level 37, with source at AOSP the same day. Its cross-device continuity feature is called Continue On, not Handoff — handoff is the action Continue On performs. It is off by default on every activity, and turning it on takes four APIs: setHandoffEnabled(), onHandoffActivityDataRequested(), HandoffActivityData.Builder, and HandoffActivityData.createWebHandoff(). Extras carried between devices are capped at 50KB and Google's documentation says explicitly not to put credentials or personally identifiable information in them, which under India's Digital Personal Data Protection Act 2023 and its penalties of up to ₹250 crore per violation is a design constraint rather than a style note. Continue On is bidirectional by design but ships supporting mobile-to-tablet first. The same release makes any app launchable as a floating bubble, and removes the large-screen resizability opt-out for apps targeting API 37 across the 580 million large-screen devices Google counts in users' hands.
Two of those facts do most of the work. Off by default means no app gets Continue On for free. And the 50KB extras cap means you are designing a resumption pointer, not a state transfer.
Continue On, not Handoff: getting the vocabulary right
Google's terminology is precise and most secondary coverage gets it wrong. In Google's own documentation, Continue On is the Android 17 feature; the sending device is the one an activity originates from; the receiving device requests a supported app from nearby sending devices; and handoff is the action of transitioning the app and its data between them. There is no class called HandoffApi. The methods live on Activity.
Continue On is designed to work in both directions, so any supported device can send and receive. At launch it supports mobile-to-tablet transitions: the tablet taskbar shows a suggestion for the most recently opened app from the user's phone, giving a one-tap way to pick up where they left off.
Writing about the release on 16 June 2026, Matthew McCullough, VP of Product Management for Android Developer at Google, framed the wider shift this way: "Android 17 marks the start of our transition to an intelligence system, putting your apps at the center." Continue On is the user-visible edge of that, and it is one of the few Android 17 features where a modest amount of code buys a visible product capability.
The four APIs
1. setHandoffEnabled() — opt in, per activity, at the right moment
Support is off by default and implemented per activity. Calling setHandoffEnabled(true, null) marks the current activity as handoff-ready.
class MyHandoffActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Enable handoff
setHandoffEnabled(true, null)
}
override fun onHandoffActivityDataRequested(
handoffRequestInfo: HandoffActivityDataRequestInfo
): HandoffActivityData {
// Create and return handoff data
}
}
The timing warning in the documentation is the part to internalise: once setHandoffEnabled(true) is called, handoff can happen at any point for that activity, so only call it when the activity is genuinely ready to be handed off. An activity mid-way through an unsaved edit, an unconfirmed payment step or a partially loaded list is not ready. isHandoffEnabled() lets you check the current state.
The practical pattern is to enable late and disable around transient states, rather than switching it on in onCreate for every screen and hoping the receiving device figures it out.
2. onHandoffActivityDataRequested() — the callback with no default
If an activity enables handoff, it must also implement onHandoffActivityDataRequested() and return a non-null HandoffActivityData. Google's documentation is explicit that no default behaviour is implemented. Enable without implementing and you have a broken feature, not a degraded one.
The callback receives a HandoffActivityDataRequestInfo, and isActiveRequest() on that object tells you which of two situations you are in. True means the activity is in the foreground and the user has requested to continue on another device. False means the activity has stopped and moved to the background, and the user may request a handoff later.
That distinction is what lets you show a progress affordance on the sending device. The documentation adds a constraint worth reading twice: do not execute that UI code synchronously inside onHandoffActivityDataRequested(). Queue it asynchronously so it cannot block or delay the handoff.
override fun onHandoffActivityDataRequested(
handoffRequestInfo: HandoffActivityDataRequestInfo
): HandoffActivityData {
if (handoffRequestInfo.isActiveRequest()) {
// Queue UI asynchronously - never block this callback
}
val extras = PersistableBundle()
extras.putString("data_id", getDataId())
extras.putInt("scroll_position", getScrollPosition())
return HandoffActivityData.Builder(this)
.setExtras(extras)
.build()
}
3. HandoffActivityData.Builder — a pointer, not a payload
HandoffActivityData tells Continue On how to recreate the activity on the receiving device. It carries two things.
The component name is required: the ComponentName of the activity to launch on the receiving device. For exact replication that is usually the same activity that created the object, and the builder accepts either an Activity or a ComponentName.
Extras are optional, supplied as a PersistableBundle via setExtras(), and included in the start Intent on the receiving side. They must be under 50KB.
That 50KB ceiling is the design decision the API is making for you. It is enough for a document identifier, a scroll offset, a filter selection or a draft key. It is not enough for a document, a decoded image or a cached list. Send identifiers and let the receiving device fetch, and your handoff also survives the case where the receiver already holds newer data than the sender.
Google's warning on the same page is unambiguous: because HandoffActivityData is passed between devices, do not include sensitive or personally identifiable information, user credentials given as the example. Teams shipping in India should treat that as a hard rule rather than guidance, because personal data leaving a device is a processing event under the DPDP Act 2023, where penalties reach ₹250 crore per violation with hard enforcement widely dated to May 2027. A resumption token that resolves server-side against an authenticated session is the pattern that satisfies both the API constraint and the statute.
4. Web fallback and direct-to-web
Two paths exist for when the native app is not the right destination.
setFallbackUri() on the builder sets a URL opened in the user's default browser when the specified activity cannot be started on the receiving device. This is app-to-app handoff with web fallback.
val fallbackWebLink: Uri = Uri.parse("https://myapp.example/fallback?query=$paramVal")
val handoffData = HandoffActivityData.Builder(this)
.setExtras(extras)
.setFallbackUri(fallbackWebLink)
.build()
HandoffActivityData.createWebHandoff() makes the web experience the primary destination.
val webHandoffLink: Uri = Uri.parse("https://myapp.example/handoff?query=$paramVal")
val handoffData = HandoffActivityData.createWebHandoff(webHandoffLink)
The documentation notes that a URL handoff may still be intercepted by the native app on the receiving device if that app can handle the URL intent, which is a third implementation route: prioritise the Android app, fall back to web, and express both with one URL.
| Flow | Builder call | When it fits |
|---|---|---|
| App-to-app | Builder(this).setExtras(...) |
Native app installed on both devices, exact state replication |
| App-to-app with web fallback | .setFallbackUri(uri) |
Native preferred, receiver may not have the app |
| Direct to web | createWebHandoff(uri) |
Web experience is better on the larger screen |
| URL intercepted by native app |
createWebHandoff(uri) plus intent filters |
One URL, native when available, web otherwise |
Receiving the handoff
On the receiving device the activity named in HandoffActivityData gets a normal launch intent carrying the extras. If you handed off to the same activity, read them in onCreate().
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val intent: Intent = getIntent()
if (intent != null && intent.hasExtra("data_id")) {
val dataId: String = intent.getStringExtra("data_id")
// Fetch the record, populate the UI
if (intent.hasExtra("scroll_position")) {
val scrollPosition: Int = intent.getIntExtra("scroll_position", 0)
// Restore the scroll offset
}
}
}
Handle the null and missing-extra cases properly. A handoff that arrives with no extras should still open the app sensibly rather than crashing or showing an empty screen; the receiving device may be running an older app version that does not recognise your keys.
Testing it: the setup nobody documents in a tweet
This is where most teams lose an afternoon. Google's setup and test guide lists the requirements, and they are stricter than a normal feature test.
You need two Pixel devices, one mobile and one tablet, both eligible for and enrolled in the Android Beta for Pixel programme. Both must be signed in to the same Google account for cross-device services. Both must be enrolled in the Cross-Device Services public beta and the Google system services public beta in Play, with the latest versions installed. Bluetooth must be on and both devices must be on the same Wi-Fi network. Then, on both devices, go to Settings, Connected devices, Connection preferences, Cross-device services, Continue activity, tap Set up, allow the requested permissions and enable Tasks.
To run the test, put the tablet into desktop windowing mode, launch your app on the phone and navigate to the activity that enabled Continue On. Your app icon should appear in the right-most spot of the tablet's bottom taskbar with the Continue On suggestion badge. Tapping it launches the activity you designated.
One honest caveat. The Continue On documentation pages were last updated on 14 May 2026 and the setup page still describes API level 37 as "currently in beta", which stopped being true when Android 17 shipped on 16 June 2026. Verify device-eligibility steps against the live pages rather than against a snapshot, ours included.
App Bubbles: the feature you do not implement, only survive
Continue On is opt-in. Bubbles is the opposite, and that asymmetry catches teams out.
In Android 17, a user can long-press any app icon on the launcher to turn that app into a floating bubble, on phones, foldables and tablets. On large screens the taskbar gains a Bubble Bar for organising bubbles and moving them between anchored points. Google's Bubbles guidance states the experience is available to all apps that comply with existing best practices for multi-window support, and that developers should follow the multi-window mode guidelines to make their app work correctly as a bubble.
There is no bubble API to call. Your app is already eligible. If it renders badly in a small floating window, users will see that, and you will not have shipped a line of code to cause it.
The same release adds desktop interactive Picture-in-Picture, where pinned windows stay fully interactive rather than read-only as traditional PiP windows are.
The Android 17 change that forces the work: resizability
Bubbles and Continue On both assume your app handles arbitrary window sizes, and Android 17 removes the escape hatch. For apps targeting API level 37, the platform removes the developer opt-out for orientation and resizability restrictions on large-screen devices with a smallest width above 600 dp. The system ignores screenOrientation, setRequestedOrientation(), resizeableActivity=false and the minAspectRatio and maxAspectRatio constraints. Games, classified by app category in Google Play, remain exempt.
| Android 17 change | Applies to | What breaks if ignored |
|---|---|---|
| Large-screen resizability opt-out removed | Apps targeting API 37, sw > 600 dp | Layouts assuming fixed orientation or aspect ratio |
| Activity recreation defaults changed | All apps on Android 17 | Code relying on a restart to reload resources |
| App memory limits enforced | All apps on Android 17 | Process terminated; ApplicationExitInfo reports "MemoryLimiter:AnonSwap" |
Lock-free MessageQueue
|
Apps targeting SDK 37+ | Reflection on private MessageQueue internals |
static final fields truly final |
Apps targeting SDK 37+ | Reflection throws IllegalAccessException; JNI setters crash |
| Local network access restricted | Apps targeting SDK 37+ | Smart-home and cast discovery without ACCESS_LOCAL_NETWORK
|
Two of those deserve a second look before you plan a Continue On sprint. Activity recreation no longer restarts activities by default for configuration changes that do not need a full UI redraw, including CONFIG_KEYBOARD, CONFIG_KEYBOARD_HIDDEN, CONFIG_NAVIGATION, CONFIG_TOUCHSCREEN and CONFIG_COLOR_MODE; running activities get onConfigurationChanged() instead, and apps that genuinely need the restart must opt in with the new android:recreateOnConfigChanges manifest attribute. And if the memory limiter kills your process, getDescription() on ApplicationExitInfo returns the string "MemoryLimiter:AnonSwap", which is the tell to look for in crash reporting rather than a generic OOM.
One version note that will cost a release if missed: Google states you need CameraX 1.5.2 or 1.6.0 and above to avoid a crash related to an added dynamic range mode on Android 17 devices.
Sequencing a Continue on rollout
Do not start with the handoff code. Start with the window.
Audit resizability first, because Bubbles, desktop PiP and the API 37 large-screen rules all fail in the same place. Our walkthrough of the Android 17 target SDK 37 adaptive layout migration covers that work in detail, and it is the prerequisite here.
Then pick one activity. Continue On is per-activity and there is no benefit to enabling it everywhere at once. Choose the screen where a user genuinely switches devices: a long-form reader, a document editor, a multi-step form, a media player. Instrument it before and after so you can tell whether anyone uses the affordance.
Design the extras payload as identifiers under 50KB, with a version key so an older receiving app can ignore fields it does not understand. Add the fallback URI early rather than as a follow-up, because the receiver-not-installed case is common in real fleets and a fallback URL is a few lines.
Finally, treat the two-device beta setup as a named task with an owner. It is roughly a dozen configuration steps across two devices and two Play beta programmes, and it is the step most likely to make a team conclude the feature is broken when it is not.
India-specific considerations
Two things shape this work for Indian product teams.
The device mix is the first. Continue On's launch configuration is mobile-to-tablet, and the tablet side of the test loop requires Pixel hardware on the Android Beta programme, which is not a common device in Indian offices. Budget for procurement or emulator-based partial testing before committing a delivery date. Android 17 is in beta on partner handsets, tablets and foldables from Honor, iQOO, Lenovo, OnePlus, OPPO, Realme, Sharp, vivo and Xiaomi, so the eventual user base is broad even where the test rig is not.
The data rule is the second, and it is stricter here than the API text implies. Google says not to put sensitive or personally identifiable information in HandoffActivityData. Under the DPDP Act 2023 that line carries statutory weight: personal data moving between devices is processing you have to be able to account for. Send an opaque identifier, resolve it server-side against an authenticated session, and log the resolution rather than the payload. Teams that have already built to our DPDP Act engineering playbook will find the pattern familiar; teams shipping a cross-device feature for the first time usually do not think about it until review.
Beyond that, the adaptive work is where the actual cost sits, and it is the same work that opens up foldables and Googlebooks. If your roadmap already includes foldable and large-screen adaptive development, Continue On is a small increment on top rather than a separate project.
What this fits into
Android 17 also makes Android development Compose-first: all new Android APIs, libraries, tools and developer guidance are built exclusively for Jetpack Compose, and legacy View components in the android.widget package along with View-based Jetpack libraries such as Fragments, RecyclerView and ViewPager are now in maintenance mode receiving only critical bug fixes.
Read together with the resizability enforcement, that sets the direction plainly. An app that is still View-based, fixed-orientation and phone-shaped has three separate reasons to change in this release, and Continue On is the one that pays a visible product dividend for the smallest amount of new code. Do the window work because you have to. Do the handoff work because it is the cheap part. Our enterprise mobile app development guide sets out how that sequencing usually plays out across a portfolio.
How eCorpIT can help
eCorpIT is a Gurugram-based technology consultancy founded in 2021, CMMI Level 5 assessed, MSME certified and ISO 27001:2022 certified, with senior Android engineering teams shipping adaptive apps for Indian and global products. We handle the part that actually takes time: auditing fixed-orientation and aspect-ratio assumptions against the API 37 rules, making layouts behave in a floating bubble and a desktop window, then adding Continue On on the activities where device switching is real. Our Android and Kotlin app development work is designed aligned with DPDP Act 2023 requirements, so the handoff payload carries identifiers rather than personal data. Send us your target SDK and current resizeableActivity posture at /contact-us/ and we will scope the migration before the feature.
FAQ
What is Continue On in Android 17?
Continue On is the Android 17 cross-device continuity feature that lets a user start an activity on one Android device and transition it to another. Handoff is the action Continue On performs. It runs in the background, surfacing available activities from nearby sending devices through entry points such as the receiving device's taskbar.
Which APIs do I need to implement Continue On?
Four are essential. Call setHandoffEnabled() to mark an activity handoff-ready, implement onHandoffActivityDataRequested() so it returns a non-null HandoffActivityData, build that object with HandoffActivityData.Builder, and use HandoffActivityData.createWebHandoff() for direct-to-web handoff. Two supporting checks help: isHandoffEnabled() reports the current state, and isActiveRequest() tells you whether the user has requested a handoff right now.
How much data can Continue On carry between devices?
Extras are supplied as a PersistableBundle through setExtras() and must be less than 50KB. Google's documentation also states that because the data is passed between devices you must not include sensitive or personally identifiable information such as user credentials. Send identifiers and resolve them on the receiving device instead.
What happens if the app is not installed on the receiving device?
Set a fallback URL with setFallbackUri() on the builder. If the designated activity cannot be started on the receiving device, that URL opens in the user's default browser. Alternatively, use createWebHandoff() to make the web experience the primary handoff destination from the start.
What devices does Continue On support?
Continue On is designed to work bidirectionally, so any supported Android device can both send and receive activities. At launch it first supports mobile-to-tablet transitions, where the tablet taskbar shows a suggestion for the most recently opened app from the user's mobile device with a one-tap affordance to resume.
Do I need to write code to support App Bubbles?
No. In Android 17 users can turn any app into a floating bubble by long-pressing its launcher icon, and Google states the experience is available to all apps that comply with existing best practices for multi-window support. There is no bubble API to call; follow the multi-window guidelines so your layout renders correctly.
What changes for apps targeting API level 37?
Android 17 removes the developer opt-out for orientation and resizability restrictions on large-screen devices with smallest width above 600 dp. The system ignores screenOrientation, setRequestedOrientation(), resizeableActivity=false and aspect-ratio constraints. Games, based on Google Play app category, remain exempt from this change.
How do I test Continue On during development?
You need two Android Beta enrolled Pixel devices, one phone and one tablet, on the same Google account and the same Wi-Fi network with Bluetooth on, both enrolled in the Cross-Device Services and Google system services public betas. Enable Continue activity under cross-device services, then test from the tablet in desktop windowing mode.
References
- About the Continue On feature | Android Developers
- Enable and customize cross-device handoff | Android Developers
- Setup and test Continue On | Android Developers
- Android 17 is here | Android Developers Blog, 16 June 2026
- Bubbles | Adaptive Apps | Android Developers
- Support multi-window mode | Adaptive Apps | Android Developers
- HandoffActivityData | Android API reference
- HandoffActivityDataRequestInfo | Android API reference
- Activity | Android API reference
- android:recreateOnConfigChanges | Android API reference
- Adaptive app quality guidelines | Android Developers
- Android is Compose-first | Android Developers
- CameraX releases | Jetpack | Android Developers
- Android Open Source Project
- India's DPDP timeline: critical compliance deadlines for 2026-27 | India Briefing
Last updated: 5 August 2026.
Top comments (0)