目录

使用App Linking实现应用冷启动时应用闪退

问题现象

在配置App Linking时,应用作为被拉起应用,冷启动情况下应用闪退,报错显示UIAbility未正常启动,涉及在EntryAbility的onCreate方法中有处理App Linking参数和跳转相关页面的操作。

问题代码的EntryAbility中参数配置如下:

// 冷启动
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
  this.getRouterUri(want);
  console.info('Ability onCreate');
}
private getRouterUri(want: Want) {
  let uri: string | undefined = want?.uri;
  if (uri) {
    // 根据解析的uri跳转至相应页面,例如需要跳转页面为"pages/Access"
    let status: router.RouterState = router.getState();
    if (status && status.name !== 'Access' && uri) {
      // 根据uri参数做业务处理
      router.replaceUrl({
        url: 'pages/Page1',
        params: {
          uri: uri
        }
      })
    }
  }
}

背景知识

问题定位

  1. 用try-catch将问题代码包裹住,App确实没有再闪退,但首次启动时也无法跳转到二级页面。try-catch捕获到的异常信息如下:
     error:Error message:Internal error. UI execution context not found.
     Error code:100001
     Stacktrace:
       at onCreate (entry/src/main/ets/entryability/EntryAbility.ets:13:38)
  2. 根据上述异常结合API特性分析可知,router.getState获取的是栈顶页面的状态信息,而在onCreate中获取调用时,它的生命周期尚未开始,所以会报错。

分析结论

分析当前问题出在冷启动时在onCreate方法中进行页面跳转(router操作)的处理方式上,导致UIAbility启动异常。需要重新审视这种在生命周期早期进行页面跳转的合理性,并考虑合适的处理参数和加载页面的时机。

修改建议

  1. 避免在onCreate中使用跳转router操作,可以在onCreate里解析参数。在EntryAbility中定义参数(如funcAbilityWant)用于接收调用方UIAbility传过来的参数。
  2. 在onWindowStageCreate中根据解析后的参数来加载页面。例如,根据funcAbilityWant中的parameters.router值来决定加载的页面(如值为'funcA'则加载'pages/Page_ColdStartUp',否则加载'pages/Index'),通过windowStage.loadContent方法加载页面,并处理可能的错误和数据。
    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 {
      funcAbilityWant: Want | undefined = undefined;
      uiContext: UIContext | undefined = undefined;
    
      onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
        // 接收调用方UIAbility传过来的参数
        this.funcAbilityWant = want;
    
        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');
        hilog.info(DOMAIN, 'testTag', '%{public}s', JSON.stringify(launchParam));
      }
    
      onWindowStageCreate(windowStage: window.WindowStage): void {
        // Main window is created, set main page for this ability
        console.info('Ability onWindowStageCreate');
        // Main window is created, set main page for this ability
        let url = 'pages/Index';
        if (this.funcAbilityWant?.parameters?.router && this.funcAbilityWant.parameters.router === 'funcA') {
          url = 'pages/Page_ColdStartUp'; // 根据实际业务设置
        }
        windowStage.loadContent(url, (err, data) => {
          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.');
          hilog.info(DOMAIN, 'testTag', 'data: %{public}s', JSON.stringify(data));
        });
      }
    
      // 示例省略其他生命周期函数
    };
  3. 可参考官方文档链接:目标UIAbility冷启动,获取更多关于UIAbility设备内交互相关指导。

总结