HarmonyOS鸿蒙Next中如何使自定义文件的"打开方式"中能被自己应用唤起

HarmonyOS鸿蒙Next中如何使自定义文件的"打开方式"中能被自己应用唤起 我在做一个信息分享软件A,自定义了.family格式,然后参考了官方视频"打开方式"适配代码,但多次无果,在文件管理器内点击文件可选打开应用里没有A。请问如何把自定义格式注册到手机里呢

图片


更多关于HarmonyOS鸿蒙Next中如何使自定义文件的"打开方式"中能被自己应用唤起的实战教程也可以访问 https://www.itying.com/category-93-b0.html

15 回复

开发者你好:
1、需要确认下你这边是否配置了自定义文件类型
2、目标应用是否声明对应文件的打开能力,检查module.json5配置文件中的module.abilities.skills.uris.type;

"uris": [
  {
    // 允许打开uri中以file://协议开头标识的本地文件
    "scheme": "file", // 必填,声明协议类型为文件
    "type": "general.video", // 必填,表示支持打开的文件类型
    "linkFeature": "FileOpen" // 必填且大小写敏感,表示此URI的功能为文件打开
  }
]

3、配置了自定义文件类型之后,参考使用拉起指定类型的应用

更多关于HarmonyOS鸿蒙Next中如何使自定义文件的"打开方式"中能被自己应用唤起的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


目标方接入步骤

  1. 声明文件打开能力。
    支持打开文件的应用需要在module.json5配置文件中声明文件打开能力。其中uris字段表示接收URI的类型,其中scheme固定为file。type字段表示支持打开的文件类型(参见UTD类型(推荐)或MIME type类型),如下举例中类型为txt文件。

    {
        "module": {
            // ...
            "abilities": [
                {
                    // ...
                    "skills": [
                        {
                            "actions": [
                                "ohos.want.action.viewData" // 必填,声明数据处理能力
                            ],
                            "uris": [
                                {
                                    // 允许打开uri中以file://协议开头标识的本地文件
                                    "scheme": "file", // 必填,声明协议类型为文件
                                    "type": "general.plain-text", // 必填,表示支持打开的文件类型
                                    "linkFeature": "FileOpen" // 必填且大小写敏感,表示此URI的功能为文件打开
                                }
                                // ...
                            ]
                            // ...
                        }
                    ]
                }
            ]
        }
    }
    
  2. 应用处理待打开文件。
    声明了文件打开的应用在被拉起后,获取传入的Want参数信息,从中获取待打开文件的URI,在打开文件并获取对应的file对象后,可对文件进行读写操作。

    // xxx.ets
    import { fileIo } from '@kit.CoreFileKit';
    import { Want, AbilityConstant, UIAbility } from '@kit.AbilityKit';
    import { BusinessError } from '@kit.BasicServicesKit';
    export default class EntryAbility extends UIAbility {
        onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
            // 从want信息中获取uri字段
            let uri = want.uri;
            if (uri == null || uri == undefined) {
                console.info('uri is invalid');
                return;
            }
            try {
                // 根据待打开文件的URI进行相应操作。例如同步读写的方式打开URI获取file对象
                let file = fileIo.openSync(uri, fileIo.OpenMode.READ_WRITE);
                console.info('Succeed to open file.');
            } catch (err) {
                let error: BusinessError = err as BusinessError;
                console.error(`Failed to open file openSync, code: ${error.code}, message: ${error.message}`);
            }
        }
    }
    

详见开发文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/file-processing-apps-startup

开发者您好,针对您的问题可以参考该文档进行开发:

如何处理自定义文件类型

https://developer.huawei.com/consumer/cn/doc/architecture-guides/traffic-v1_1-ts_85-0000002445416345

文件管理器能唤起你的应用,只能说明 viewData + file + type/UTD + FileOpen 这条普通文件打开链路匹配成功;碰一碰接收端不一定完全复用文件管理器的打开方式选择逻辑。建议先抓两类信息对比:1)文件管理器打开 .family 时传进来的 Want 里的 action、uri、type、flags;2)碰一碰接收后系统实际生成的文件 URI、MIME/UTD 类型和 action。你的应用侧仍然按文件处理类应用配置 ohos.want.action.viewDatascheme: file、正确的 UTD/MIME type 和 linkFeature: FileOpen。如果碰一碰没有把该文件按同一个 type 分发出来,应用侧通常没有一个“注册到碰一碰”的单独开关,只能按它实际传入的 type/uri 去补匹配,或走接收后再手动导入的方案。

从moudle.json5里配置,

{
  "module": {
    "abilities": [
      {
        "name": "EntryAbility",
        "srcEntry": "./ets/entryability/EntryAbility.ts",
        "icon": "$media:icon",
        "label": "$string:EntryAbility_label",
        "exported": true, // true,允许外部唤起
        "skills": [
          {
            "actions": [
              "ohos.want.action.viewData" // 声明这是一个查看/打开数据的动作
            ],
            "uris": [
              {
                "scheme": "file",              // 文件协议
                "type": "application/json",    // 对应的 MIME 类型(如果是标准格式)
                "utd": "com.example.mytext",   // 推荐:使用通用类型标识符 (UTD)
                "fileExtensions": ["json", "myext"] // 核心:支持的自定义文件后缀名列表
              }
            ]
          }
        ]
      }
    ]
  }
}

然后,再去EntryAbility的 **onCreate**和 **onNewWant**生命周期中拿这个 want

onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {

  // 1. 应用冷启动时从 want 中获取文件 URI 
  this.handleIncomingWant(want);

}

onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {

  // 2. 应用热启动时从 want 中获取文件 URI 
  this.handleIncomingWant(want);

}

现在我能够在文件管理器一点击.family文件一唤起我的程序A,但是我是想设计通过【碰一碰】接收端直接打开.family文件备份但是失败了,碰一碰传过来的.family文件在自动弹出的"打开方式列表"里没有我的程序A。问了AI,AI说文件管理器和碰一碰打开文件用的不是一套代码,得额外配置。那请问如何将程序A注册到碰一碰上呢?

开发者你好,可以看下4楼回复,配置是否完成。

补充一版可直接校验的做法:这里不是把 .family 后缀“注册到系统”,而是让文件管理器发出的隐式 Want 能匹配到你的 UIAbility。先看三点:目标 Ability 必须 exported 为 true;skills 里 action 要能匹配打开文件场景,通常是 ohos.want.action.viewData;uris 里 scheme 固定按文件打开用 file,type 要和文件管理器识别到的类型一致,linkFeature 写 FileOpen,注意大小写。

如果 .family 不是系统预置 UTD,建议先用自定义 MIME 做闭环,例如 application/x-family;真机验证通过后,再按业务决定是否补充更标准的 UTD/MIME 映射。配置示例:

{
  "module": {
    "abilities": [
      {
        "name": "EntryAbility",
        "exported": true,
        "skills": [
          {
            "actions": ["ohos.want.action.viewData"],
            "entities": ["entity.system.default"],
            "uris": [
              {
                "scheme": "file",
                "type": "application/x-family",
                "linkFeature": "FileOpen"
              }
            ]
          }
        ]
      }
    ]
  }
}

Ability 被拉起后,不要只看页面是否打开,还要从 want.uri 取文件 URI,并用文件 API 打开:

import { UIAbility, Want, AbilityConstant } from '@kit.AbilityKit';
import { fileIo as fs } from '@kit.CoreFileKit';
import { BusinessError } from '@kit.BasicServicesKit';

export default class EntryAbility extends UIAbility {
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    this.handleOpenFile(want);
  }

  onNewWant(want: Want): void {
    this.handleOpenFile(want);
  }

  private handleOpenFile(want: Want): void {
    const uri = want.uri;
    if (!uri) {
      return;
    }
    try {
      const file = fs.openSync(uri, fs.OpenMode.READ_ONLY);
      // TODO: 读取 .family 内容并进入导入/预览页面
      fs.closeSync(file.fd);
    } catch (e) {
      const err = e as BusinessError;
      console.error('open family file failed: ' + err.code + ', ' + err.message);
    }
  }
}

排查时建议用 aa 命令模拟文件管理器的隐式拉起:

hdc shell "aa start -A ohos.want.action.viewData -U 'file://xxx/test.family' -t 'application/x-family'"

如果 aa 能拉起但文件管理器列表没有你的应用,重点查 type 是否匹配、linkFeature 是否为 FileOpen、是否重装了新包;如果 aa 也拉不起,就先按显式/隐式 Want 匹配规则逐项对 actions、entities、uris。参考文档:module.json5 配置文件、显式 Want 与隐式 Want 匹配规则、UTD/标准化数据定义。

文档链接:module.json5 配置文件显式 Want 与隐式 Want 匹配规则UTD/标准化数据定义

现在我能够在文件管理器—点击.family文件—唤起我的程序A,但是我是想设计通过【碰一碰】接收端直接打开.family文件备份但是失败了,碰一碰传过来的.family文件在自动弹出的"打开方式列表"里没有我的程序A。问了AI,AI说文件管理器和碰一碰打开文件用的不是一套代码,得额外配置。那请问如何将程序A注册到碰一碰上呢,

那是碰一碰的文件传递了,你需要让ai读取碰一碰的文档,跟AI说 现在要碰一碰传文件,文件是什么就可以了,如果的claude或者codex很快就能解决了,

首先从HarmonyOS官网UTD配置列表当中确认当前格式文件是否为HarmonyOS默认支持的文件类型,如果不是,则参看以下步骤自定义文件类型。实现方案如下:

  1. 在当前应用entry\src\main\resources\rawfile\arkdata\utd\目录下新增utd.json5文件。其中的TypeId属性由应用bundleName和具体类型名组成,例如com.example.myapplication.kml,其中com.example.myapplication为应用bundleName。

要实现这种结果的话,需要你的应用能够出现在其他应用分享或打开文件的“打开方式”列表中,并成功唤起你的应用处理文件。

这样的核心在于正确配置应用的接收能力(skills),并在UIAbility中解析传入的Want参数。

比如下面这样

"abilities": [
  {
    "skills": [
      {
        "entities": ["entity.system.share"],
        "actions": [
          "ohos.want.action.sendData",
          "ohos.want.action.viewData"
        ],
        "uris": [
          {
            "scheme": "file",
            "type": "general.plain-text",
            "linkFeature": "FileOpen"
          }
        ]
      }
    ]
  }
]

每个参数的配置说明:

entities:建议至少包含"entity.system.share",表示应用具备系统分享相关能力。

actions:包含"ohos.want.action.viewData"(用于打开文件)或"ohos.want.action.sendData"(用于接收分享数据)。若希望应用同时支持两种场景,可同时声明。

uris:定义应用能处理的文件类型。

scheme:通常设为"file",表示支持文件协议。

type:指定文件类型,如"general.plain-text"表示纯文本文件。你可以根据应用支持的文件类型进行设置,例如"image/*"表示所有图片类型。更精确的类型可通过UniformTypeDescriptor(UTD)描述。

linkFeature:设为"FileOpen"(大小写敏感),明确此URI的功能为文件打开。

配置完成后,在在UIAbility中解析传入的Want,应该就可以解决你的问题。

不是把 .family 后缀放到系统里就会自动出现,关键是目标 Ability 的 skills 能否和文件管理器发出的 Want 匹配上。

建议检查 module.json5:1. actions 里声明 ohos.want.action.viewData;2. uris 里 scheme 使用 file;3. type 使用 UTD 类型优先,如果是自定义格式,可以先用合适的 MIME 兜底,例如 application/x-family;4. linkFeature 要写 FileOpen,大小写也要一致;5. Ability 被拉起后从 want.uri 读取文件,并确认有 READ URI 授权。

如果调用方传了 type,type 必须和你的声明一致;如果只靠后缀,系统不一定能把 .family 映射成你想要的类型。所以调试时可以先用一个已知类型如 text/plain 跑通打开链路,再换成自定义类型。

在HarmonyOS Next中,应用需在module.json5abilities中配置skills,添加actions"ohos.want.action.viewData",并在uris中指定type(如"application/your-custom-type")或schemehostportpath。例如:

"skills": [{
  "actions": ["ohos.want.action.viewData"],
  "uris": [{"type": "application/x-your-format"}],
  "entities": ["entity.system.default"]
}]

同时确保应用已注册到文件类型关联。系统会据此将应用加入“打开方式”列表。

在 module.json5 的目标 Ability 中添加 skills 配置,通过 uris 匹配自定义扩展名。关键配置如下:

"skills": [
  {
    "actions": ["ohos.want.action.viewData"],
    "uris": [
      {
        "scheme": "file",
        "pathPattern": ".*\\.family"
      }
    ]
  }
]

注意 pathPattern 使用正则匹配 .family 后缀的文件;无需指定 host。
确保该 Ability 已声明支持文件打开,且 actions 配对。配置后需 卸载重装应用 使系统重新扫描 skills,文件管理器即可在“打开方式”中列出你的应用。

回到顶部