HarmonyOS6 接入快手 SDK 指南

介绍

目前快手开放了 授权、发布单图、发布单视频的鸿蒙能力,开发者如果有需要接入,可以按照以下流程操作。

效果一览

环境准备

开发者需要在快手开放平台完成注册 ,新建一个应用 ,并获取应用标识 appId ,详细参考申请注册流程,官网地址:open.kuaishou.com/platform

环境要求

  • 快手版本 >= 13.0.10
  • 鸿蒙SDK版本 >= 12

接入步骤

  1. 在模块中引入 SDK依赖,如 Entry模块
perl 复制代码
  "dependencies": {    "@kwai_open_platform/opensdk": "^1.0.1"
  }
  1. 在 entry 模块下的 module.json5 文件中添加querySchemes配置。

在鸿蒙应用的module.json5文件中配置querySchemes的作用是声明应用支持的URL协议(URL Scheme) ,允许其他应用或网页通过特定格式的URL调起当前应用。具体解析如下:

  1. 核心功能实现 示例中配置的"kwai""ksnebula"表示该应用可以响应以下两种格式的URL请求:
  • kwai://...

  • ksnebula://...当其他应用或系统触发这类链接时,鸿蒙系统会尝试启动当前应用并传递参数。

  1. 典型应用场景
  • 跨应用跳转:其他应用通过startAbility发送包含对应Scheme的Want对象调起本应用
  • 网页跳转:在浏览器中点击<a href="kwai://detail?id=123">类链接触发应用打开
  • 广告引流:通过短信、二维码等方式引导用户通过特定Scheme打开应用指定页面
json 复制代码
{
  "module": {
    "querySchemes": [
      "kwai",
      "ksnebula"
    ]
  }
}
  1. 同时还需求申请网络权限
json 复制代码
    "requestPermissions": [
      {
        "name" : "ohos.permission.INTERNET"
      }
    ]
  1. 在接受回调的 UIAbility 的 onCreate 和 onNewWant 方法中,调用 kwaiOpenSdk.handleCallback 方法处理回调数据。

onCreate 表示应用首次启动

onNewWant 表示应用已经启动的,然后被重新拉起

php 复制代码
import { kwaiOpenSdk } from '@kwai_open_platform/opensdk/src/main/ets/KwaiOpensdk';

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

  onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    kwaiOpenSdk.handleCallback(want)
  }
}
  1. 初始化SDK,如在 Index.ets的aboutToAppear中初始化
csharp 复制代码
  aboutToAppear(): void {
    // 初始化快手SDK
    kwaiOpenSdk.init(this.context);
  }

相关功能

目前SDK提供有 授权 和 发布单图和发单视频能力,开发者可以根据需求引入使用

初始化代码数据

定义快手应用ID APPID

定义鸿蒙应用ID harmonyAppID

定义媒体选择通用方法 selectMedia

typescript 复制代码
// 导入快手开放平台SDK
import { kwaiOpenSdk } from '@kwai_open_platform/opensdk/src/main/ets/KwaiOpensdk';
// 导入AbilityKit相关组件
import { common } from '@kit.AbilityKit';
// 导入授权请求模型
import { AuthRequest } from '@kwai_open_platform/opensdk/src/main/ets/model/request/AuthRequest';
// 导入授权响应模型
import { AuthResponse } from '@kwai_open_platform/opensdk/src/main/ets/model/response/AuthResponse';
// 导入日志工具
import { Logger } from '@kwai_open_platform/opensdk/src/main/ets/utils/Logger';
// 导入分享请求模型创建函数
import {
  createSingleImagePublish,
  createSingleVideoPublish
} from '@kwai_open_platform/opensdk/src/main/ets/model/request/ShareRequest';
// 导入ArkTS集合框架
import { ArrayList } from '@kit.ArkTS';
// 导入媒体库访问助手
import { photoAccessHelper } from '@kit.MediaLibraryKit';
// 导入文件操作相关工具
import { fileIo, fileUri } from '@kit.CoreFileKit';

// 定义快手应用ID
const APPID = "ks669910448092164647"

// 定义鸿蒙应用ID
const harmonyAppID: string = "6917560710208292268";

@Entry
@Component
struct Index {
  // 获取UIAbility上下文
  context = this.getUIContext().getHostContext() as common.UIAbilityContext;
  // 回调结果状态
  @State callbackResult: boolean = false;
  // 授权码
  @State authCode: string = "";
  // 错误信息
  @State errMsg: string = "";
  // 错误码
  @State errCode: number = -1;

  aboutToAppear(): void {
    // 初始化快手SDK
    kwaiOpenSdk.init(this.context);
  }


  // 媒体选择通用方法
  private selectMedia<T>(
    callback: (t: T) => void,
    type: photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE | photoAccessHelper.PhotoViewMIMETypes.VIDEO_TYPE,
    num: number = 1
  ) {
    // 创建照片选择选项
    let photoOptions = new photoAccessHelper.PhotoSelectOptions();
    // 设置MIME类型(图片或视频)
    photoOptions.MIMEType = type;
    // 设置最大选择数量
    photoOptions.maxSelectNumber = num;

    // 创建照片选择器
    let picker = new photoAccessHelper.PhotoViewPicker();
    // 调用选择方法
    picker.select(photoOptions).then((photoSelectResult: photoAccessHelper.PhotoSelectResult) => {
      // 获取选中的URI列表
      let uris: Array<string> = photoSelectResult.photoUris;
      if (uris.length > 0) {
        // 获取第一个URI
        let str = uris[0];
        // 提取文件名
        let fileName = str.substring(str.lastIndexOf('/'));
        // 构建目标文件路径
        let desFilePath = this.context.getApplicationContext().tempDir + fileName;
        // 打开源文件(只读)
        let srcFile = fileIo.openSync(str, fileIo.OpenMode.READ_ONLY);
        // 打开目标文件(写,如不存在则创建)
        let desFile = fileIo.openSync(desFilePath, fileIo.OpenMode.WRITE_ONLY | fileIo.OpenMode.CREATE);
        // 复制文件内容
        fileIo.copyFileSync(srcFile.fd, desFile.fd)
        // 回调处理,传递文件URI
        callback?.(fileUri.getUriFromPath(desFilePath) as T);
      } else {
        // 未选择资源时显示提示
        this.getUIContext().getPromptAction().showToast({
          message: '没有选择资源'
        })
      }
    }).catch((error: BusinessError) => {
      // 选择出错时显示提示
      this.getUIContext().getPromptAction().showToast({
        message: '选择资源error'
      })
    })
  }
}

接入快手授权能力

参数说明:

参数

说明

是否必填

requiredScopes

申请获取用户的那些授权信息,如果需要多个scope,用 "," 分割。比如:user_info,user_phone

optional0Scopes

可选scope,授权页可以取消勾选,默非认勾选态

optional1Scopes

可选scope,授权页可以取消勾选,默认勾选态

callbackLocalEntry

回调的UIAbility名称,需要在module.json中声明

abilityContext

如果没有安装快手,会跳转到应用市场安装。不传则不会跳转到应用市场

javascript 复制代码
  // 授权功能实现
  fn1 = () => {
    {
      // 创建授权请求对象
      let request = new AuthRequest(APPID);
      // 设置必需的权限范围
      request.requiredScopes = "user_phone,user_info";
      // 设置可选权限范围0
      request.optional0Scopes = "user_base,share_media,following,share_message"
      // 设置可选权限范围1
      request.optional1Scopes = "user_growth_distribution,message,live,relation"
      // 设置回调入口
      request.callbackLocalEntry = "EntryAbility";
      // 设置Ability上下文
      request.abilityContext = this.context;
      // 重要提示,这行代码不要复制
      request.harmonyAppId = harmonyAppID
      // 调用SDK授权接口
      kwaiOpenSdk.createApi().authorize(this.context, request, {
        // 授权成功回调
        onSuccess: (res) => {
          Logger.i("authCallback", "success.......");
          // 保存授权码
          this.authCode = (res as AuthResponse).code;
          // 设置回调结果为成功
          this.callbackResult = true;
        },
        // 授权失败回调
        onError: (errorCode, msg) => {
          Logger.i("authCallback", `failed, code: ${errorCode}, msg: ${msg}`);
          // 保存错误信息
          this.errMsg = msg
          this.errCode = errorCode
          // 设置回调结果为失败
          this.callbackResult = false;
        }
      })
    }
  }

授权-错误码

错误码

描述

999

成功

1000

appId is empty

1001

request is error

1002

request is empty

1003

request bundle id is empty

1004

request harmony app id is empty

1005

not install kuaishou app

2000

auth request requiredScopes is empty

2002

无效的授权内容

2101

提交授权信息失败,缺少授权参数

100200100

请求缺少参数或参数类型错误

100200101

无效的client,无效的 app 或 developer,可能是验证参数不正确(回调地址等信息)

100200102

请求被拒绝,可能是无效的 token 等

100200103

请求的 responseType 错误

100200104

请求的 grantType 不支持

100200105

请求的 code 错误

100200106

请求的 scope 错误

100200107

无效的 openid

100200108

access_token过期

100200109

用户取消该 app 授权

100200110

用户授权过期

100200111

用户未授权过

100200112

bundleToken不合法

100200113

refresh_token过期

100200500

服务内部错误

接入发布单图能力

  1. 分享请求构建
  2. 使用createSingleImagePublish(APPID)创建单图分享请求对象
  3. 初始化ArrayList存储媒体URI列表,并添加选中图片的URI
  4. 设置callbackLocalEntry指定回调入口为EntryAbility
  5. 关键参数配置
  6. 显式设置harmonyAppId参数(注释提示该行代码具有重要性)
  7. 通过上下文this.context保持与当前页面的关联
  8. SDK调用与结果处理

调用kwaiOpenSdk.createApi().share()方法执行实际分享操作

typescript 复制代码
  fn2 = () => {
    // 调用媒体选择方法,指定图片类型
    this.selectMedia<string>((url: string) => {
      // 创建单图分享请求对象
      let shareRequest = createSingleImagePublish(APPID);
      // 创建媒体URI列表
      let list: ArrayList<string> = new ArrayList();
      // 添加选中的图片URI
      list.add(url);
      // 设置媒体URI列表
      shareRequest.mediaUri = list;
      // 设置回调入口
      shareRequest.callbackLocalEntry = "EntryAbility";
      // 重要提示,这行代码不要复制
      shareRequest.harmonyAppId = harmonyAppID

      // 调用SDK分享接口
      kwaiOpenSdk.createApi().share(this.context, shareRequest, {
        // 分享成功回调
        onSuccess: (res) => {
          // 设置回调结果为成功
          this.callbackResult = true;
          Logger.i("shareCallback", "success.......");
        },
        // 分享失败回调
        onError: (errorCode, msg) => {
          // 设置回调结果为失败
          this.callbackResult = false;
          // 保存错误信息
          this.errMsg = msg
          this.errCode = errorCode
          Logger.i("shareCallback", `failed, code: ${errorCode}, msg: ${msg}`);
        }
      })
    }, photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE);
  }

接入发布单视频能力

  1. 视频分享请求构建
  • 初始化ArrayList容器
  • 将视频URI添加到容器
  • 设置请求的mediaUri属性为容器对象
  1. 对象创建:createSingleVideoPublish(APPID)生成视频分享请求对象(区别于图片接口)
  2. 媒体列表管理:
  3. 关键参数配置
  4. callbackLocalEntry指定回调入口为"EntryAbility"(需与实际Ability名称一致)
  5. harmonyAppId显式赋值(通过独立变量harmonyAppID注入,需确保配置有效性)
  6. SDK调用与响应处理

通过kwaiOpenSdk.createApi().share()发起分享请求,传入上下文对象和配置参

typescript 复制代码
  // 发布单视频功能实现
  fn3 = () => {
    // 调用媒体选择方法,指定视频类型
    this.selectMedia<string>((url: string) => {
      // 创建单视频分享请求对象
      let shareRequest = createSingleVideoPublish(APPID);
      // 创建媒体URI列表
      let list: ArrayList<string> = new ArrayList();
      // 添加选中的视频URI
      list.add(url);
      // 设置媒体URI列表
      shareRequest.mediaUri = list;
      // 设置回调入口
      shareRequest.callbackLocalEntry = "EntryAbility";
      // 重要提示,这行代码不要复制
      shareRequest.harmonyAppId = harmonyAppID
      // 调用SDK分享接口
      kwaiOpenSdk.createApi().share(this.context, shareRequest, {
        // 分享成功回调
        onSuccess: (res) => {
          // 设置回调结果为成功
          this.callbackResult = true;
          Logger.i("shareCallback", "success.......");
        },
        // 分享失败回调
        onError: (errorCode, msg) => {
          // 设置回调结果为失败
          this.callbackResult = false;
          // 保存错误信息
          this.errMsg = msg
          this.errCode = errorCode
          Logger.i("shareCallback", `failed, code: ${errorCode}, msg: ${msg}`);
        }
      })
    }, photoAccessHelper.PhotoViewMIMETypes.VIDEO_TYPE);
  }

发布单图-发布单视频的错误码

错误码

描述

999

成功

1000

appId is empty

1001

request is error

1002

request is empty

1003

request bundle id is empty

1004

request harmony app id is empty

1005

not install kuaishou app

3000

用户取消

3001

框架出错,请反馈客服

3002

参数错误,包含shareType、appId、harmonyId、mediaUri等相关参数

3003

打开发布页失败

3004

网络错误

3005

发布请求过于频繁(3s内重复调用)

3006

视频size超过最大大小

3007

图片size超过最大大小

3008

拒绝当次分享动作;如果是发布视频:请检查视频长度

3009

鉴权失败

完整 Index.ets 代码

typescript 复制代码
// 导入快手开放平台SDK
import { kwaiOpenSdk } from '@kwai_open_platform/opensdk/src/main/ets/KwaiOpensdk';
// 导入AbilityKit相关组件
import { common } from '@kit.AbilityKit';
// 导入授权请求模型
import { AuthRequest } from '@kwai_open_platform/opensdk/src/main/ets/model/request/AuthRequest';
// 导入授权响应模型
import { AuthResponse } from '@kwai_open_platform/opensdk/src/main/ets/model/response/AuthResponse';
// 导入日志工具
import { Logger } from '@kwai_open_platform/opensdk/src/main/ets/utils/Logger';
// 导入分享请求模型创建函数
import {
  createSingleImagePublish,
  createSingleVideoPublish
} from '@kwai_open_platform/opensdk/src/main/ets/model/request/ShareRequest';
// 导入ArkTS集合框架
import { ArrayList } from '@kit.ArkTS';
// 导入媒体库访问助手
import { photoAccessHelper } from '@kit.MediaLibraryKit';
// 导入文件操作相关工具
import { fileIo, fileUri } from '@kit.CoreFileKit';

// 定义快手应用ID
const APPID = "ks669910448092164647"

// 定义鸿蒙应用ID
const harmonyAppID: string = "6917560710208292268";

@Entry
@Component
struct Index {
  // 获取UIAbility上下文
  context = this.getUIContext().getHostContext() as common.UIAbilityContext;
  // 回调结果状态
  @State callbackResult: boolean = false;
  // 授权码
  @State authCode: string = "";
  // 错误信息
  @State errMsg: string = "";
  // 错误码
  @State errCode: number = -1;

  aboutToAppear(): void {
    // 初始化快手SDK
    kwaiOpenSdk.init(this.context);
  }

  // 授权功能实现
  fn1 = () => {
    {
      // 创建授权请求对象
      let request = new AuthRequest(APPID);
      // 设置必需的权限范围
      request.requiredScopes = "user_phone,user_info";
      // 设置可选权限范围0
      request.optional0Scopes = "user_base,share_media,following,share_message"
      // 设置可选权限范围1
      request.optional1Scopes = "user_growth_distribution,message,live,relation"
      // 设置回调入口
      request.callbackLocalEntry = "EntryAbility";
      // 设置Ability上下文
      request.abilityContext = this.context;
      // 重要提示,这行代码不要复制
      request.harmonyAppId = harmonyAppID
      // 调用SDK授权接口
      kwaiOpenSdk.createApi().authorize(this.context, request, {
        // 授权成功回调
        onSuccess: (res) => {
          Logger.i("authCallback", "success.......");
          // 保存授权码
          this.authCode = (res as AuthResponse).code;
          // 设置回调结果为成功
          this.callbackResult = true;
        },
        // 授权失败回调
        onError: (errorCode, msg) => {
          Logger.i("authCallback", `failed, code: ${errorCode}, msg: ${msg}`);
          // 保存错误信息
          this.errMsg = msg
          this.errCode = errorCode
          // 设置回调结果为失败
          this.callbackResult = false;
        }
      })
    }
  }
  // 发布单图功能实现
  fn2 = () => {
    // 调用媒体选择方法,指定图片类型
    this.selectMedia<string>((url: string) => {
      // 创建单图分享请求对象
      let shareRequest = createSingleImagePublish(APPID);
      // 创建媒体URI列表
      let list: ArrayList<string> = new ArrayList();
      // 添加选中的图片URI
      list.add(url);
      // 设置媒体URI列表
      shareRequest.mediaUri = list;
      // 设置回调入口
      shareRequest.callbackLocalEntry = "EntryAbility";
      // 重要提示,这行代码不要复制
      shareRequest.harmonyAppId = harmonyAppID

      // 调用SDK分享接口
      kwaiOpenSdk.createApi().share(this.context, shareRequest, {
        // 分享成功回调
        onSuccess: (res) => {
          // 设置回调结果为成功
          this.callbackResult = true;
          Logger.i("shareCallback", "success.......");
        },
        // 分享失败回调
        onError: (errorCode, msg) => {
          // 设置回调结果为失败
          this.callbackResult = false;
          // 保存错误信息
          this.errMsg = msg
          this.errCode = errorCode
          Logger.i("shareCallback", `failed, code: ${errorCode}, msg: ${msg}`);
        }
      })
    }, photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE);
  }
  // 发布单视频功能实现
  fn3 = () => {
    // 调用媒体选择方法,指定视频类型
    this.selectMedia<string>((url: string) => {
      // 创建单视频分享请求对象
      let shareRequest = createSingleVideoPublish(APPID);
      // 创建媒体URI列表
      let list: ArrayList<string> = new ArrayList();
      // 添加选中的视频URI
      list.add(url);
      // 设置媒体URI列表
      shareRequest.mediaUri = list;
      // 设置回调入口
      shareRequest.callbackLocalEntry = "EntryAbility";
      // 重要提示,这行代码不要复制
      shareRequest.harmonyAppId = harmonyAppID
      // 调用SDK分享接口
      kwaiOpenSdk.createApi().share(this.context, shareRequest, {
        // 分享成功回调
        onSuccess: (res) => {
          // 设置回调结果为成功
          this.callbackResult = true;
          Logger.i("shareCallback", "success.......");
        },
        // 分享失败回调
        onError: (errorCode, msg) => {
          // 设置回调结果为失败
          this.callbackResult = false;
          // 保存错误信息
          this.errMsg = msg
          this.errCode = errorCode
          Logger.i("shareCallback", `failed, code: ${errorCode}, msg: ${msg}`);
        }
      })
    }, photoAccessHelper.PhotoViewMIMETypes.VIDEO_TYPE);
  }

  build() {
    Column({ space: 10 }) {
      Button("授权")
        .onClick(this.fn1)
      Button("发布单图")
        .onClick(this.fn2)
      Button("发布单视频")
        .onClick(this.fn3)
    }
    .height('100%')
    .width('100%')
  }

  // 媒体选择通用方法
  private selectMedia<T>(
    callback: (t: T) => void,
    type: photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE | photoAccessHelper.PhotoViewMIMETypes.VIDEO_TYPE,
    num: number = 1
  ) {
    // 创建照片选择选项
    let photoOptions = new photoAccessHelper.PhotoSelectOptions();
    // 设置MIME类型(图片或视频)
    photoOptions.MIMEType = type;
    // 设置最大选择数量
    photoOptions.maxSelectNumber = num;

    // 创建照片选择器
    let picker = new photoAccessHelper.PhotoViewPicker();
    // 调用选择方法
    picker.select(photoOptions).then((photoSelectResult: photoAccessHelper.PhotoSelectResult) => {
      // 获取选中的URI列表
      let uris: Array<string> = photoSelectResult.photoUris;
      if (uris.length > 0) {
        // 获取第一个URI
        let str = uris[0];
        // 提取文件名
        let fileName = str.substring(str.lastIndexOf('/'));
        // 构建目标文件路径
        let desFilePath = this.context.getApplicationContext().tempDir + fileName;
        // 打开源文件(只读)
        let srcFile = fileIo.openSync(str, fileIo.OpenMode.READ_ONLY);
        // 打开目标文件(写,如不存在则创建)
        let desFile = fileIo.openSync(desFilePath, fileIo.OpenMode.WRITE_ONLY | fileIo.OpenMode.CREATE);
        // 复制文件内容
        fileIo.copyFileSync(srcFile.fd, desFile.fd)
        // 回调处理,传递文件URI
        callback?.(fileUri.getUriFromPath(desFilePath) as T);
      } else {
        // 未选择资源时显示提示
        this.getUIContext().getPromptAction().showToast({
          message: '没有选择资源'
        })
      }
    }).catch((error: BusinessError) => {
      // 选择出错时显示提示
      this.getUIContext().getPromptAction().showToast({
        message: '选择资源error'
      })
    })
  }
}

参考文档

  1. @kwai_open_platform/opensdk(V1.0.1)

open.kuaishou.com/platformDoc...

  1. 快手接入鸿蒙应用指南

ohpm.openharmony.cn/#/cn/detail...

相关推荐
sure2822 小时前
在react native中实现短视频平台滑动视频播放组件
前端·react native
weibkreuz2 小时前
React开发者工具的下载及安装@4
前端·javascript·react
帅哥一天八碗米饭2 小时前
HarmonyOS ArkTS 实战:阅读器顶部栏“高度收缩 + 背景透明度过渡”(@AnimatableExtend 方案,能直接抄)
harmonyos
代码猎人2 小时前
link和@import有什么区别
前端
小肥宅仙女2 小时前
React + ECharts 多图表联动实战:从零实现 Tooltip 同步与锁定功能
前端·react.js·echarts
如果你好2 小时前
一文了解 Cookie、localStorage、sessionStorage的区别与实战案例
前端·javascript
鹏北海2 小时前
Vue3 + Axios 企业级请求封装实战:从零搭建完整的 HTTP 请求层
前端·vue.js·axios
帅哥一天八碗米饭2 小时前
HarmonyOS ArkTS:自动“缓存池复用监控日志”怎么做
harmonyos
前端无涯2 小时前
React父子组件回调传参避坑指南:从基础到进阶实践
前端·react.js