Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
Web Security TippsNew manual calculation setting in Google Sheets(21.09.2026 um 20:54 Uhr)
Videos & KonferenzenTechquickie: The Steam Frame Shouldn't Work - Here's Why It Does(21.09.2026 um 21:17 Uhr)
Sichere ProgrammierungHow to Build a Production-Ready iOS App With AI-Generated Code(21.09.2026 um 21:00 Uhr)
Sichere ProgrammierungAfriex Integrations: Sandbox, Idempotency, and Webhook Simulation(21.09.2026 um 21:50 Uhr)
Sichere ProgrammierungBridging Local and Cloud Databases for Centralized Data Management(21.09.2026 um 21:51 Uhr)
Web Security TippsNew manual calculation setting in Google Sheets(21.09.2026 um 20:54 Uhr)
Videos & KonferenzenTechquickie: The Steam Frame Shouldn't Work - Here's Why It Does(21.09.2026 um 21:17 Uhr)
Sichere ProgrammierungHow to Build a Production-Ready iOS App With AI-Generated Code(21.09.2026 um 21:00 Uhr)
Sichere ProgrammierungAfriex Integrations: Sandbox, Idempotency, and Webhook Simulation(21.09.2026 um 21:50 Uhr)
Sichere ProgrammierungBridging Local and Cloud Databases for Centralized Data Management(21.09.2026 um 21:51 Uhr)
Intelligence View
⚡ tsecurity.de Intelligence

How to implement two-way data synchronization between the app and the widget?

Read the original article:How to implement two-way data synchronization between the app and the widget? Requirement Description When users add widgets, the data should be in sync between the app and the widget. B…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!

Read the original article:How to implement two-way data synchronization between the app and the widget?






Requirement Description



When users add widgets, the data should be in sync between the app and the widget.






Background Knowledge




  • There may be cases where you want to provide in a widget access to features available in your application running in the foreground, for example, the play, pause, and stop buttons in a music application widget. This is where the call capability of the postCardAction API comes in handy. This capability, when used in a widget, can start the specified UIAbility of the widget provider in the background. It also allows the widget to call the specified method of the application and transfer data so that the application, while in the background, can behave accordingly in response to touching the buttons on the widget.

  • The widget provider can call updateForm to actively update the widget.






Implementation Steps



Step 1: Create an application.



Step 2: Define data models.



Step 3: Implement preferences to store data.



Step 4: Create a widget with dimensions '2*3'



Step 5: Modify MyModeFormAbility to store widget IDs.



Step 6: Modify Entrybility



Step 7: Modify Index.ets to show current mode.



Step 8: Add a widget and see two-way synchronization.






Code Snippet



Step 1: Create an application.



Step 2: Define data models.




  • Mode (Basic enumeration data)




// model/Mode.ets

export enum Mode {
sad,
neutral,
happy
}







  • ModeData and ModeParcelable (For two-way data sync)




// model/ModeParcelable.ets

import { Mode } from "./Mode";
import { rpc } from "@kit.IPCKit";

export interface ModeData {
mode: Mode
}

export class ModeParcelable implements rpc.Parcelable {
mode: Mode

constructor(mode: Mode) {
this.mode = mode
}

marshalling(messageSequence: rpc.MessageSequence): boolean {
messageSequence.writeInt(this.mode)
return true;
}

unmarshalling(messageSequence: rpc.MessageSequence): boolean {
const dataObj: ModeData = JSON.parse(messageSequence.readString())
this.mode = dataObj.mode
return true;
}
}






Step 3: Implement preferences to store data.




  • WidgetIdPrefs (To store widget ids)




// util/WidgetIdPrefs.ets

import { Context } from '@kit.AbilityKit';
import { preferences } from '@kit.ArkData';

export default class WidgetIdPrefs {
static addFormID(context: Context, formID: string) {
console.log('addFormID', formID);
let prefs = preferences.getPreferencesSync(context, { name: 'ids' });
prefs.putSync(formID, formID)
prefs.flushSync()
}

static removeFormID(context: Context, formID: string) {
console.log('removeFormID', formID);
let prefs = preferences.getPreferencesSync(context, { name: 'ids' });
prefs.deleteSync(formID)
prefs.flushSync()
}

static getFormIDs(context: Context): string[] {
console.log('getFormIDs');
let prefs = preferences.getPreferencesSync(context, { name: 'ids' });
return Object.values(prefs.getAllSync())
}
}







  • ModePrefs (to store current mode)




// util/ModePrefs.ets

import { Context } from '@kit.AbilityKit';
import { preferences } from '@kit.ArkData';
import { Mode } from '../model/Mode';

export default class ModePrefs {
static setMode(context: Context, newMode: Mode) {
let prefs = preferences.getPreferencesSync(context, { name: 'mode_data' });
prefs.putSync('mode', newMode)
prefs.flushSync()
}

static getMode(context: Context): Mode {
let prefs = preferences.getPreferencesSync(context, { name: 'mode_data' });
return prefs.getSync('mode', Mode.happy) as Mode
}
}






Step 4: Create a widget with dimensions '2*3' (This can be added to the cards page of the watch) and name it MyMode. For details about how to create a widget, please visit: Creating an ArkTS Widget




  • MyModeCard




// mymode/pages/MyModeCard.ets

import { Mode } from '../../model/Mode'

let ls = new LocalStorage();

@Entry(ls)
@Component
struct MyModeCard {
@LocalStorageProp('mode') mode: Mode = Mode.happy

build() {
Row({ space: 8 }) {
Button('😭')
.fontSize(18)
.backgroundColor(this.mode === Mode.sad ? Color.Red : Color.Grey)
.type(ButtonType.Circle)
.layoutWeight(1)
.onClick(() => {
this.changeMode(Mode.sad)
})
Button('😑')
.fontSize(18)
.backgroundColor(this.mode === Mode.neutral ? Color.Yellow : Color.Grey)
.type(ButtonType.Circle)
.layoutWeight(1)
.onClick(() => {
this.changeMode(Mode.neutral)
})
Button('😊')
.fontSize(18)
.backgroundColor(this.mode === Mode.happy ? Color.Green : Color.Grey)
.type(ButtonType.Circle)
.layoutWeight(1)
.onClick(() => {
this.changeMode(Mode.happy)
})
}
.padding(8)
.height('100%')
.backgroundColor($r('sys.color.comp_background_primary'))
.onClick(() => {
postCardAction(this, {
action: 'router',
abilityName: 'EntryAbility',
});
})
}

changeMode(newMode: Mode) {
if (this.mode !== newMode) {
this.mode = newMode
this.postCardActionCall(newMode)
}
}

// call action to wake app
postCardActionCall(newMode: Mode) {
postCardAction(this, {
action: 'call',
abilityName: 'EntryAbility',
params: {
// function name
method: 'changeMode',
// additional parameters
mode: newMode
}
});
}
}






Step 5: Modify MyModeFormAbility to store widget IDs.




  • MyModeFormAbility




// mymodeformability/MyModeFormAbility.ets

onAddForm(want: Want) {
// Called to return a FormBindingData object.
if (!want || !want.parameters) {
console.error(`FormAbility onAddForm want or want.parameters is undefined`);
return formBindingData.createFormBindingData('');
}

let formId: string = want.parameters[formInfo.FormParam.IDENTITY_KEY] as string;

// store form id
WidgetIdPrefs.addFormID(this.context, formId);
console.log('set form id', formId)

const data: ModeData = { mode: ModePrefs.getMode(this.context) };

// send initial data to the widget
return formBindingData.createFormBindingData(data);
}

onRemoveForm(formId: string) {
// Called to notify the form provider that a specified form has been destroyed.
// remove form id
WidgetIdPrefs.removeFormID(this.context, formId);
}






Step 6: Modify Entrybility




  • to catch the call action.




// entryability/EntryAbility.ets

onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate');

// postCardAction 'call' is caught here
this.callee.on('changeMode', (data: rpc.MessageSequence) => {
// Obtain all parameters passed in the call event.
const dataObj: ModeData = JSON.parse(data.readString())
console.log('ModeData', JSON.stringify(dataObj), dataObj.mode);

AppStorage.set('mode', dataObj.mode)
ModePrefs.setMode(this.context, dataObj.mode);
vibrator.startVibration({ type: 'time', duration: 200 }, { usage: 'physicalFeedback' })
return new ModeParcelable(dataObj.mode);
});
}







  • to store mode in PersistentStorage (to update UI directly)




onWindowStageCreate(windowStage: window.WindowStage): void {
// Main window is created, set main page for this ability
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate');

windowStage.loadContent('pages/Index', (err) => {
if (err.code) {
hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err));
return;
}
hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.');

const mode = ModePrefs.getMode(this.context)
PersistentStorage.persistProp('mode', mode)
AppStorage.set('mode', mode)
});
}






Step 7: Modify Index.ets to show current mode.




  • Index




import { Mode } from '../model/Mode';
import { ModeData } from '../model/ModeParcelable';
import ModePrefs from '../util/ModePrefs';
import WidgetIdPrefs from '../util/WidgetIdPrefs';
import { formBindingData, formProvider } from '@kit.FormKit';


@Entry
@Component
struct Index {
@StorageLink('mode') mode: Mode = ModePrefs.getMode(this.getUIContext().getHostContext() as Context)

build() {
Row({ space: 8 }) {
Button('😭')
.fontSize(18)
.backgroundColor(this.mode === Mode.sad ? Color.Red : Color.Grey)
.type(ButtonType.Circle)
.layoutWeight(1)
.onClick(() => {
this.changeMode(Mode.sad)
})
Button('😑')
.fontSize(18)
.backgroundColor(this.mode === Mode.neutral ? Color.Yellow : Color.Grey)
.type(ButtonType.Circle)
.layoutWeight(1)
.onClick(() => {
this.changeMode(Mode.neutral)
})
Button('😊')
.fontSize(18)
.backgroundColor(this.mode === Mode.happy ? Color.Green : Color.Grey)
.type(ButtonType.Circle)
.layoutWeight(1)
.onClick(() => {
this.changeMode(Mode.happy)
})
}
.padding(8)
.height('100%')
.backgroundColor($r('sys.color.comp_background_primary'))
}

changeMode(newMode: Mode) {
if (this.mode !== newMode) {
this.mode = newMode
ModePrefs.setMode(this.getUIContext().getHostContext() as Context, newMode)
const ids = WidgetIdPrefs.getFormIDs(this.getUIContext().getHostContext() as Context)
// update widgets
ids.forEach((id: string) => {
const data: ModeData = { 'mode': newMode }
let formInfo: formBindingData.FormBindingData = formBindingData.createFormBindingData(data);
formProvider.updateForm(id, formInfo)
})
}
}
}






Step 8: Add a widget and see two-way synchronization.






Written by Mehmet Karaaslan

Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten How to implement two-way data synchronization between the app and the widget?

Thematisch verwandte Begriffe: implement, twoway, data, synchronization · 6 Treffer

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-94497 | jshERP through 3.6 fails to validate object ownership in by-id info, upd…
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel Rechts: nächster Artikel unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick