HarmonyOS 鸿蒙Next中共享面板拉起失败

HarmonyOS 鸿蒙Next中共享面板拉起失败 harmony OS SDK 6.02,Mate80真机和仿真器都看不到拉起的面板。代码如下:

try {
  const uiContext: UIContext = this.getUIContext();
  const contextFaker: Context = uiContext.getHostContext() as Context;
  const tempFiles: string[] = [];

  for (const item of items) {
    const url = `${BASE_URL}${item.filePath}${item.fileName}`;
    const fileName = `share_${Date.now()}_${item.id}.jpg`;
    const filePath = `${contextFaker.tempDir}/${fileName}`;
    await this.downloadImage(url, filePath);
    tempFiles.push(`file://` + filePath);
  }

  let utdTypeId = utd.getUniformDataTypeByFilenameExtension('.jpg', utd.UniformDataType.IMAGE);
  const shareData = new systemShare.SharedData({
    utd: utdTypeId,
    uri: fileUri.getUriFromPath(tempFiles[0])
  });
  for (let i = 1; i < tempFiles.length; i++) {
    shareData.addRecord({
      utd: utdTypeId,
      uri: fileUri.getUriFromPath(tempFiles[i])
    });
  }

  let controller = new systemShare.ShareController(shareData);
  const context: common.UIAbilityContext = uiContext.getHostContext() as common.UIAbilityContext;
  try {
    controller.show(context,{
      selectionMode: systemShare.SelectionMode.BATCH,
      previewMode: systemShare.SharePreviewMode.DEFAULT
    }).then(() => {
      console.log('ShareController show success.');
    });
  } catch (err) {
    console.error(`同步调用错误: ${JSON.stringify(err)}`);
  }

} catch (error) {
  console.error(`Share failed: ${JSON.stringify(error)}`);
}

用户日志打印"ShareController show success."

系统日志有udmf错误:

02-06 11:37:36.727 21452-21452 C01656/UDMF com.orchi…alendar2 E CustomUtdStore::ReadTypeCfgs Failed to open custom utd file, errno=2

02-06 11:37:36.727 21452-21452 C01656/UDMF com.orchi…alendar2 E CustomUtdStore::GetDynamicUtd ReadTypeCfgs failed, ret = 27721734.

02-06 11:37:36.871 21452-22850 C04204/WMSScb com.orchi…alendar2 E SetRSUIContext: RSUIContext is null, RSNode [id: 131627862720519], RSUIContext is null

02-06 11:37:36.872 21452-22850 C04201/DMS com.orchi…alendar2 E GetScreenSession: Error found screen session with id: 18446744073709551615

02-06 11:37:36.887 21452-21452 C04201/DMS com.orchi…alendar2 E GetScreenSession: Error found screen session with id: 18446744073709551615


更多关于HarmonyOS 鸿蒙Next中共享面板拉起失败的实战教程也可以访问 https://www.itying.com/category-93-b0.html

4 回复

开发者您好,问题描述中的代码不全无法完整复现,但是根据部分代码我这边做了部分修改没有能够复现问题,6.0.2设备也可以正常拉起共享面板,您这边是否能够提供一下以下信息方便我们这边进行复现定位:

  1. 能够复现问题的完整代码
  2. 样机型号代码及对应软件版本号:设置——关于本机

本地验证代码如下:

import { common } from '@kit.AbilityKit';
import  { fileUri, picker } from '@kit.CoreFileKit';
import { systemShare } from '@kit.ShareKit';
import { uniformTypeDescriptor as utd } from '@kit.ArkData';
@Entry
@Component
struct Index {
  @State message: string = 'hello World';

  build() {
    Row() {
      Column() {
        Text(this.message)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
          .onClick(()=>{
            try {
              const uiContext: UIContext = this.getUIContext();
              const contextFaker: Context = uiContext.getHostContext() as Context;
              const tempFiles: string[] = [];
              let utdTypeId = utd.getUniformDataTypeByFilenameExtension('.png', utd.UniformDataType.IMAGE);
              let shareData: systemShare.SharedData = new systemShare.SharedData({
                utd: utdTypeId,
                uri: fileUri.getUriFromPath(contextFaker.filesDir + '/image2.png'),
              });
              let controller = new systemShare.ShareController(shareData);
              const context: common.UIAbilityContext = uiContext.getHostContext() as common.UIAbilityContext;
              try {
                controller.show(context,{
                  selectionMode: systemShare.SelectionMode.BATCH,
                  previewMode: systemShare.SharePreviewMode.DEFAULT
                }).then(() => {
                  console.log('ShareController show success.');
                });
              } catch (err) {
                console.error(`同步调用错误: ${JSON.stringify(err)}`);
              }

            } catch (error) {
              console.error(`Share failed: ${JSON.stringify(error)}`);
            }
          })
      }
      .width('100%')
    }
    .height('100%')
  }
}

更多关于HarmonyOS 鸿蒙Next中共享面板拉起失败的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


谢谢答复!

对比了一下,问题出在uri的手动拼接导致格式非法。原来的代码是:

tempFiles.push(`file://` + filePath);
let uri = fileUri.getUriFromPath(tempFiles[0])

得到的uri是原始路径uri:file:///data/storage/…

统一使用 fileUri.getUriFromPath() 处理物理路径后问题解决:

const finalUri = fileUri.getUriFromPath(filePath); 
tempFiles.push(finalUri);

鸿蒙Next中共享面板拉起失败,通常由以下原因导致:

  1. 权限未配置:检查是否在配置文件中声明了ohos.permission.SYSTEM_FLOAT_WINDOW权限。
  2. 组件未注册:确认共享面板相关Ability或ExtensionAbility已在module.json5中正确注册。
  3. API版本不匹配:共享面板接口可能依赖特定API版本,需检查设备系统版本是否支持。
  4. 资源缺失:面板布局或资源文件未正确打包或引用。
  5. 生命周期冲突:面板与当前页面生命周期状态冲突,导致无法正常显示。

从代码和日志看,共享面板拉起失败的核心问题在于上下文(Context)的获取和使用不当,特别是与UI渲染相关的上下文。系统日志中的关键错误信息指向了这个问题。

主要问题分析:

  1. RSUIContext is null 错误:这是导致面板无法显示的直接原因。日志 SetRSUIContext: RSUIContext is null 表明,在尝试启动共享面板时,系统无法获取到有效的渲染上下文。在HarmonyOS Next中,ShareController.show() 方法需要正确的UI上下文来关联界面渲染。

  2. 上下文获取方式错误:你的代码中使用了 this.getUIContext()uiContext.getHostContext() 来获取上下文。在HarmonyOS Next的Stage模型中,UIAbility的UI上下文 (UIAbilityContext) 与UI组件渲染的上下文 (RSUIContext/UIContext) 是不同的ShareController.show() 需要的是与当前UI组件树关联的、有效的UI上下文,而不是UIAbility的上下文。

  3. UDMF错误是次要问题:日志中的UDMF(Uniform Data Model Framework)错误 Failed to open custom utd file 通常是由于系统预定义的数据类型配置文件缺失或损坏引起的,可能是一个系统级或环境问题,但不是导致面板无法拉起的主因。主因仍然是上下文问题。

解决方案:

修改上下文获取方式。在ArkUI(特别是声明式范式)中,正确的做法是使用 getContext() 方法获取当前UI组件节点的上下文,或者直接使用UIAbility实例的 context 属性(在某些场景下)。对于共享面板,推荐使用以下方式:

修改后的关键代码段:

import { common, systemShare, utd, fileUri } from '@kit.ArkData';
import { shareController } from '@kit.ShareKit'; // 注意API包名

// 在您的UI组件方法中(例如一个按钮点击事件回调里):
try {
  // 1. 构建临时文件URI列表 (你的原有逻辑可以保留)
  const tempFiles: string[] = [];
  // ... [你的文件下载和路径构建代码] ...
  
  // 2. 构建ShareData
  let utdTypeId = utd.getUniformDataTypeByFilenameExtension('.jpg', utd.UniformDataType.IMAGE);
  const shareData = new systemShare.SharedData({
    utd: utdTypeId,
    uri: fileUri.getUriFromPath(tempFiles[0])
  });
  for (let i = 1; i < tempFiles.length; i++) {
    shareData.addRecord({
      utd: utdTypeId,
      uri: fileUri.getUriFromPath(tempFiles[i])
    });
  }

  // 3. 关键修改:获取正确的上下文并拉起面板
  // 方案一(推荐):在UI组件内,直接使用UIAbility实例的context
  // 假设你的UIAbility实例名为'context'(在EntryAbility中常见)
  let abilityContext: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
  
  // 方案二:如果是在UIAbility的onWindowStageCreate等方法中调用,可直接使用this.context
  // let abilityContext: common.UIAbilityContext = this.context;

  let controller = new shareController.ShareController(shareData); // 注意API引用
  controller.show(abilityContext, { // 传入正确的UIAbilityContext
    selectionMode: systemShare.SelectionMode.BATCH,
    previewMode: systemShare.SharePreviewMode.DEFAULT
  }).then(() => {
    console.log('ShareController show success.');
  }).catch((err) => {
    console.error(`拉起分享面板失败: ${JSON.stringify(err)}`);
  });

} catch (error) {
  console.error(`Share failed: ${JSON.stringify(error)}`);
}

核心修改点说明:

  • 导入路径:确认 @kit.ShareKit 的导入路径和API名称(如shareController)与你的SDK版本匹配。
  • 上下文:将 controller.show() 的参数从之前获取的 uiContext.getHostContext() 改为直接获取的 UIAbilityContext (abilityContext)。这个上下文必须与当前UIAbility实例关联,并且是有效的。
  • 错误处理:将 controller.show() 的Promise调用用 .catch() 捕获异步错误,这有助于发现更多调用阶段的异常。

验证步骤:

  1. 确保你的UIAbility已经创建并进入了前台(例如onWindowStageCreate生命周期已完成)。
  2. 确保共享的文件URI是有效的,并且应用有相应的文件访问权限(如果涉及沙箱外路径,需要申请权限)。
  3. 在真机上再次测试,观察系统日志中是否还有 RSUIContext is nullGetScreenSession 错误。

如果按照以上修改后问题仍然存在,请检查:

  • SDK版本兼容性:确认HarmonyOS Next SDK 6.02的ShareKit API是否有变更。
  • UIAbility生命周期:确保调用 controller.show() 时,UIAbility处于活跃状态(例如,不能在onDestroy或后台状态下调用)。
  • 设备系统版本:确保Mate80真机的HarmonyOS Next版本与SDK版本匹配。
回到顶部