✨ HarmonyOS Hidden Case Revealed! A Hands-on Guide to Mastering Continuation Feature ✨
Hello everyone~ Today I'm going to share a super practical HarmonyOS development tip! I always felt that the official HarmonyOS documentation hid the best examples too deep, but recently I stumbled upon some treasure code about "Application Continuation". I couldn't help but organize it into this dry goods post overnight! This article will use the simplest language + tons of examples to help you easily achieve the magical effect of "switching from phone to tablet without losing your progress"! 🚀
🌟 Why Use Application Continuation?
Imagine these scenarios👇:
- 📱 Browsing Taobao on your phone for half an hour, then switching to a tablet and having to scroll from the top again… (Frustrating!)
- 🎬 Watching a movie halfway, switch device and the progress bar resets to zero… (Crazy!)
- 📖 Reading a web page for 20 screens, switch device and have to find your place again… (Suffocating!)
HarmonyOS's distributed capabilities are here to save you! Today we'll focus on three high-frequency scenarios: long lists, media playback, and web browsing continuation, with complete code and pitfall guides!
🛠️ Environment Preparation
First, make sure your project is configured correctly!
-
Enable continuation in
module.json5(must do!)
{
"module": {
"abilities": [
{
"continuable": true // This line is required!
}
]
}
}
-
Permission application: Add distributed permission in
config.json:
"reqPermissions": [
{
"name": "ohos.permission.DISTRIBUTED_DATASYNC"
}
]
📜 Scenario 1: Long List Continuation (e.g. Shopping Cart List)
Pain Point: Scrolled to item 100, after switching device have to start from the top again?
🔑 Core Code
// 1. Listen to scroll position
Scroll(this.scroller) {
// ...list content
}
.onDidScroll((xOffset, yOffset) => {
// Record current y-axis scroll position
AppStorage.setOrCreate('currentOffset', yOffset);
})
// 2. Source device saves data
async onContinue(wantParam) {
const currentOffset = AppStorage.get('currentOffset') || 0;
const dataObject = distributedDataObject.create(this.context, { currentOffset });
const sessionId = distributedDataObject.genSessionId();
dataObject.setSessionId(sessionId);
wantParam.distributedSessionId = sessionId;
dataObject.save(wantParam.targetDevice);
return AbilityConstant.OnContinueResult.AGREE;
}
// 3. Target device restores data
continueRestore(want) {
const sessionId = want.parameters.distributedSessionId;
const dataObject = distributedDataObject.create(this.context, {});
dataObject.setSessionId(sessionId);
dataObject.on('status', (sessionId, networkId, status) => {
if (status === 'restored') {
// Get previous scroll position
const savedOffset = dataObject['currentOffset'];
this.scroller.scrollTo({ xOffset:0, yOffset:savedOffset });
}
});
}
Pitfall Guide:
- The list component must be wrapped with
Scroll, directly manipulatingListscrolling may not work! - If the list has pagination, remember to also pass the page number parameter!
🎥 Scenario 2: Video Playback Continuation (e.g. Bilibili Device Switch)
Pain Point: Watching at 45 minutes, switch device and the progress bar goes back to the start?
🔑 Core Code
// 1. Listen to playback progress
this.avPlayer.on('timeUpdate', (currentTime) => {
AppStorage.setOrCreate('videoProgress', currentTime);
});
// 2. Save progress (inside onContinue method)
const progress = AppStorage.get('videoProgress') || 0;
const dataObject = distributedDataObject.create(this.context, { progress });
// 3. Restore playback
// Note! Must call seek after video is loaded
this.avPlayer.on('stateChange', (state) => {
if (state === 'playing') {
const savedTime = dataObject['progress'];
this.avPlayer.seek(savedTime); // Jump to recorded time
}
});
Pitfall Guide:
- You must call
seekafter the video enters theplayingstate, otherwise it won't work! - If it's an online video, make sure the target device has the same playback permissions!
🌐 Scenario 3: Web Browsing Continuation (e.g. Zhihu Long Article)
Pain Point: Read 20 screens of a web page, after switching device it goes back to the top?
🔑 Core Code
// 1. Listen to web page scroll
Web({ controller: this.webController })
.onTouch((event) => {
if (event.type === TouchType.Up) {
// Get current scroll position
this.webController.runJavaScript('window.pageYOffset').then((result) => {
AppStorage.setOrCreate('webScrollY', result);
});
}
})
// 2. Save data (inside onContinue method)
const scrollY = AppStorage.get('webScrollY') || 0;
const dataObject = distributedDataObject.create(this.context, { scrollY });
// 3. Restore scroll position
onPageEnd(() => {
const savedY = dataObject['scrollY'];
this.webController.runJavaScript(`window.scrollTo(0, ${savedY})`);
})
Pitfall Guide:
- Some web pages use
document.documentElement.scrollTopinstead ofwindow.pageYOffset - If the web page has dynamic content loading, it's recommended to use element IDs for precise positioning!
💡 Development Tips
-
Debugging Tool: Use
hilogto print distributed data transfer logs:
hilog.info(0x0000, 'DEBUG', 'Current progress: %{public}s', savedOffset);
-
Compatibility Handling: Older devices may not support continuation, remember to add
try-catch! -
Data Compression: If transferring large objects, use
zlibto compress and reduce transfer time!
🚀 Summary
Master these three scenarios and your app will instantly have "seamless switching" superpowers! In fact, HarmonyOS distributed development is much more than this—cross-device clipboard, shared camera and other features are also super fun! If you encounter problems, feel free to shout out in the Huawei Developer Community, lots of experts are online to help~
Final Soul Question: What other "progress lost when switching devices" scenarios have made you want to smash your phone? Share in the comments, maybe the next post will solve your problem! 💥
Interaction Time: If you found this useful, give it a like ❤️ to let me know!
Top comments (0)