M3(批1): 占位桩 + 震动 + 剪贴板 + 系统能力 Provider

T-M3-15 RoomStubProvider/PayStubProvider:createRoom/exitRoom/getVideoinfo/DragViewvideoIsshow、
        paybrowser/getGameplay 全 void 空实现+日志,绝不触发出站(§6.5 安全网)
T-M3-04 VibrateProvider:vibrator/repeatvibrator/canclevibrator(@ohos.vibrator,重复用递归 setTimeout)
T-M3-05 ClipboardProvider:gameCopytext/gamepastetext(@ohos.pasteboard,读取经 responseCallback 回执)
T-M3-01 AppSystemProvider:orientation(window.setPreferredOrientation 横/竖)、browser(隐式 want)、
        finsh(terminateSelf)、openApplyDownloadpath(按包名启动失败回退浏览器)、notification(空)
组装根 buildCapabilities 装配上述 + 桩;module.json5 增 VIBRATE 权限

devecocli build 通过。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
lanterngamescn
2026-06-25 19:15:21 +08:00
parent 4590d5bf70
commit 59b000ce7a
7 changed files with 277 additions and 9 deletions
@@ -0,0 +1,86 @@
/**
* 系统/应用能力(契约 §8.4/§8.8/§8.10T-M3-01)。
* - orientationdata="1" 横屏 / 其他 竖屏(窗口动态切换,§7.4 保留 H5 显式方向控制)。
* - browserdata=URL,隐式 want 拉起系统浏览器。
* - finsh(拼写原样):退出当前 Ability。
* - openApplyDownloadpathdata=JSON{packagename,downloadpath},按包名启动 App,失败则浏览器打开下载地址。
* - notification:空实现(契约标注未落地)。
*/
import { common, Want } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';
import { BridgeController } from 'feature_bridge';
import { InboundHandlers, OpenApplyDownloadReq } from 'contracts';
import { Logger } from 'common';
import { CapabilityContext, CapabilityProvider } from '../core/CapabilityProvider';
export class AppSystemProvider implements CapabilityProvider {
readonly name: string = 'appsystem';
private readonly log: Logger = Logger.tag('AppSystemProvider');
private context: common.UIAbilityContext | undefined = undefined;
register(bridge: BridgeController, ctx: CapabilityContext): void {
this.context = ctx.uiAbilityContext;
bridge.registerHandler(InboundHandlers.Orientation, (data: string, _cb: (resp: string) => void) => {
this.setOrientation(data === '1');
});
bridge.registerHandler(InboundHandlers.Browser, (data: string, _cb: (resp: string) => void) => {
this.openBrowser(data);
});
bridge.registerHandler(InboundHandlers.Finsh, (_d: string, _cb: (resp: string) => void) => {
this.context?.terminateSelf()
.catch((e: BusinessError) => this.log.w(`terminateSelf failed: ${e.code} ${e.message}`));
});
bridge.registerHandler(InboundHandlers.OpenApplyDownloadPath, (data: string, _cb: (resp: string) => void) => {
this.openApply(data);
});
bridge.registerHandler(InboundHandlers.Notification, (_d: string, _cb: (resp: string) => void) => {
// 契约标注:空实现,未落地
});
}
/** 动态设方向:横屏 LANDSCAPE / 竖屏 PORTRAIT(对齐 Android setRequestedOrientation)。 */
private setOrientation(landscape: boolean): void {
const ctx = this.context;
if (ctx === undefined) {
return;
}
const target: window.Orientation = landscape ? window.Orientation.LANDSCAPE : window.Orientation.PORTRAIT;
window.getLastWindow(ctx)
.then((win: window.Window) => win.setPreferredOrientation(target))
.catch((e: BusinessError) => this.log.w(`setOrientation failed: ${e.code} ${e.message}`));
}
private openBrowser(url: string): void {
if (this.context === undefined || url === '') {
return;
}
const want: Want = {
action: 'ohos.want.action.viewData',
entities: ['entity.system.browsable'],
uri: url,
};
this.context.startAbility(want)
.catch((e: BusinessError) => this.log.w(`openBrowser failed: ${e.code} ${e.message}`));
}
private openApply(data: string): void {
const ctx = this.context;
if (ctx === undefined) {
return;
}
let req: OpenApplyDownloadReq;
try {
req = JSON.parse(data) as OpenApplyDownloadReq;
} catch (e) {
this.log.w(`openApply bad json: ${(e as Error).message}`);
return;
}
// 按包名启动 App;失败回退浏览器打开下载地址
ctx.startAbility({ bundleName: req.packagename } as Want)
.catch((e: BusinessError) => {
this.log.i(`start app ${req.packagename} failed (${e.code}); fallback to download page`);
this.openBrowser(req.downloadpath);
});
}
}