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.
- 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.
SOCIAL SHARE CARD GENERATOR