mirror of
https://github.com/openharmony/applications_permission_manager.git
synced 2026-07-01 20:44:13 -04:00
+2
-2
@@ -4,8 +4,8 @@
|
||||
"app": {
|
||||
"bundleName": "com.ohos.permissionmanager",
|
||||
"vendor": "example",
|
||||
"versionCode": 1000080,
|
||||
"versionName": "1.8.0",
|
||||
"versionCode": 1000081,
|
||||
"versionName": "1.8.1",
|
||||
"icon": "$media:app_icon",
|
||||
"label": "$string:app_name",
|
||||
"configuration": "$profile:configuration"
|
||||
|
||||
+2
-2
@@ -16,8 +16,8 @@
|
||||
"app": {
|
||||
"bundleName": "com.ohos.permissionmanager",
|
||||
"vendor": "example",
|
||||
"versionCode": 1000080,
|
||||
"versionName": "1.8.0",
|
||||
"versionCode": 1000081,
|
||||
"versionName": "1.8.1",
|
||||
"icon": "$media:app_icon",
|
||||
"label": "$string:app_name",
|
||||
"configuration": "$profile:configuration"
|
||||
|
||||
@@ -15,14 +15,17 @@
|
||||
|
||||
import extension from '@ohos.app.ability.ServiceExtensionAbility';
|
||||
import window from '@ohos.window';
|
||||
import display from '@ohos.display';
|
||||
import { GlobalContext } from '../common/utils/globalContext';
|
||||
import { Configuration } from '@ohos.app.ability.Configuration';
|
||||
import deviceInfo from '@ohos.deviceInfo';
|
||||
|
||||
const TAG = 'PermissionManager_Log:';
|
||||
const BG_COLOR = '#00000000';
|
||||
|
||||
enum NotifyType {
|
||||
Toast = 1,
|
||||
Dialog = 0
|
||||
}
|
||||
|
||||
export default class SecurityExtensionAbility extends extension {
|
||||
/**
|
||||
* Lifecycle function, called back when a service extension is started for initialization.
|
||||
@@ -41,15 +44,26 @@ export default class SecurityExtensionAbility extends extension {
|
||||
console.info(TAG + 'want: ' + JSON.stringify(want));
|
||||
|
||||
try {
|
||||
let width = want.parameters['ohos.display.width'];
|
||||
let height = want.parameters['ohos.display.height'];
|
||||
let width = want.parameters['ohos.display.width'] ?? 0;
|
||||
let height = want.parameters['ohos.display.height'] ?? 0;
|
||||
let top = want.parameters['ohos.display.top'] ?? 0;
|
||||
let navigationBarRect = {
|
||||
left: 0,
|
||||
top: 0,
|
||||
top: top,
|
||||
width: width,
|
||||
height: height
|
||||
};
|
||||
this.createWindow('SecurityDialog' + startId, window.WindowType.TYPE_DIALOG, navigationBarRect, want);
|
||||
let notifyType = want.parameters['ohos.ability.notify.type'] ?? 0;
|
||||
if (notifyType === NotifyType.Toast) {
|
||||
try {
|
||||
startId > 1 && window.findWindow(`SaveButtonTip${startId - 1}`).destroyWindow();
|
||||
} catch (exception) {
|
||||
console.error(`Failed to find the Window. Cause code: ${exception.code}, message: ${exception.message}`);
|
||||
}
|
||||
this.createToast('SaveButtonTip' + startId, window.WindowType.TYPE_SYSTEM_TOAST, navigationBarRect, want);
|
||||
} else {
|
||||
this.createWindow('SecurityDialog' + startId, window.WindowType.TYPE_DIALOG, navigationBarRect, want);
|
||||
}
|
||||
} catch (exception) {
|
||||
console.error(TAG + 'Failed to obtain the default display object. Code: ' + JSON.stringify(exception));
|
||||
};
|
||||
@@ -98,8 +112,8 @@ export default class SecurityExtensionAbility extends extension {
|
||||
});
|
||||
try {
|
||||
await win.setFollowParentWindowLayoutEnabled(true);
|
||||
} catch(error) {
|
||||
console.error(TAG + `setFollowParentWindowLayoutEnabled error: ${JSON.stringify(error)}`);
|
||||
} catch (error) {
|
||||
console.error(TAG + `setFollowParentWindowLayoutEnabled error: ${JSON.stringify(error)}.`);
|
||||
await win.moveWindowTo(rect.left, rect.top);
|
||||
await win.resize(rect.width, rect.height);
|
||||
};
|
||||
@@ -113,4 +127,22 @@ export default class SecurityExtensionAbility extends extension {
|
||||
console.error(TAG + `window create failed! err: ${JSON.stringify(err)}`);
|
||||
}
|
||||
}
|
||||
|
||||
private async createToast(name: string, windowType, rect, want): Promise<void> {
|
||||
try {
|
||||
const win = await window.createWindow({ ctx: this.context, name, windowType });
|
||||
let property: Record<string, Object> = { 'want': want, 'win': win };
|
||||
let storage: LocalStorage = new LocalStorage(property);
|
||||
await win.moveWindowTo(rect.left, rect.top);
|
||||
await win.resize(rect.width, rect.height);
|
||||
await win.setSystemAvoidAreaEnabled(true);
|
||||
await win.loadContent('pages/securityToast', storage);
|
||||
win.setWindowBackgroundColor(BG_COLOR);
|
||||
await win.setWindowTouchable(false);
|
||||
await win.setWindowFocusable(false);
|
||||
await win.showWindow();
|
||||
} catch (error) {
|
||||
console.error(TAG + `window create failed! err: ${JSON.stringify(error)} `);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -350,4 +350,22 @@ export default class Constants {
|
||||
public static CUSTOMIZE_BUTTON_WIDTH = 152;
|
||||
public static CUSTOMIZE_BUTTON_TEXT_MIN_SIZE = 12;
|
||||
public static CUSTOMIZE_BUTTON_TEXT_MAX_SIZE = 15;
|
||||
|
||||
// SecurityToast
|
||||
public static TOAST_SYMBOLGLYPH_FONTSIZE = 16;
|
||||
public static TOAST_POSITION_Y_UP = 15;
|
||||
public static TOAST_POSITION_Y_UNDER = -15;
|
||||
public static TOAST_ANIMATION_OFFSET = 80;
|
||||
public static TOAST_ANIMATION_TIMEOUT_START = 100;
|
||||
public static TOAST_ANIMATION_TIMEOUT_END = 3100;
|
||||
public static TOAST_ANIMATION_TIMEOUT_ID = 3500;
|
||||
public static TOAST_ICON_FONTSIZE_4 = 4;
|
||||
public static TOAST_ICON_FONTSIZE_2 = 2;
|
||||
public static TOAST_ICON_FONTSIZE_16 = 16;
|
||||
public static TOAST_ICON_FONTSIZE_14 = 14;
|
||||
public static TOAST_MAX_FONT_SCALE = 1;
|
||||
public static TOAST_CONSTRAINT_SIZE_MAX_WIDTH = 400;
|
||||
public static TOAST_CONSTRAINT_SIZE_MIN_HEIGHT = 36;
|
||||
public static TOAST_COLUMN_WIDTH = '100%';
|
||||
public static TOAST_COLUMN_HEIGHT = '100%';
|
||||
}
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import window from '@ohos.window';
|
||||
import display from '@ohos.display';
|
||||
import accessibility from '@ohos.accessibility';
|
||||
import { Log } from '../common/utils/utils';
|
||||
import { DeviceUtil } from '../common/utils/deviceUtil';
|
||||
import Constants from '../common/utils/constant';
|
||||
import { WantInfo } from '../common/model/typedef';
|
||||
|
||||
@Entry({ useSharedStorage: true })
|
||||
@Component
|
||||
struct SecurityToast {
|
||||
@LocalStorageLink('want') want: WantInfo = new WantInfo([]);
|
||||
@LocalStorageLink('win') win: window.Window = {} as window.Window;
|
||||
@State alpha: number = 0;
|
||||
@State positionY: number = 0;
|
||||
@State setPosition: boolean = false;
|
||||
@State setOffset: number = Constants.TOAST_ANIMATION_OFFSET;
|
||||
@State windowWidth: number = 0;
|
||||
@State windowHeight: number = 0;
|
||||
@State rotationInit: number = 0;
|
||||
@State densityDPIInit: number = 0;
|
||||
@State topRectHeight: number = 0;
|
||||
|
||||
getAnnounceForAccessibility() {
|
||||
try {
|
||||
let textAnnounce =
|
||||
this.getUIContext().getHostContext()?.resourceManager.getStringSync($r('app.string.SecurityTitle_mediaFiles')
|
||||
.id);
|
||||
let eventInfo: accessibility.EventInfo = ({
|
||||
type: 'announceForAccessibility',
|
||||
bundleName: 'com.ohos.permissionmanager',
|
||||
triggerAction: 'common',
|
||||
textAnnouncedForAccessibility: textAnnounce
|
||||
});
|
||||
accessibility.sendAccessibilityEvent(eventInfo)
|
||||
.catch((error: Error) => {
|
||||
Log.error(`sendAnnounceForAccessibilityEvent fail: ${error.message}`);
|
||||
return false;
|
||||
});
|
||||
} catch (error) {
|
||||
Log.error(`sendAccessibilityEvent failed, error code: ${error.code}, message: ${error.message}.`);
|
||||
}
|
||||
}
|
||||
|
||||
getWinAvoidArea() {
|
||||
let type = window.AvoidAreaType.TYPE_SYSTEM;
|
||||
let avoidArea = this.win?.getWindowAvoidArea(type);
|
||||
this.topRectHeight = avoidArea.topRect.height;
|
||||
}
|
||||
|
||||
aboutToAppear(): void {
|
||||
Log.info('onAboutToAppear');
|
||||
this.rotationInit = display.getDefaultDisplaySync().orientation;
|
||||
this.densityDPIInit = display.getDefaultDisplaySync().densityDPI;
|
||||
this.setPosition = this.want.parameters['ohos.toast.position'] ?? false;
|
||||
this.positionY = this.setPosition ? Constants.TOAST_POSITION_Y_UP : Constants.TOAST_POSITION_Y_UNDER;
|
||||
this.setOffset = this.want.parameters['ohos.toast.offset'] ?? Constants.TOAST_ANIMATION_OFFSET;
|
||||
this.screenMonitor();
|
||||
this.getWinAvoidArea();
|
||||
let timeoutStart = setTimeout(() => {
|
||||
this.alpha = 1;
|
||||
this.positionY = 0;
|
||||
clearTimeout(timeoutStart);
|
||||
}, Constants.TOAST_ANIMATION_TIMEOUT_START);
|
||||
let timeoutEnd = setTimeout(() => {
|
||||
this.alpha = 0;
|
||||
this.positionY = this.setPosition ? Constants.TOAST_POSITION_Y_UP : Constants.TOAST_POSITION_Y_UNDER;
|
||||
clearTimeout(timeoutEnd);
|
||||
}, Constants.TOAST_ANIMATION_TIMEOUT_END);
|
||||
let timeoutID = setTimeout(() => {
|
||||
this.win?.destroyWindow();
|
||||
clearTimeout(timeoutID);
|
||||
}, Constants.TOAST_ANIMATION_TIMEOUT_ID);
|
||||
}
|
||||
|
||||
aboutToDisappear(): void {
|
||||
try {
|
||||
display.off('foldStatusChange');
|
||||
display.off('change');
|
||||
} catch (exception) {
|
||||
Log.error(`Failed to unregister callback. Cause code: ${exception.code}, message: ${exception.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
screenMonitor() {
|
||||
try {
|
||||
display.on('foldStatusChange', (data: display.FoldStatus) => {
|
||||
Log.info(`Listening enabled. Data: ${JSON.stringify(data)}`);
|
||||
this.win?.destroyWindow();
|
||||
});
|
||||
} catch (exception) {
|
||||
Log.error(`Failed to register callback. Code: ${JSON.stringify(exception)}`);
|
||||
}
|
||||
|
||||
try {
|
||||
display.on('change', (data: number) => {
|
||||
Log.info(`Listening enabled. Data: ${JSON.stringify(data)}`);
|
||||
let rotation: number = display.getDefaultDisplaySync().orientation;
|
||||
let densityDPI = display.getDefaultDisplaySync().densityDPI;
|
||||
if (rotation !== this.rotationInit) {
|
||||
this.rotationInit = rotation;
|
||||
this.win?.destroyWindow();
|
||||
return;
|
||||
}
|
||||
if (this.densityDPIInit !== densityDPI) {
|
||||
this.densityDPIInit = densityDPI;
|
||||
this.win?.destroyWindow();
|
||||
}
|
||||
});
|
||||
} catch (exception) {
|
||||
Log.error(`Failed to register callback. Code: ${JSON.stringify(exception)}`);
|
||||
}
|
||||
}
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
Flex({ alignItems: ItemAlign.Center }) {
|
||||
SymbolGlyph($r('sys.symbol.security_shield'))
|
||||
.maxFontScale(Constants.TOAST_MAX_FONT_SCALE)
|
||||
.minFontScale(Constants.TOAST_MAX_FONT_SCALE)
|
||||
.fontSize(Constants.TOAST_SYMBOLGLYPH_FONTSIZE)
|
||||
.fontColor([$r('sys.color.icon_primary'), $r('sys.color.icon_emphasize')])
|
||||
.renderingStrategy(SymbolRenderingStrategy.MULTIPLE_COLOR)
|
||||
Blank()
|
||||
.width('4vp')
|
||||
Text($r('app.string.SecurityTitle_mediaFiles'))
|
||||
.maxFontScale(Constants.TOAST_MAX_FONT_SCALE)
|
||||
.minFontScale(Constants.TOAST_MAX_FONT_SCALE)
|
||||
.fontSize($r('sys.float.Body_M'))
|
||||
.fontColor($r('sys.color.font_primary'))
|
||||
.onAppear(() => {
|
||||
this.getAnnounceForAccessibility();
|
||||
})
|
||||
}
|
||||
.opacity(this.alpha)
|
||||
.offset({ bottom: this.positionY })
|
||||
.animation({
|
||||
duration: Constants.TOAST_ANIMATION_TIMEOUT_START,
|
||||
curve: 'cubic-bezier(0.2, 0, 0.1, 1)',
|
||||
})
|
||||
.width('auto')
|
||||
.constraintSize({
|
||||
maxWidth: Constants.TOAST_CONSTRAINT_SIZE_MAX_WIDTH,
|
||||
minHeight: Constants.TOAST_CONSTRAINT_SIZE_MIN_HEIGHT
|
||||
})
|
||||
.margin(this.setPosition ? { top: this.setOffset - px2vp(this.topRectHeight) } : { bottom: this.setOffset })
|
||||
.padding(DeviceUtil.isPC() ? $r('sys.float.padding_level4') : {
|
||||
top: Constants.PADDING_8,
|
||||
right: Constants.PADDING_16,
|
||||
bottom: Constants.PADDING_8,
|
||||
left: Constants.PADDING_16
|
||||
})
|
||||
.shadow(DeviceUtil.isPC() ? ShadowStyle.OUTER_DEFAULT_SM : ShadowStyle.OUTER_DEFAULT_MD)
|
||||
.borderRadius(DeviceUtil.isPC() ? $r('sys.float.corner_radius_level4') : $r('sys.float.corner_radius_level9'))
|
||||
.backgroundBlurStyle(DeviceUtil.isPC() ? BlurStyle.COMPONENT_REGULAR : BlurStyle.COMPONENT_ULTRA_THICK)
|
||||
.border(DeviceUtil.isPC() ? { width: '1px', color: '#33ffffff' } : {})
|
||||
.outline(DeviceUtil.isPC() ?
|
||||
{ width: '1px', color: $r('app.color.outline'), radius: $r('sys.float.corner_radius_level4') } : {})
|
||||
}
|
||||
.width(Constants.TOAST_COLUMN_WIDTH)
|
||||
.height(Constants.TOAST_COLUMN_HEIGHT)
|
||||
.justifyContent(this.setPosition ? FlexAlign.Start : FlexAlign.End)
|
||||
.padding({
|
||||
left: (DeviceUtil.isPC() || DeviceUtil.isTablet()) ? Constants.PADDING_24 : Constants.PADDING_16,
|
||||
right: (DeviceUtil.isPC() || DeviceUtil.isTablet()) ? Constants.PADDING_24 : Constants.PADDING_16
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,10 @@
|
||||
{
|
||||
"name": "local_background_color",
|
||||
"value": "#3194F7"
|
||||
},
|
||||
{
|
||||
"name": "outline",
|
||||
"value": "#1A000000"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -10,6 +10,7 @@
|
||||
"pages/dialogPlus",
|
||||
"pages/globalSwitch",
|
||||
"pages/securityDialog",
|
||||
"pages/securityToast",
|
||||
"pages/transition",
|
||||
"PermissionSheet/PermissionStateSheetDialog",
|
||||
"PermissionSheet/GlobalSwitchSheetDialog"
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"color": [
|
||||
{
|
||||
"name": "outline",
|
||||
"value": "#66000000"
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user