OpenHarmony4.0配置应用开机自启

OpenHarmony开发实战手册:应用开机自启原理 整个实现原理就是专门弄个应用当启动器,让这个应用进行开机自启(此处的开机自启并不是直接打开应用,而是自启一个服务挂在后台运行),然后让这个应用去打开需要自启的那个应用 阅读详情

一、开发环境

系统版本:OpenHarmony 4.0.10.13
设备平台:rk3588
SDK版本:fullSDK 4.0.10.13

二、背景

使用自研应用作为默认Launcher,或者说使特定应用默认开机自启作为Home应用。

三、分析过程

通过分析原生Launcher启动流程可知:
AMS启动根据应用优先级启动应用,通常是OOBE或Launcher
foundation/ability/ability_runtime/services/abilitymgr/src/ability_manager_service.cpp

void AbilityManagerService::StartUserApps(int32_t userId, bool isBoot)
{
HILOG_INFO("StartUserApps, userId:%{public}d, currentUserId:%{public}d", userId, GetUserId());
if (currentMissionListManager_ && currentMissionListManager_->IsStarted()) {
HILOG_INFO("missionListManager ResumeManager");
currentMissionListManager_->ResumeManager();
}
//启动优先级最高的应用
StartHighestPriorityAbility(userId, isBoot);
}

...

void AbilityManagerService::StartHighestPriorityAbility(int32_t userId, bool isBoot)
{
    ...
    /* Query the highest priority ability or extension ability, and start it. usually, it is OOBE or launcher */
    Want want;
    want.AddEntity(HIGHEST_PRIORITY_ABILITY_ENTITY);
    AppExecFwk::AbilityInfo abilityInfo;
    AppExecFwk::ExtensionAbilityInfo extensionAbilityInfo;
    int attemptNums = 0;
    //ImplicitQueryInfoByPriority查询应用ability和extensionAbility配置中的优先级
    while (!IN_PROCESS_CALL(bms->ImplicitQueryInfoByPriority(want,
        AppExecFwk::AbilityInfoFlag::GET_ABILITY_INFO_DEFAULT, userId,
        abilityInfo, extensionAbilityInfo))) {
        HILOG_INFO("Waiting query highest priority ability info completed.");
        ++attemptNums;
        if (!isBoot && attemptNums > SWITCH_ACCOUNT_TRY) {
            HILOG_ERROR("Query highest priority ability failed.");
            return;
        }
        AbilityRequest abilityRequest;
        ComponentRequest componentRequest = initComponentRequest();
        if (!IsComponentInterceptionStart(want, componentRequest, abilityRequest)) {
            return;
        }
        usleep(REPOLL_TIME_MICRO_SECONDS);
    }
	...
	//启动查询到的最高优先级应用
    /* note: OOBE APP need disable itself, otherwise, it will be started when restart system everytime */
    (void)StartAbility(abilityWant, userId, DEFAULT_INVAL_VALUE);
}

至此我们了解到应用优先级取决于应用ability和extensionAbility 优先级配置
查看官方资料
module.json5配置文件
priority
查看launcher module.json5配置文件

"extensionAbilities": [
      {
        "priority": 2,  //优先级设定为2
        "skills": [  //接受home Want的特征标签
          {
            "entities": [
              "entity.system.home",
              "flag.home.intent.from.system"
            ],
            "actions": [
              "action.system.home",
              "com.ohos.action.main",
              "action.form.publish"
            ]
          }
        ],
        "exported": false,  //本组件不可被其他应用调研
        "name": "com.ohos.launcher.MainAbility",  //组件名称,应用中唯一
        "icon": "$media:icon",
        "description": "$string:mainability_description",
        "label": "$string:entry_MainAbility",
        "srcEntry": "./ets/MainAbility/MainAbility.ts",  //组件代码对应路径
        "type": "service"  //组件类型为后台运行服务
      }
    ]

实现案例

创建openharmony demo工程

创建ServiceExtensionAbility

entery/src/main/ets创建ServiceExtAbility文件夹,添加ServiceExtensionAbility.ets
在这里插入图片描述
参考Launcher 配置module.json5 extensionAbilities和requestPermissions
demo/entry/src/main/module.json5

{
  "module": {
    "name": "entry",
    "type": "entry",
    "srcEntry": "./ets/entryability/EntryAbility.ets",
    "description": "$string:module_desc",
    "mainElement": "EntryAbility",
    "deviceTypes": [
      "default",
      "tablet"
    ],
    "metadata": [
      {
        "name": "ArkTSPartialUpdate",
        "value": "true"
      }
    ],
    "deliveryWithInstall": true,
    "installationFree": false,
    "pages": "$profile:main_pages",
    "extensionAbilities": [
      {
        "priority": 3,
        "skills": [
          {
            "entities": [
              "entity.system.home",
              "flag.home.intent.from.system"
            ],
            "actions": [
              "action.system.home",
              "com.ohos.action.main",
              "action.form.publish"
            ]
          }
        ],
        "exported": false,
        "name": "mylauncher",
        "icon": "$media:icon",
        "srcEntry": "./ets/ServiceExtAbility/ServiceExtensionAbility.ets",
        "type": "service"
      }
    ],
    "requestPermissions": [
      {
        "name": "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED"
      },
      {
        "name": "ohos.permission.INSTALL_BUNDLE"
      },
      {
        "name": "ohos.permission.LISTEN_BUNDLE_CHANGE"
      },
      {
        "name": "ohos.permission.MANAGE_MISSIONS"
      },
      {
        "name": "ohos.permission.REQUIRE_FORM"
      },
      {
        "name": "ohos.permission.INPUT_MONITORING"
      },
      {
        "name": "ohos.permission.NOTIFICATION_CONTROLLER"
      },
      {
        "name": "ohos.permission.MANAGE_SECURE_SETTINGS"
      },
      {
        "name": "ohos.permission.START_ABILITIES_FROM_BACKGROUND"
      }
    ]
  }
}

打开默认index page

注意:windowType需配置为TYPE_DESKTOP桌面类型
demo/entry/src/main/ets/ServiceExtAbility/ServiceExtensionAbility.ets

import ServiceExtensionAbility from '@ohos.app.ability.ServiceExtensionAbility';
import Want from '@ohos.application.Want';
import rpc from '@ohos.rpc';
import window from '@ohos.window';
import { BusinessError } from '@ohos.base';

const TAG: string = "[ServiceDemo]";

export default class ServiceExtAbility extends ServiceExtensionAbility {
  onCreate(want: Want) {
    console.info(TAG, `onCreate, want: ${want.abilityName}`);
    let winCfg : window.Configuration = {
      name:"test",
      windowType: window.WindowType.TYPE_DESKTOP,  //
      ctx: this.context
    }
    window.createWindow(winCfg).then((win) =>{
      console.info(TAG, `createWindow`);
      win.setUIContent('pages/Index', (err) => {
        if (err.code) {
          //hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
          return;
        }
        //hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.');
      });
      win.showWindow((err: BusinessError) => {
        const errCode: number = err.code;
        if (errCode) {
          console.error('Failed to show the window. Cause: ' + JSON.stringify(err));
          return;
        }
        console.info('Succeeded in showing the window.');
      });
    });

  }

  onRequest(want: Want, startId: number) {
    console.info(TAG, `onRequest, want: ${want.abilityName}`);
  }

  onDisconnect(want: Want) {
    console.info(TAG, `onDisconnect, want: ${want.abilityName}`);
  }

  onDestroy() {
    console.info(TAG, `onDestroy`);
  }
}

demo配置为系统应用

配置apl和app-feature
SDK_OpenHarmony\sdk\10\toolchains\lib\UnsgnedReleasedProfileTemplate.json

"bundle-info":{
		"developer-id":"OpenHarmony",
		"distribution-certificate":"xxxxxx",
		"bundle-name":"com.example.mylauncherdemo",
		"apl":"system_core",
		"app-feature":"hos_system_app"
	},

特权安装列表配置文件install_list_capability.json添加demo 应用配置

#从设备获取install_list_capability.json
hdc shell mount -o remount,rw /;hdc file recv /system/etc/app/install_list_capability.json  xxx\Desktop\hdcTools\configs
#修改后,更新install_list_capability.json至设备,并重启
hdc shell mount -o remount,rw /;hdc file send xxx\Desktop\hdcTools\configs\install_list_capability.json /system/etc/app/install_list_capability.json;hdc shell reboot

install_list_capability.json添加demo特权配置
‘注:签名指纹获取方式’

## 方式1
#打开应用查看应用包名
hdc shell "aa dump -a | grep 'bundle name' | sed -n 1p"
#查看指定包名应用的指纹信息
hdc shell "bm dump -n com.example.bluetoothopp | grep finger"

##方式2
#设置hilog level debug
hdc shell  hilog -b D
#安装时过滤log中finger关键字
hilog|grep finger
		....
        },
        {
            "bundleName": "com.ohos.launcher",
            "app_signature": ["8E93863FC32EE238060BF69A9B37E2608FFFB21F93C862DD511CBAC9F30024B5"],
            "allowAppUsePrivilegeExtension": true
        },
        {
            "bundleName": "com.example.mylauncherdemo",
            "app_signature": ["xxxxxx"],
            "keepAlive": true,
            "allowAppUsePrivilegeExtension": true
        },
        ....

安装demo程序后,重启设备默认打开demo应用

自动拉起

相比launcher demo应用无法自动拉起
kill [pid] 沙掉demo应用进程后无法自启;而launcher正常。
分析log发现,launcher由AMS重启

AbilityManagerService: [ability_connect_manager.cpp(HandleAbilityDiedTask:1560)]restart ability: com.ohos.launcher.MainAbility

foundation/ability/ability_runtime/services/abilitymgr/src/ability_connect_manager.cpp

void AbilityConnectManager::HandleAbilityDiedTask(
    const std::shared_ptr<AbilityRecord> &abilityRecord, int32_t currentUserId)
{
    HILOG_INFO("Handle ability died task.");
    ...
    //如果应用保活,则重启启动
    if (IsAbilityNeedKeepAlive(abilityRecord)) {
        HILOG_INFO("restart ability: %{public}s", abilityRecord->GetAbilityInfo().name.c_str());
        RestartAbility(abilityRecord, currentUserId);
    }
}

//判断应用是否保活
bool AbilityConnectManager::IsAbilityNeedKeepAlive(const std::shared_ptr<AbilityRecord> &abilityRecord)
{
	//systemUI和Launcher直接保活
    if ((abilityRecord->GetApplicationInfo().bundleName == AbilityConfig::SYSTEM_UI_BUNDLE_NAME &&
            abilityRecord->GetAbilityInfo().name == AbilityConfig::SYSTEM_UI_ABILITY_NAME) ||
        (abilityRecord->GetApplicationInfo().bundleName == AbilityConfig::LAUNCHER_BUNDLE_NAME &&
            abilityRecord->GetAbilityInfo().name == AbilityConfig::LAUNCHER_ABILITY_NAME)) {
        return true;
    }
    auto bms = AbilityUtil::GetBundleManager();
    CHECK_POINTER_AND_RETURN(bms, false);
    std::vector<AppExecFwk::BundleInfo> bundleInfos;
    //获取待检测应用
    bool getBundleInfos = bms->GetBundleInfos(OHOS::AppExecFwk::GET_BUNDLE_DEFAULT, bundleInfos, USER_ID_NO_HEAD);
    if (!getBundleInfos) {
        HILOG_ERROR("Handle ability died task, get bundle infos failed");
        return false;
    }
	//检查ability是否保活
    auto CheckIsAbilityNeedKeepAlive = [](const AppExecFwk::HapModuleInfo &hapModuleInfo,
        const std::string processName, std::string &mainElement) {
        if (!hapModuleInfo.isModuleJson) {
            // old application model
            mainElement = hapModuleInfo.mainAbility;
            for (auto abilityInfo : hapModuleInfo.abilityInfos) {
                if (abilityInfo.process == processName && abilityInfo.name == mainElement) {
                    return true;
                }
            }
            return false;
        }

        // new application model
        if (hapModuleInfo.process == processName) {
            mainElement = hapModuleInfo.mainElementName;
            return true;
        }
        return false;
    };
	获取保活abilities
    auto GetKeepAliveAbilities = [&](std::vector<std::pair<std::string, std::string>> &keepAliveAbilities) {
        for (size_t i = 0; i < bundleInfos.size(); i++) {
            std::string processName = bundleInfos[i].applicationInfo.process;
            HILOG_DEBUG("GetKeepAliveAbilities bundleName:%{public}s isKeepAlive:%{public}d",bundleInfos[i].name.c_str(), bundleInfos[i].isKeepAlive);
            if (!bundleInfos[i].isKeepAlive || processName.empty()) {
                continue;
            }
            std::string bundleName = bundleInfos[i].name;
            for (auto hapModuleInfo : bundleInfos[i].hapModuleInfos) {
                std::string mainElement;
                if (CheckIsAbilityNeedKeepAlive(hapModuleInfo, processName, mainElement) && !mainElement.empty()) {
                    keepAliveAbilities.push_back(std::make_pair(bundleName, mainElement));
                }
            }
        }
    };

    auto findKeepAliveAbility = [abilityRecord](const std::pair<std::string, std::string> &keepAlivePair) {
        return ((abilityRecord->GetAbilityInfo().bundleName == keepAlivePair.first &&
                abilityRecord->GetAbilityInfo().name == keepAlivePair.second));
    };

    std::vector<std::pair<std::string, std::string>> keepAliveAbilities;
    GetKeepAliveAbilities(keepAliveAbilities);
    auto findIter = find_if(keepAliveAbilities.begin(), keepAliveAbilities.end(), findKeepAliveAbility);
    if (findIter != keepAliveAbilities.end()) {
        abilityRecord->SetKeepAlive();
        return true;
    }
    return false;
}

本以为可以在install_list_capability.json配置demo keepAlive来保活,但bms->GetBundleInfos()获取的待检测应用不包含demo应用, 具体原因未知,有了解的专家帮忙解答下~

GetKeepAliveAbilities bundleName:com.example.kikakeyboard isKeepAlive:0
GetKeepAliveAbilities bundleName:com.example.kikakeyboard isKeepAlive:0
GetKeepAliveAbilities bundleName:com.ohos.nweb isKeepAlive:0
GetKeepAliveAbilities bundleName:com.ohos.settingsdata isKeepAlive:1
GetKeepAliveAbilities bundleName:com.ohos.systemui isKeepAlive:1
GetKeepAliveAbilities bundleName:com.ohos.useriam.authwidget isKeepAlive:0
GetKeepAliveAbilities bundleName:ohos.backgroundtaskmgr.resources isKeepAlive:0
GetKeepAliveAbilities bundleName:ohos.global.systemres isKeepAlive:0

强制保活demo

AbilityManagerService: [ability_connect_manager.cpp(HandleAbilityDiedTask:1560)]restart ability: com.ohos.launcher.MainAbility

bool AbilityConnectManager::IsAbilityNeedKeepAlive(const std::shared_ptr<AbilityRecord> &abilityRecord)
{
	//systemUI和Launcher直接保活
    if ((abilityRecord->GetApplicationInfo().bundleName == AbilityConfig::SYSTEM_UI_BUNDLE_NAME &&
            abilityRecord->GetAbilityInfo().name == AbilityConfig::SYSTEM_UI_ABILITY_NAME) ||
        (abilityRecord->GetApplicationInfo().bundleName == AbilityConfig::LAUNCHER_BUNDLE_NAME &&
            abilityRecord->GetAbilityInfo().name == AbilityConfig::LAUNCHER_ABILITY_NAME) ||
            (abilityRecord->GetApplicationInfo().bundleName == "com.example.mylauncherdemo" &&
            abilityRecord->GetAbilityInfo().name == "mylauncher")) {
        return true;
    }
}

编译并替换abilityms库进行验证

#编译libabilityms.z.so 
./build.sh -p dayu210 --build-target abilityms

#替换设备libabilityms.z.so 
hdc shell mount -o remount,rw /;hdc file send openHarmony\out\rk3588\ability\ability_runtime\libabilityms.z.so /system/lib64/platformsdk/libabilityms.z.so

验证

1、重启设备后,开机优先进入demo应用
2、手动kill 应用程序,应用程序自启

OpenHarmony系统定制:实现开机自启动应用与Launcher替换实战 在嵌入式系统与物联网设备开发中,应用自启动与系统启动管理是核心技术需求,尤其在面向专用设备(如工业平板、智能终端)的产品化场景下。其原理通常涉及操作系统启动流程、应用框架的入口管理机制(如Launcher标识与Intent匹配),通过修改系统配置或应用属性来实现特定应用的首屏展示。这项技术的核心价值在于提供“开机即用”的无缝用户体验,提升设备专业性与操作效率,是设备定制化与品牌化的重要环节。应用场景广泛覆盖智能零售终端、教育一体机、工业控制面板等专用设备领域。本文以OpenHarmony 4.1系统与RK3 阅读详情

相关推荐

OpenHarmony ArkTS RK 3568 开机启动server

OpenHarmony rk3568 开机启动server

t7g367的博客 880

OpenHarmony应用开发技巧 - 应用常驻和自启动配置

本文档将介绍如何修改系统配置项使自己开发的应用可以获得常驻和自启动的能力。临时配置用于测试配置项是否生效,当生效后可将配置信息拷贝到系统源码中,使配置永久生效。

TiZizzz 5975

【鸿蒙南向开发】OpenHarmony 应用开机自启

整个实现原理就是专门弄个应用当启动器,让这个应用进行开机自启(此处的开机自启并不是直接打开应用,而是自启一个服务挂在后台运行),然后让这个应用去打开需要自启的那个应用,在此也是参考了这篇文章

HarmonyOS_666的博客 3954

OpenHarmony 4.0 Release横屏配置

本文介绍了配置OpenHarmony默认屏幕方向,处理横屏异常的常见问题,以及应用如何配置自身UI方向,设置系统屏幕方向

mart!nhu的博客 1102

OpenHarmony怎么自启动应用

前几天天介绍了怎么自启动添加权限(https://blog.csdn.net/weixin_56488988/article/details/142961081),这篇文章介绍一下怎么自启动应用。

weixin_56488988的博客 2207

OpenHarmony v4.1 Release设置应用随系统自动启动

OpenHarmony 4.1 版本中的 Ability Manager Service (AMS) 提供了应用自启动管理功能,允许系统控制哪些应用可以在系统启动时自动运行。这需要以下两个主要步骤:启用系统的自启动管理支持开发一个系统应用来管理自启动配置。

afufufufu的博客 1889

OpenHarmony 4.1应用开机自启实战:三种方案与排错指南

系统启动流程是操作系统从内核态到用户态的关键链路,直接影响应用能否在设备上电后自动运行。在OpenHarmony等现代操作系统中,应用自启动并非简单声明权限即可,而是由init进程解析配置、拉起服务,再通过公共事件或Ability机制触发。理解这一原理,对工业面板、信息屏等垂直设备的应用预置与系统集成具有重要价值。针对OpenHarmony 4.1 Release,常见实现路径包括订阅开机公共事件、编写init脚本拉起Ability,以及将应用预置为Launcher入口。三种方案在拉起时机、系统权限要求和适

weixin_31766003的博客 260

OpenHarmony怎么开机自启动添加权限

最近在rk3568调试一个指纹模块(通过usb连接的),在应用上想要对指纹模块进行操作是发现没有权限。笔者先是把selinux给关闭掉,后面又通过敲入chmod -R 777 /dev/bus/usb命令来修改权限。做完这两步之后,权限的问题就解决了。但是每次手动敲入命令太麻烦了,后面就打算采用开机自启动的时候添加权限,下面和大家分享一下方法。

weixin_56488988的博客 954

OpenHarmony南向开发:OH标准系统开机时长优化

通过对硬件、Kernel、 Framework的相应优化让系统开机时长尽量缩短。

qq_39652397的博客 1531

OpenHarmony标准系统开机时长优化

万物互联时代,产品性能至关重要,而系统启动时间是系统性能的重要组成部分,因为用户必须等待系统启动完成后才能使用设备。对于经常需要进行冷启动的汽车等设备而言,较短的启动时间至关重要(没有人喜欢在等待几十秒后才能输入导航目的地),在金融交易设备、电子商务服务器、实时通信设备同样也有较高的应用场景,那我们该如何在OpenAtom OpenHarmony(简称OpenHarmony ) 标准系统现有的能力下,完成秒级开机?

鸿蒙开发知识记录 4669

OpenHarmony—4.0图形HDI基础适配及点屏差异分析

1.1 进程数量变化新增加两个uhdf进程。allocator_host进程及composer_host进程。删除了disp_gralloc_host 进程,并使用allocator_host替换。uhdf添加进程配置如下:1.2 拉起关系变化composer以前版本composer由render_service通过单例拉起,现在通过composer service拉起接口实现层libdisplay_composer_vdi_impl.z.so,对外提供标准的IPC服务.allocator。

2401_82546228的博客 1972

OpenHarmony应用开发 - 应用常驻和自启动配置(6.0-Release)

本文档将介绍如何修改系统配置项使自己开发的应用可以获得常驻和自启动的能力。

TiZizzz 1089

OpenHarmony实战——OpenHarmony标准系统开机时长优化

万物互联时代,产品性能至关重要,而系统启动时间是系统性能的重要组成部分,因为用户必须等待系统启动完成后才能使用设备。对于经常需要进行冷启动的汽车等设备而言,较短的启动时间至关重要(没有人喜欢在等待几十秒后才能输入导航目的地),在金融交易设备、电子商务服务器、实时通信设备同样也有较高的应用场景,那我们该如何在OpenAtom OpenHarmony(简称OpenHarmony ) 标准系统现有的能力下,完成秒级开机?

xianglizaibie的博客 1004

【鸿蒙OH实战开发】OpenHarmony标准系统开机时长优化

万物互联时代,产品性能至关重要,而系统启动时间是系统性能的重要组成部分,因为用户必须等待系统启动完成后才能使用设备。对于经常需要进行冷启动的汽车等设备而言,较短的启动时间至关重要(没有人喜欢在等待几十秒后才能输入导航目的地),在金融交易设备、电子商务服务器、实时通信设备同样也有较高的应用场景,那我们该如何在OpenAtom OpenHarmony(简称OpenHarmony ) 标准系统现有的能力下,完成秒级开机?

huchenghe2的博客 1107

OpenHarmony系统解决方案 - 配置屏幕方向导致开机动画和Launcher显示异常

源码中文件位于foundation/window/window_manager/resources/config/rk3568/display_manager_config.xml。修改源码文件:foundation/window/window_manager/wmserver/src/window_node_container.cpp。系统中文件位于/etc/window/resources/display_manager_config.xml。如果应用的方向需要随系统切换,可以在。

liuhaojiabin的博客 1030

性能优化——OpenHarmony标准系统开机时长优化

万物互联时代,产品性能至关重要,而系统启动时间是系统性能的重要组成部分,因为用户必须等待系统启动完成后才能使用设备。对于经常需要进行冷启动的汽车等设备而言,较短的启动时间至关重要(没有人喜欢在等待几十秒后才能输入导航目的地),在金融交易设备、电子商务服务器、实时通信设备同样也有较高的应用场景,那我们该如何在OpenAtom OpenHarmony(简称OpenHarmony ) 标准系统现有的能力下,完成秒级开机?

maniuT的博客 1583
上一篇: Linux环境变量
下一篇: OpenHarmony镜像烧录bat脚本工具
Mart!nHu
博客等级 码龄7年 1万+粉丝 50原创
评论 9
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值