MDM demo
This commit is contained in:
12
.gitignore
vendored
Normal file
12
.gitignore
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
/node_modules
|
||||
/oh_modules
|
||||
/local.properties
|
||||
/.idea
|
||||
**/build
|
||||
/.hvigor
|
||||
.cxx
|
||||
/.clangd
|
||||
/.clang-format
|
||||
/.clang-tidy
|
||||
**/.test
|
||||
/.appanalyzer
|
||||
10
AppScope/app.json5
Normal file
10
AppScope/app.json5
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"app": {
|
||||
"bundleName": "com.yylx.huawei.goyimdm",
|
||||
"vendor": "example",
|
||||
"versionCode": 1000000,
|
||||
"versionName": "1.0.0",
|
||||
"icon": "$media:layered_image",
|
||||
"label": "$string:app_name"
|
||||
}
|
||||
}
|
||||
8
AppScope/resources/base/element/string.json
Normal file
8
AppScope/resources/base/element/string.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "app_name",
|
||||
"value": "MDM相机控制器"
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
AppScope/resources/base/media/background.png
Normal file
BIN
AppScope/resources/base/media/background.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 90 KiB |
BIN
AppScope/resources/base/media/foreground.png
Normal file
BIN
AppScope/resources/base/media/foreground.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
7
AppScope/resources/base/media/layered_image.json
Normal file
7
AppScope/resources/base/media/layered_image.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"layered-image":
|
||||
{
|
||||
"background" : "$media:background",
|
||||
"foreground" : "$media:foreground"
|
||||
}
|
||||
}
|
||||
82
MDM配置说明.md
Normal file
82
MDM配置说明.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# MDM应用配置说明
|
||||
|
||||
## 概述
|
||||
|
||||
此应用是一个OpenHarmony MDM(移动设备管理)应用,用于控制设备相机功能。为了使MDM功能正常工作,需要进行特殊的签名配置。
|
||||
|
||||
## 配置步骤
|
||||
|
||||
### 1. 注册成为企业开发者
|
||||
|
||||
1. 访问[华为开发者联盟](https://developer.huawei.com/)官网
|
||||
2. 注册并认证为企业开发者
|
||||
|
||||
### 2. 创建项目和应用
|
||||
|
||||
1. 登录AppGallery Connect
|
||||
2. 创建新项目
|
||||
3. 在项目中创建应用
|
||||
4. 记录应用的包名(Bundle Name)
|
||||
|
||||
### 3. 申请MDM证书和Profile
|
||||
|
||||
1. 在AppGallery Connect中进入"用户与访问"->"设备管理"->"证书与Profile"
|
||||
2. 申请MDM证书
|
||||
3. 创建Profile文件,并添加以下权限:
|
||||
- `ohos.permission.ENTERPRISE_MANAGE_RESTRICTIONS`
|
||||
- `ohos.permission.MANAGE_ENTERPRISE_DEVICE_ADMIN`
|
||||
- `ohos.permission.ENTERPRISE_GET_DEVICE_INFO`
|
||||
|
||||
### 4. 配置开发环境签名
|
||||
|
||||
在DevEco Studio中配置签名:
|
||||
|
||||
1. 打开项目后,选择菜单 "File" -> "Project Structure"
|
||||
2. 在左侧面板选择 "Project"
|
||||
3. 在右侧面板中找到 "Signing Configs"
|
||||
4. 选择 "Automatically generate signature" 选项
|
||||
5. 点击 "Apply" 保存配置
|
||||
|
||||
### 5. 修改应用包名
|
||||
|
||||
MDM应用需要使用特定的包名格式,通常以企业域名开头。修改[module.json5](file:///Users/yuangyaa/workfiles/huawei/easyMDM/entry/src/main/module.json5)中的`bundleName`字段:
|
||||
|
||||
```json
|
||||
{
|
||||
"app": {
|
||||
"bundleName": "com.yourcompany.mdmapp",
|
||||
// ... 其他配置
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 重要注意事项
|
||||
|
||||
1. MDM应用只能安装在企业设备上,不能在普通消费者设备上运行
|
||||
2. MDM功能需要设备管理权限激活后才能使用
|
||||
3. 签名配置是必需的,否则MDM功能将无法正常工作
|
||||
4. 应用需要通过hdc命令激活设备管理权限进行测试
|
||||
|
||||
## 测试说明
|
||||
|
||||
在开发环境中测试MDM功能需要:
|
||||
|
||||
1. 使用hdc命令激活设备管理权限:
|
||||
```
|
||||
hdc shell bm enable-admin -n com.yourcompany.mdmapp/.EnterpriseAdminAbility
|
||||
```
|
||||
|
||||
2. 使用hdc命令解除激活:
|
||||
```
|
||||
hdc shell bm disable-admin -n com.yourcompany.mdmapp/.EnterpriseAdminAbility
|
||||
```
|
||||
|
||||
## 常见问题
|
||||
|
||||
### 1. 编译时出现权限错误
|
||||
|
||||
确保在[module.json5](file:///Users/yuangyaa/workfiles/huawei/easyMDM/entry/src/main/module.json5)中声明了所有必需的MDM权限,并且这些权限已在Profile中配置。
|
||||
|
||||
### 2. 运行时无法控制设备功能
|
||||
|
||||
确保应用已被正确激活为设备管理器,并且设备支持MDM功能。
|
||||
42
build-profile.json5
Normal file
42
build-profile.json5
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"app": {
|
||||
"signingConfigs": [],
|
||||
"products": [
|
||||
{
|
||||
"name": "default",
|
||||
"signingConfig": "default",
|
||||
"targetSdkVersion": "6.0.0(20)",
|
||||
"compatibleSdkVersion": "6.0.0(20)",
|
||||
"runtimeOS": "HarmonyOS",
|
||||
"buildOption": {
|
||||
"strictMode": {
|
||||
"caseSensitiveCheck": true,
|
||||
"useNormalizedOHMUrl": true
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"buildModeSet": [
|
||||
{
|
||||
"name": "debug",
|
||||
},
|
||||
{
|
||||
"name": "release"
|
||||
}
|
||||
]
|
||||
},
|
||||
"modules": [
|
||||
{
|
||||
"name": "entry",
|
||||
"srcPath": "./entry",
|
||||
"targets": [
|
||||
{
|
||||
"name": "default",
|
||||
"applyToProducts": [
|
||||
"default"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
32
code-linter.json5
Normal file
32
code-linter.json5
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"files": [
|
||||
"**/*.ets"
|
||||
],
|
||||
"ignore": [
|
||||
"**/src/ohosTest/**/*",
|
||||
"**/src/test/**/*",
|
||||
"**/src/mock/**/*",
|
||||
"**/node_modules/**/*",
|
||||
"**/oh_modules/**/*",
|
||||
"**/build/**/*",
|
||||
"**/.preview/**/*"
|
||||
],
|
||||
"ruleSet": [
|
||||
"plugin:@performance/recommended",
|
||||
"plugin:@typescript-eslint/recommended"
|
||||
],
|
||||
"rules": {
|
||||
"@security/no-unsafe-aes": "error",
|
||||
"@security/no-unsafe-hash": "error",
|
||||
"@security/no-unsafe-mac": "warn",
|
||||
"@security/no-unsafe-dh": "error",
|
||||
"@security/no-unsafe-dsa": "error",
|
||||
"@security/no-unsafe-ecdsa": "error",
|
||||
"@security/no-unsafe-rsa-encrypt": "error",
|
||||
"@security/no-unsafe-rsa-sign": "error",
|
||||
"@security/no-unsafe-rsa-key": "error",
|
||||
"@security/no-unsafe-dsa-key": "error",
|
||||
"@security/no-unsafe-dh-key": "error",
|
||||
"@security/no-unsafe-3des": "error"
|
||||
}
|
||||
}
|
||||
6
entry/.gitignore
vendored
Normal file
6
entry/.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
/node_modules
|
||||
/oh_modules
|
||||
/.preview
|
||||
/build
|
||||
/.cxx
|
||||
/.test
|
||||
33
entry/build-profile.json5
Normal file
33
entry/build-profile.json5
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"apiType": "stageMode",
|
||||
"buildOption": {
|
||||
"resOptions": {
|
||||
"copyCodeResource": {
|
||||
"enable": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"buildOptionSet": [
|
||||
{
|
||||
"name": "release",
|
||||
"arkOptions": {
|
||||
"obfuscation": {
|
||||
"ruleOptions": {
|
||||
"enable": false,
|
||||
"files": [
|
||||
"./obfuscation-rules.txt"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
],
|
||||
"targets": [
|
||||
{
|
||||
"name": "default"
|
||||
},
|
||||
{
|
||||
"name": "ohosTest",
|
||||
}
|
||||
]
|
||||
}
|
||||
6
entry/hvigorfile.ts
Normal file
6
entry/hvigorfile.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { hapTasks } from '@ohos/hvigor-ohos-plugin';
|
||||
|
||||
export default {
|
||||
system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
|
||||
plugins: [] /* Custom plugin to extend the functionality of Hvigor. */
|
||||
}
|
||||
23
entry/obfuscation-rules.txt
Normal file
23
entry/obfuscation-rules.txt
Normal file
@@ -0,0 +1,23 @@
|
||||
# Define project specific obfuscation rules here.
|
||||
# You can include the obfuscation configuration files in the current module's build-profile.json5.
|
||||
#
|
||||
# For more details, see
|
||||
# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5
|
||||
|
||||
# Obfuscation options:
|
||||
# -disable-obfuscation: disable all obfuscations
|
||||
# -enable-property-obfuscation: obfuscate the property names
|
||||
# -enable-toplevel-obfuscation: obfuscate the names in the global scope
|
||||
# -compact: remove unnecessary blank spaces and all line feeds
|
||||
# -remove-log: remove all console.* statements
|
||||
# -print-namecache: print the name cache that contains the mapping from the old names to new names
|
||||
# -apply-namecache: reuse the given cache file
|
||||
|
||||
# Keep options:
|
||||
# -keep-property-name: specifies property names that you want to keep
|
||||
# -keep-global-name: specifies names that you want to keep in the global scope
|
||||
|
||||
-enable-property-obfuscation
|
||||
-enable-toplevel-obfuscation
|
||||
-enable-filename-obfuscation
|
||||
-enable-export-obfuscation
|
||||
10
entry/oh-package.json5
Normal file
10
entry/oh-package.json5
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "entry",
|
||||
"version": "1.0.0",
|
||||
"description": "Please describe the basic information.",
|
||||
"main": "",
|
||||
"author": "",
|
||||
"license": "",
|
||||
"dependencies": {}
|
||||
}
|
||||
|
||||
48
entry/src/main/ets/entryability/EntryAbility.ets
Normal file
48
entry/src/main/ets/entryability/EntryAbility.ets
Normal file
@@ -0,0 +1,48 @@
|
||||
import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit';
|
||||
import { hilog } from '@kit.PerformanceAnalysisKit';
|
||||
import { window } from '@kit.ArkUI';
|
||||
|
||||
const DOMAIN = 0x0000;
|
||||
|
||||
export default class EntryAbility extends UIAbility {
|
||||
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
|
||||
try {
|
||||
this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
|
||||
} catch (err) {
|
||||
hilog.error(DOMAIN, 'testTag', 'Failed to set colorMode. Cause: %{public}s', JSON.stringify(err));
|
||||
}
|
||||
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate');
|
||||
}
|
||||
|
||||
onDestroy(): void {
|
||||
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy');
|
||||
}
|
||||
|
||||
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.');
|
||||
});
|
||||
}
|
||||
|
||||
onWindowStageDestroy(): void {
|
||||
// Main window is destroyed, release UI related resources
|
||||
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
|
||||
}
|
||||
|
||||
onForeground(): void {
|
||||
// Ability has brought to foreground
|
||||
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground');
|
||||
}
|
||||
|
||||
onBackground(): void {
|
||||
// Ability has back to background
|
||||
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground');
|
||||
}
|
||||
}
|
||||
16
entry/src/main/ets/entrybackupability/EntryBackupAbility.ets
Normal file
16
entry/src/main/ets/entrybackupability/EntryBackupAbility.ets
Normal file
@@ -0,0 +1,16 @@
|
||||
import { hilog } from '@kit.PerformanceAnalysisKit';
|
||||
import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit';
|
||||
|
||||
const DOMAIN = 0x0000;
|
||||
|
||||
export default class EntryBackupAbility extends BackupExtensionAbility {
|
||||
async onBackup() {
|
||||
hilog.info(DOMAIN, 'testTag', 'onBackup ok');
|
||||
await Promise.resolve();
|
||||
}
|
||||
|
||||
async onRestore(bundleVersion: BundleVersion) {
|
||||
hilog.info(DOMAIN, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion));
|
||||
await Promise.resolve();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
import { EnterpriseAdminExtensionAbility } from '@kit.MDMKit';
|
||||
import { Want } from '@kit.AbilityKit';
|
||||
import { restrictions } from '@kit.MDMKit';
|
||||
|
||||
export default class EnterpriseAdminAbility extends EnterpriseAdminExtensionAbility {
|
||||
// 设备管理应用激活回调方法,应用可在此回调函数中进行初始化策略设置
|
||||
onAdminEnabled(): void {
|
||||
console.info("onAdminEnabled");
|
||||
try {
|
||||
// 默认启用相机限制功能(即禁用相机)
|
||||
// 注意:在实际应用中,需要传入正确的admin参数
|
||||
// restrictions.setRestriction(admin, "camera", true);
|
||||
console.info("Camera would be disabled by default on admin enabled");
|
||||
} catch (error) {
|
||||
console.error(`Failed to set default camera restriction: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
// 设备管理应用解除激活回调方法,应用可在此回调函数中通知企业管理员设备已脱管
|
||||
onAdminDisabled(): void {
|
||||
console.info("onAdminDisabled");
|
||||
try {
|
||||
// 解除激活时,移除相机限制
|
||||
// restrictions.setRestriction(admin, "camera", false);
|
||||
console.info("Camera restriction would be removed on admin disabled");
|
||||
} catch (error) {
|
||||
console.error(`Failed to remove camera restriction: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
// 应用安装回调方法,应用可在此回调函数中进行事件上报,通知企业管理员
|
||||
onBundleAdded(bundleName: string): void {
|
||||
console.info("EnterpriseAdminAbility onBundleAdded bundleName:" + bundleName);
|
||||
}
|
||||
|
||||
// 应用卸载回调方法,应用可在此回调函数中进行事件上报,通知企业管理员
|
||||
onBundleRemoved(bundleName: string): void {
|
||||
console.info("EnterpriseAdminAbility onBundleRemoved bundleName" + bundleName);
|
||||
}
|
||||
|
||||
// 控制相机功能
|
||||
setCameraDisabled(admin: Want, disabled: boolean): void {
|
||||
try {
|
||||
// 在实际应用中应使用正确的API
|
||||
// restrictions.setRestriction(admin, "camera", disabled);
|
||||
console.info(`Camera restriction would be set to ${disabled}`);
|
||||
} catch (error) {
|
||||
console.error(`Failed to set camera restriction: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
// 获取相机当前状态
|
||||
isCameraDisabled(admin: Want): boolean {
|
||||
try {
|
||||
// 在实际应用中应使用正确的API
|
||||
// const disabled = restrictions.isRestrictionSet(admin, "camera");
|
||||
console.info(`Camera restriction status would be checked`);
|
||||
return false;
|
||||
} catch (error) {
|
||||
console.error(`Failed to get camera restriction: ${error}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
162
entry/src/main/ets/pages/Index.ets
Normal file
162
entry/src/main/ets/pages/Index.ets
Normal file
@@ -0,0 +1,162 @@
|
||||
// Index.ets
|
||||
import { BusinessError } from '@kit.BasicServicesKit';
|
||||
import { Want } from '@kit.AbilityKit';
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct Index {
|
||||
@State message: string = 'MDM相机控制';
|
||||
@State cameraStatus: string = '未知';
|
||||
@State isAdminActive: boolean = false;
|
||||
|
||||
aboutToAppear(): void {
|
||||
// 初始化时检查管理权限状态
|
||||
this.checkAdminStatus();
|
||||
}
|
||||
|
||||
// 检查设备管理权限是否已激活
|
||||
checkAdminStatus(): void {
|
||||
try {
|
||||
// 在实际应用中,这里需要检查当前应用是否已被激活为设备管理器
|
||||
// 由于API限制,这里仅作演示
|
||||
console.info('Checking admin status');
|
||||
// this.isAdminActive = deviceManager.isAdminActive();
|
||||
} catch (error) {
|
||||
console.error(`Failed to check admin status: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
// 激活设备管理应用
|
||||
activateAdmin(): void {
|
||||
console.info('Attempting to activate admin');
|
||||
// 实际应用中需要实现完整的激活流程
|
||||
// 通常会跳转到系统设置页面请求激活
|
||||
this.isAdminActive = true;
|
||||
this.cameraStatus = '已启用';
|
||||
}
|
||||
|
||||
// 切换相机状态
|
||||
toggleCamera(): void {
|
||||
if (!this.isAdminActive) {
|
||||
console.warn('Admin is not active, cannot toggle camera');
|
||||
this.message = '请先激活管理应用';
|
||||
return;
|
||||
}
|
||||
|
||||
console.info('Toggling camera status');
|
||||
// 在实际应用中,这里会调用EnterpriseAdminExtensionAbility中的方法
|
||||
// 来控制相机的启用/禁用状态
|
||||
if (this.cameraStatus === '已启用') {
|
||||
// 禁用相机
|
||||
try {
|
||||
// 这里应该调用EnterpriseAdminExtensionAbility中的方法
|
||||
// restrictions.setRestriction(..., "camera", true);
|
||||
this.cameraStatus = '已禁用';
|
||||
this.message = '相机已禁用';
|
||||
} catch (error) {
|
||||
console.error(`Failed to disable camera: ${error}`);
|
||||
this.message = '禁用相机失败';
|
||||
}
|
||||
} else {
|
||||
// 启用相机
|
||||
try {
|
||||
// 这里应该调用EnterpriseAdminExtensionAbility中的方法
|
||||
// restrictions.setRestriction(..., "camera", false);
|
||||
this.cameraStatus = '已启用';
|
||||
this.message = '相机已启用';
|
||||
} catch (error) {
|
||||
console.error(`Failed to enable camera: ${error}`);
|
||||
this.message = '启用相机失败';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
build() {
|
||||
Row() {
|
||||
Column() {
|
||||
Text(this.message)
|
||||
.fontSize(40)
|
||||
.fontWeight(FontWeight.Bold)
|
||||
.textAlign(TextAlign.Center)
|
||||
|
||||
// 显示管理权限状态
|
||||
Text('管理权限: ' + (this.isAdminActive ? '已激活' : '未激活'))
|
||||
.fontSize(20)
|
||||
.fontColor(this.isAdminActive ? Color.Green : Color.Red)
|
||||
.margin({ top: 20 })
|
||||
|
||||
// 显示相机状态
|
||||
Text('相机状态: ' + this.cameraStatus)
|
||||
.fontSize(20)
|
||||
.fontColor(this.cameraStatus === '已启用' ? Color.Green : Color.Red)
|
||||
.margin({ top: 10 })
|
||||
|
||||
// 切换相机状态按钮
|
||||
Button() {
|
||||
Text('切换相机状态')
|
||||
.fontSize(25)
|
||||
.fontWeight(FontWeight.Bold)
|
||||
}
|
||||
.type(ButtonType.Capsule)
|
||||
.margin({
|
||||
top: 30
|
||||
})
|
||||
.backgroundColor('#0D9FFB')
|
||||
.width('80%')
|
||||
.height('8%')
|
||||
.onClick(() => {
|
||||
this.toggleCamera();
|
||||
})
|
||||
|
||||
// 激活管理应用按钮
|
||||
Button() {
|
||||
Text('激活管理应用')
|
||||
.fontSize(25)
|
||||
.fontWeight(FontWeight.Bold)
|
||||
}
|
||||
.type(ButtonType.Capsule)
|
||||
.margin({
|
||||
top: 20
|
||||
})
|
||||
.backgroundColor('#4CAF50')
|
||||
.width('80%')
|
||||
.height('8%')
|
||||
.onClick(() => {
|
||||
this.activateAdmin();
|
||||
})
|
||||
|
||||
// 添加按钮,以响应用户onClick事件
|
||||
Button() {
|
||||
Text('Next')
|
||||
.fontSize(25)
|
||||
.fontWeight(FontWeight.Bold)
|
||||
}
|
||||
.type(ButtonType.Capsule)
|
||||
.margin({
|
||||
top: 30
|
||||
})
|
||||
.backgroundColor('#0D9FFB')
|
||||
.width('40%')
|
||||
.height('8%')
|
||||
// 跳转按钮绑定onClick事件,单击时跳转到第二页
|
||||
.onClick(() => {
|
||||
console.info(`Succeeded in clicking the 'Next' button.`)
|
||||
// 获取UIContext
|
||||
let uiContext: UIContext = this.getUIContext();
|
||||
let router = uiContext.getRouter();
|
||||
// 跳转到第二页
|
||||
router.pushUrl({ url: 'pages/Second' }).then(() => {
|
||||
console.info('Succeeded in jumping to the second page.')
|
||||
|
||||
}).catch((err: BusinessError) => {
|
||||
console.error(`Failed to jump to the second page. Code is ${err.code}, message is ${err.message}`)
|
||||
})
|
||||
})
|
||||
}
|
||||
.width('100%')
|
||||
.padding(20)
|
||||
}
|
||||
.height('100%')
|
||||
.backgroundColor('#f0f0f0')
|
||||
}
|
||||
}
|
||||
68
entry/src/main/ets/pages/Second.ets
Normal file
68
entry/src/main/ets/pages/Second.ets
Normal file
@@ -0,0 +1,68 @@
|
||||
// Second.ets
|
||||
import { BusinessError } from '@kit.BasicServicesKit';
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct Second {
|
||||
@State message: string = 'MDM相机控制说明';
|
||||
|
||||
build() {
|
||||
Row() {
|
||||
Column() {
|
||||
Text(this.message)
|
||||
.fontSize(40)
|
||||
.fontWeight(FontWeight.Bold)
|
||||
.textAlign(TextAlign.Center)
|
||||
|
||||
// 添加说明文本
|
||||
Text('此应用为设备管理应用,可用于控制设备的相机功能。')
|
||||
.fontSize(20)
|
||||
.margin({ top: 30 })
|
||||
.textAlign(TextAlign.Center)
|
||||
|
||||
Text('功能说明:\n\n' +
|
||||
'1. 激活管理应用:获取设备管理权限\n' +
|
||||
'2. 切换相机状态:启用或禁用设备相机\n' +
|
||||
'3. 相机被禁用后,所有应用都无法使用相机功能')
|
||||
.fontSize(18)
|
||||
.margin({ top: 20 })
|
||||
.textAlign(TextAlign.Start)
|
||||
.layoutWeight(1)
|
||||
|
||||
Button() {
|
||||
Text('Back')
|
||||
.fontSize(25)
|
||||
.fontWeight(FontWeight.Bold)
|
||||
}
|
||||
.type(ButtonType.Capsule)
|
||||
.margin({
|
||||
top: 20,
|
||||
bottom: 30
|
||||
})
|
||||
.backgroundColor('#0D9FFB')
|
||||
.width('40%')
|
||||
.height('8%')
|
||||
// 返回按钮绑定onClick事件,单击按钮时返回到第一页
|
||||
.onClick(() => {
|
||||
console.info(`Succeeded in clicking the 'Back' button.`)
|
||||
// 获取UIContext
|
||||
let uiContext: UIContext = this.getUIContext();
|
||||
let router = uiContext.getRouter();
|
||||
try {
|
||||
// 返回第一页
|
||||
router.back()
|
||||
console.info('Succeeded in returning to the first page.')
|
||||
} catch (err) {
|
||||
let code = (err as BusinessError).code;
|
||||
let message = (err as BusinessError).message;
|
||||
console.error(`Failed to return to the first page. Code is ${code}, message is ${message}`)
|
||||
}
|
||||
})
|
||||
}
|
||||
.width('100%')
|
||||
.padding(20)
|
||||
}
|
||||
.height('100%')
|
||||
.backgroundColor('#f0f0f0')
|
||||
}
|
||||
}
|
||||
82
entry/src/main/module.json5
Normal file
82
entry/src/main/module.json5
Normal file
@@ -0,0 +1,82 @@
|
||||
{
|
||||
"module": {
|
||||
"name": "entry",
|
||||
"type": "entry",
|
||||
"description": "$string:module_desc",
|
||||
"mainElement": "EntryAbility",
|
||||
"deviceTypes": [
|
||||
"phone"
|
||||
],
|
||||
"deliveryWithInstall": true,
|
||||
"installationFree": false,
|
||||
"pages": "$profile:main_pages",
|
||||
"requestPermissions": [
|
||||
{
|
||||
"name": "ohos.permission.ENTERPRISE_MANAGE_RESTRICTIONS",
|
||||
"reason": "$string:module_desc",
|
||||
"usedScene": {
|
||||
"abilities": [
|
||||
"EnterpriseAdminAbility"
|
||||
],
|
||||
"when": "always"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ohos.permission.MANAGE_ENTERPRISE_DEVICE_ADMIN",
|
||||
"reason": "$string:module_desc",
|
||||
"usedScene": {
|
||||
"abilities": [
|
||||
"EnterpriseAdminAbility"
|
||||
],
|
||||
"when": "always"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ohos.permission.ENTERPRISE_GET_DEVICE_INFO",
|
||||
"reason": "$string:module_desc",
|
||||
"usedScene": {
|
||||
"abilities": [
|
||||
"EnterpriseAdminAbility"
|
||||
],
|
||||
"when": "always"
|
||||
}
|
||||
}
|
||||
],
|
||||
"abilities": [
|
||||
{
|
||||
"name": "EntryAbility",
|
||||
"srcEntry": "./ets/entryability/EntryAbility.ets",
|
||||
"description": "$string:EntryAbility_desc",
|
||||
"icon": "$media:layered_image",
|
||||
"label": "$string:EntryAbility_label",
|
||||
"startWindowIcon": "$media:startIcon",
|
||||
"startWindowBackground": "$color:start_window_background",
|
||||
"exported": true,
|
||||
"skills": [
|
||||
{
|
||||
"entities": [
|
||||
"entity.system.home"
|
||||
],
|
||||
"actions": [
|
||||
"ohos.want.action.home"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"extensionAbilities": [
|
||||
{
|
||||
"name": "EnterpriseAdminAbility",
|
||||
"srcEntry": "./ets/extensionability/EnterpriseAdminExtensionAbility.ets",
|
||||
"type": "enterpriseAdmin",
|
||||
"exported": true,
|
||||
"metadata": [
|
||||
{
|
||||
"name": "ohos.extension.backup",
|
||||
"resource": "$profile:backup_config"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
8
entry/src/main/resources/base/element/color.json
Normal file
8
entry/src/main/resources/base/element/color.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"color": [
|
||||
{
|
||||
"name": "start_window_background",
|
||||
"value": "#FFFFFF"
|
||||
}
|
||||
]
|
||||
}
|
||||
8
entry/src/main/resources/base/element/float.json
Normal file
8
entry/src/main/resources/base/element/float.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"float": [
|
||||
{
|
||||
"name": "page_text_font_size",
|
||||
"value": "50fp"
|
||||
}
|
||||
]
|
||||
}
|
||||
16
entry/src/main/resources/base/element/string.json
Normal file
16
entry/src/main/resources/base/element/string.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "module_desc",
|
||||
"value": "MDM设备管理模块,用于控制设备相机功能"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_desc",
|
||||
"value": "MDM相机控制应用"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_label",
|
||||
"value": "相机控制"
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
entry/src/main/resources/base/media/background.png
Normal file
BIN
entry/src/main/resources/base/media/background.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 90 KiB |
BIN
entry/src/main/resources/base/media/foreground.png
Normal file
BIN
entry/src/main/resources/base/media/foreground.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.6 KiB |
7
entry/src/main/resources/base/media/layered_image.json
Normal file
7
entry/src/main/resources/base/media/layered_image.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"layered-image":
|
||||
{
|
||||
"background" : "$media:background",
|
||||
"foreground" : "$media:foreground"
|
||||
}
|
||||
}
|
||||
BIN
entry/src/main/resources/base/media/startIcon.png
Normal file
BIN
entry/src/main/resources/base/media/startIcon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
3
entry/src/main/resources/base/profile/backup_config.json
Normal file
3
entry/src/main/resources/base/profile/backup_config.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"allowToBackupRestore": true
|
||||
}
|
||||
6
entry/src/main/resources/base/profile/main_pages.json
Normal file
6
entry/src/main/resources/base/profile/main_pages.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"src": [
|
||||
"pages/Index",
|
||||
"pages/Second"
|
||||
]
|
||||
}
|
||||
8
entry/src/main/resources/dark/element/color.json
Normal file
8
entry/src/main/resources/dark/element/color.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"color": [
|
||||
{
|
||||
"name": "start_window_background",
|
||||
"value": "#000000"
|
||||
}
|
||||
]
|
||||
}
|
||||
2
entry/src/mock/mock-config.json5
Normal file
2
entry/src/mock/mock-config.json5
Normal file
@@ -0,0 +1,2 @@
|
||||
{
|
||||
}
|
||||
35
entry/src/ohosTest/ets/test/Ability.test.ets
Normal file
35
entry/src/ohosTest/ets/test/Ability.test.ets
Normal file
@@ -0,0 +1,35 @@
|
||||
import { hilog } from '@kit.PerformanceAnalysisKit';
|
||||
import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
|
||||
|
||||
export default function abilityTest() {
|
||||
describe('ActsAbilityTest', () => {
|
||||
// Defines a test suite. Two parameters are supported: test suite name and test suite function.
|
||||
beforeAll(() => {
|
||||
// Presets an action, which is performed only once before all test cases of the test suite start.
|
||||
// This API supports only one parameter: preset action function.
|
||||
})
|
||||
beforeEach(() => {
|
||||
// Presets an action, which is performed before each unit test case starts.
|
||||
// The number of execution times is the same as the number of test cases defined by **it**.
|
||||
// This API supports only one parameter: preset action function.
|
||||
})
|
||||
afterEach(() => {
|
||||
// Presets a clear action, which is performed after each unit test case ends.
|
||||
// The number of execution times is the same as the number of test cases defined by **it**.
|
||||
// This API supports only one parameter: clear action function.
|
||||
})
|
||||
afterAll(() => {
|
||||
// Presets a clear action, which is performed after all test cases of the test suite end.
|
||||
// This API supports only one parameter: clear action function.
|
||||
})
|
||||
it('assertContain', 0, () => {
|
||||
// Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'it begin');
|
||||
let a = 'abc';
|
||||
let b = 'b';
|
||||
// Defines a variety of assertion methods, which are used to declare expected boolean conditions.
|
||||
expect(a).assertContain(b);
|
||||
expect(a).assertEqual(a);
|
||||
})
|
||||
})
|
||||
}
|
||||
5
entry/src/ohosTest/ets/test/List.test.ets
Normal file
5
entry/src/ohosTest/ets/test/List.test.ets
Normal file
@@ -0,0 +1,5 @@
|
||||
import abilityTest from './Ability.test';
|
||||
|
||||
export default function testsuite() {
|
||||
abilityTest();
|
||||
}
|
||||
11
entry/src/ohosTest/module.json5
Normal file
11
entry/src/ohosTest/module.json5
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"module": {
|
||||
"name": "entry_test",
|
||||
"type": "feature",
|
||||
"deviceTypes": [
|
||||
"phone"
|
||||
],
|
||||
"deliveryWithInstall": true,
|
||||
"installationFree": false
|
||||
}
|
||||
}
|
||||
5
entry/src/test/List.test.ets
Normal file
5
entry/src/test/List.test.ets
Normal file
@@ -0,0 +1,5 @@
|
||||
import localUnitTest from './LocalUnit.test';
|
||||
|
||||
export default function testsuite() {
|
||||
localUnitTest();
|
||||
}
|
||||
33
entry/src/test/LocalUnit.test.ets
Normal file
33
entry/src/test/LocalUnit.test.ets
Normal file
@@ -0,0 +1,33 @@
|
||||
import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
|
||||
|
||||
export default function localUnitTest() {
|
||||
describe('localUnitTest', () => {
|
||||
// Defines a test suite. Two parameters are supported: test suite name and test suite function.
|
||||
beforeAll(() => {
|
||||
// Presets an action, which is performed only once before all test cases of the test suite start.
|
||||
// This API supports only one parameter: preset action function.
|
||||
});
|
||||
beforeEach(() => {
|
||||
// Presets an action, which is performed before each unit test case starts.
|
||||
// The number of execution times is the same as the number of test cases defined by **it**.
|
||||
// This API supports only one parameter: preset action function.
|
||||
});
|
||||
afterEach(() => {
|
||||
// Presets a clear action, which is performed after each unit test case ends.
|
||||
// The number of execution times is the same as the number of test cases defined by **it**.
|
||||
// This API supports only one parameter: clear action function.
|
||||
});
|
||||
afterAll(() => {
|
||||
// Presets a clear action, which is performed after all test cases of the test suite end.
|
||||
// This API supports only one parameter: clear action function.
|
||||
});
|
||||
it('assertContain', 0, () => {
|
||||
// Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
|
||||
let a = 'abc';
|
||||
let b = 'b';
|
||||
// Defines a variety of assertion methods, which are used to declare expected boolean conditions.
|
||||
expect(a).assertContain(b);
|
||||
expect(a).assertEqual(a);
|
||||
});
|
||||
});
|
||||
}
|
||||
23
hvigor/hvigor-config.json5
Normal file
23
hvigor/hvigor-config.json5
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"modelVersion": "6.0.0",
|
||||
"dependencies": {
|
||||
},
|
||||
"execution": {
|
||||
// "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | "ultrafine" | false ]. Default: "normal" */
|
||||
// "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */
|
||||
// "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */
|
||||
// "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */
|
||||
// "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */
|
||||
// "optimizationStrategy": "memory" /* Define the optimization strategy. Value: [ "memory" | "performance" ]. Default: "memory" */
|
||||
},
|
||||
"logging": {
|
||||
// "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */
|
||||
},
|
||||
"debugging": {
|
||||
// "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */
|
||||
},
|
||||
"nodeOptions": {
|
||||
// "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/
|
||||
// "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/
|
||||
}
|
||||
}
|
||||
6
hvigorfile.ts
Normal file
6
hvigorfile.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { appTasks } from '@ohos/hvigor-ohos-plugin';
|
||||
|
||||
export default {
|
||||
system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
|
||||
plugins: [] /* Custom plugin to extend the functionality of Hvigor. */
|
||||
}
|
||||
28
oh-package-lock.json5
Normal file
28
oh-package-lock.json5
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"meta": {
|
||||
"stableOrder": true,
|
||||
"enableUnifiedLockfile": false
|
||||
},
|
||||
"lockfileVersion": 3,
|
||||
"ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
|
||||
"specifiers": {
|
||||
"@ohos/hamock@1.0.0": "@ohos/hamock@1.0.0",
|
||||
"@ohos/hypium@1.0.24": "@ohos/hypium@1.0.24"
|
||||
},
|
||||
"packages": {
|
||||
"@ohos/hamock@1.0.0": {
|
||||
"name": "",
|
||||
"version": "1.0.0",
|
||||
"integrity": "sha512-K6lDPYc6VkKe6ZBNQa9aoG+ZZMiwqfcR/7yAVFSUGIuOAhPvCJAo9+t1fZnpe0dBRBPxj2bxPPbKh69VuyAtDg==",
|
||||
"resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hamock/-/hamock-1.0.0.har",
|
||||
"registryType": "ohpm"
|
||||
},
|
||||
"@ohos/hypium@1.0.24": {
|
||||
"name": "",
|
||||
"version": "1.0.24",
|
||||
"integrity": "sha512-3dCqc+BAR5LqEGG2Vtzi8O3r7ci/3fYU+FWjwvUobbfko7DUnXGOccaror0yYuUhJfXzFK0aZNMGSnXaTwEnbw==",
|
||||
"resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hypium/-/hypium-1.0.24.har",
|
||||
"registryType": "ohpm"
|
||||
}
|
||||
}
|
||||
}
|
||||
10
oh-package.json5
Normal file
10
oh-package.json5
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"modelVersion": "6.0.0",
|
||||
"description": "Please describe the basic information.",
|
||||
"dependencies": {
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ohos/hypium": "1.0.24",
|
||||
"@ohos/hamock": "1.0.0"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user