1 关键字

系统应用;OnBackPressed;

2 问题描述

用户自定义的桌面应用,替换系统应用Launcher,点击界面返回键,应系统应用Launcher退出。

3 问题原因

3.1 正常机制

点击界面返回键,应系统应用Launcher不会退出。

3.2 异常机制

点击界面返回键,应系统应用Launcher退出。

4 解决方案

应用配置信息 skills.entities项添加 "flag.home.intent.from.system"

5 定位过程

正常情况下,点击后退按钮,会向系统发送BackKeyEventKeyCodeEvent

// applications_systemui\features\navigationservice\src\main\ets\com\ohos\navigationservice\KeyCodeEvent.ts
export class KeyCodeEvent {
  public sendKeyEvent(keyCode: number, eventType: number) {   
    switch (keyCode) {
      case Constants.KEYCODE_BACK:
          this.sendBackKeyEventStart(); //down
          ...
          this.sendBackKeyEventEnd(); //up

这个事件会传递到ACE UI子系统下的 Ability 及 AceContainer,最终可能会触发处于展示前台的应用退出:

// foundation\ace\ace_engine\adapter\ohos\entrance\ace_container.cpp
bool AceContainer::OnBackPressed(int32_t instanceId)
{
    ...
    //执行PipelineContext Router相关函数
    return context->CallRouterBackToPopPage();
}

PipelineContext::CallRouterBackToPopPage 执行到 DeclarativeFrontend::CallRouterBack(\bridge\declarative_frontend\declarative_frontend.cpp)... 直至FrontendDelegateDeclarative::PopPage(应用退出)

// frameworks\bridge\declarative_frontend\frontend_delegate_declarative.cpp
void FrontendDelegateDeclarative::PopPage()
{
    ...
    if (delegate->GetStackSize() == 1) {
        // 不允许继续后退页面
        if (delegate->disallowPopLastPage_) {
            LOGW("Not allow back because this is the last page!");
        }
        //应用生命周期相关函数入口
        delegate->OnPageHide();
        delegate->OnPageDestroy(delegate->GetRunningPageId());
       ...

disallowPopLastPage_的值与应用的isLauncherAbility属性关联:

// ace_container.cpp: AceContainer::InitializeFrontend
if (info && info->isLauncherAbility) {
        frontend_->DisallowPopLastPage();
    }

这里的isLauncherAbility的值基于应用内 ability.skills.entities是否包含 "flag.home.intent.from.system"来确定,在系统默认的Launcher应用内基于配置信息( API9:module.json5 或api<9: config.json)该值为true :

​
const std::string FLAG_HOME_INTENT_FROM_SYSTEM = "flag.home.intent.from.system";
​
//appexecfwk\standard\services\bundlemgr\src\module_profile.cpp
​
// API9 获取 launcher信息
bool isLauncherEntity = std::find(skill.entities.begin(), skill.entities.end(),
    Constants::FLAG_HOME_INTENT_FROM_SYSTEM) != skill.entities.end();
if (isLauncherEntity && isPreInstallApp) {
    applicationInfo.isLauncherApp = true;
    abilityInfo.isLauncherAbility = true;
}

应用配置信息:

//applications_launcher/product/phone/src/main/module.json5
"abilities": [
      {
        "skills": [
          {
            "entities": [
            ],
          }
        ],

用户自定义的Launcher应用skills.entities没有"flag.home.intent.from.system"项,应用未被判定为系统桌面应用,因此点击返回键触发应用退出逻辑。

6 知识分享

应用配置配置文件 skills标签标识UIAbility组件或者ExtensionAbility组件能够接收的Want的特征。其中字段entities表示目标应用组件的类别信息。

 

Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐