开源贡献指南:向HarmonyOS5 RN适配仓库提交PR的完整流程

爱学习的小齐哥哥
发布于 2025-6-11 11:37
浏览
0收藏

准备工作:开发环境搭建

  1. 基础环境配置

安装HarmonyOS开发工具

npm install -g @ohos/hpm-cli
hpm config set registry https://repo.harmonyos.com/npm/

安装React Native依赖

npm install -g react-native-cli
npx react-native init RNTestApp --template react-native-template-typescript

  1. 克隆适配仓库

Fork主仓库到个人账号

git clone https://github.com/{your-username}/react-native-harmony
cd react-native-harmony

添加官方上游仓库

git remote add upstream https://github.com/harmonyos/rn-harmony-adapter.git

代码修改实战流程

  1. 创建功能分支

git checkout -b fix/image-component

  1. 实现一个适配模块(示例:Image组件适配)

// src/components/ImageHarmony.tsx
import React from ‘react’;
import { requireNativeComponent, Platform } from ‘react-native’;

const RNTHarmonyImage = requireNativeComponent(‘RNTHarmonyImage’);

interface HarmonyImageProps {
source: { uri: string };
resizeMode?: ‘cover’ | ‘contain’ | ‘stretch’;
onLoad?: () => void;
onError?: (error: { nativeEvent: { error: string } }) => void;
}

const ImageHarmony: React.FC<HarmonyImageProps> = (props) => {
// 处理图片资源类型
const resolveUri = () => {
if (Platform.OS === ‘harmony’) {
// Harmony特定路径处理
return props.source.uri.replace(‘file://’, ‘/entry/resources/rawfile/’);
}
return props.source.uri;
};

return (
<RNTHarmonyImage
{…props}
source={{ uri: resolveUri() }}
onImageLoad={props.onLoad}
onImageError={props.onError}
/>
);
};

export default ImageHarmony;

  1. 添加原生端支持代码

// src/main/cpp/image/RNTHarmonyImage.cpp
#include “RNTHarmonyImage.h”
#include <hilog/log.h>

static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {
LOG_CORE, 0xD001800, “RNTHarmonyImage”
};

RNTHarmonyImage::RNTHarmonyImage(napi_env env, napi_value exports) {
napi_property_descriptor descriptors[] = {
DECLARE_NAPI_FUNCTION(“load”, Load),
DECLARE_NAPI_FUNCTION(“setResizeMode”, SetResizeMode)
};
napi_define_class(env, “RNTHarmonyImage”, NAPI_AUTO_LENGTH,
Constructor, nullptr,
sizeof(descriptors) / sizeof(*descriptors),
descriptors, &constructor_);
}

napi_value RNTHarmonyImage::Constructor(napi_env env, napi_callback_info info) {
// …构造器实现
}

napi_value RNTHarmonyImage::Load(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

// 获取图片路径
char uri[1024];
size_t strLength;
napi_get_value_string_utf8(env, args[0], uri, sizeof(uri), &strLength);

// 使用系统Image组件加载
auto image = std::make_shared<OHOS::Ace::Image>();
image->SetSrc(uri);

// 加载成功回调
napi_value jsCallback;
napi_create_function(env, "onImageLoad", NAPI_AUTO_LENGTH, 
                     [](napi_env env, napi_callback_info info) {}, 
                     nullptr, &jsCallback);

napi_value argv[] = { jsCallback };
napi_call_function(env, nullptr, args[0], 1, argv, nullptr);

return nullptr;

}

  1. 添加单元测试

// tests/components/ImageHarmony.test.tsx
import React from ‘react’;
import { render } from ‘@testing-library/react-native’;
import ImageHarmony from ‘…/…/src/components/ImageHarmony’;

describe(‘ImageHarmony Component’, () => {
it(‘handles local resources correctly’, () => {
const { getByTestId } = render(
<ImageHarmony
source={{ uri: ‘file:///entry/logo.png’ }}
testID=“test-image”
/>
);

const image = getByTestId('test-image');
expect(image.props.source.uri).toContain('/entry/resources/rawfile/');

});

it(‘triggers onLoad event’, () => {
const onLoadMock = jest.fn();
render(
<ImageHarmony
source={{ uri: ‘file:///entry/logo.png’ }}
onLoad={onLoadMock}
/>
);

// 模拟原生端加载成功
const event = new Event('onImageLoad');
fireEvent(getByTestId('test-image'), 'onImageLoad', event);

expect(onLoadMock).toHaveBeenCalledTimes(1);

});
});

测试与验证流程

  1. 本地调试脚本

#!/bin/bash

test-adapter.sh

构建TypeScript

npm run build

运行HarmonyOS模拟器

hdc shell am start -a com.example.rnapp

运行单元测试

npm test

启动调试服务器

npm run debug – --port 8088

安装测试应用

hdc install dist/rn-harmony-adapter.hap

  1. 测试覆盖率检查

生成测试覆盖率报告

npx jest --coverage

覆盖率不足时处理方案

if [ $(node -pe “require(‘./coverage/coverage-summary.json’).total.lines.pct < 85”) == “true” ]; then
echo “Coverage below 85% - adding tests…”

自动生成测试桩

npx jest-coverage-ratchet --threshold 85
exit 1
fi

提交PR规范

  1. 代码提交前检查

运行格式检查

npx lint-staged

修复代码风格问题

npm run fix

检查API兼容性

npm run api-check

  1. PR描述模板

该PR解决的问题

  • 修复React Native Image组件在HarmonyOS上的资源路径问题 (Issue #423)
  • 添加本地资源文件加载支持

技术解决方案

  1. 添加路径转换器处理资源定位
uri.replace('file://', '/entry/resources/rawfile/')
  1. 实现原生加载回调机制
napi_call_function(env, nullptr, args[0], 1, argv, nullptr);

测试验证

测试场景 结果
本地资源加载
网络资源加载 🔜
加载事件回调

兼容性检查

设备 HarmonyOS版本 结果
MatePad Pro 5.0
P50 Pro 4.0
WATCH 3 5.1 🔜

文档更新

更新了 docs/components/image.md 使用说明

  1. 提交命令

提交更改

git add src/components/ImageHarmony.tsx
git commit -m “fix(image): resolve local resource path issue”

推送到个人分支

git push origin fix/image-component

创建PR(需访问GitHub网页界面)

open https://github.com/harmonyos/rn-harmony-adapter/compare

PR审查后处理流程

  1. 响应审查建议

检出你的分支

git checkout fix/image-component

进行修改

…修改代码…

添加修改到上次提交

git add .
git commit --amend --no-edit

强制推送更新

git push origin fix/image-component -f

  1. 冲突解决方法

拉取上游最新代码

git fetch upstream main

变基到最新代码

git rebase upstream/main

  1. 合并后清理

删除本地分支

git checkout main
git branch -D fix/image-component

更新主仓库

git pull upstream main

重置本地fork仓库

git push origin main --force

最佳实践指南

  1. 模块化开发规范

// 推荐架构
src/
├── components/ // React组件
├── modules/ // 功能模块
├── natives/ // 原生模块
│ ├── harmonyos/ // HarmonyOS实现
│ └── android/ // Android实现(兼容)
└── utils/ // 公共工具

  1. 兼容性处理模式

// 多平台兼容代码示例
export const resolveResource = (uri: string) => {
if (Platform.OS === ‘harmony’) {
return uri.replace(‘file://’, ‘/entry/resources/rawfile/’);
}

if (Platform.OS === ‘android’) {
return res:/${uri.split('://')[1]};
}

return uri;
};

// 功能降级处理
export const getDeviceInfo = () => {
if (Platform.OS === ‘harmony’) {
return getHarmonyDeviceInfo(); // Harmony专用API
}

// 其他平台使用React Native实现
return {
deviceId: DeviceInfo.getUniqueId(),
brand: Platform.constants.Brand,
};
};

贡献者奖励机制

  1. 官方致谢途径

• 贡献者墙:在仓库README展示贡献者

• 特别标签:标注"First-time Contributor"等标签

• 证书认证:发放数字贡献证书(示例脚本生成)

generate_certificate.py

from PIL import Image, ImageDraw, ImageFont
from datetime import datetime

def generate_contribution_cert(name, contribution):
# 创建证书模板
img = Image.open(‘cert_template.png’)
draw = ImageDraw.Draw(img)

# 添加贡献者信息
font = ImageFont.truetype('HarmonySans.ttf', 60)
draw.text((500, 500), name, fill=(0, 0, 0), font=font)

# 添加贡献描述
draw.text((500, 700), contribution, fill=(0, 0, 0), font=font)

# 添加日期
date_str = datetime.now().strftime("%Y/%m/%d")
draw.text((1000, 1000), date_str, fill=(0, 0, 0), font=font)

# 保存证书
img.save(f'certificates/{name.replace(" ", "_")}_contrib.png')
  1. 持续贡献路线

graph TD
A[首次贡献] -->|修复问题单| B(基本贡献者)
B -->|提交3个PR| C[活跃贡献者]
C -->|模块维护| D[核心维护者]
D -->|架构设计| E[项目委员会]

常见问题解决方案

  1. 编译问题排错

日志分析脚本

#!/bin/bash

analyze-build-log.sh

LOG_FILE=${1:-build.log}

查找错误模式

grep -Ei ‘error:|fail|exception’ $LOG_FILE | head -n 10

分析资源问题

if grep -q ‘Resource not found’ $LOG_FILE; then
echo “资源未找到问题,尝试以下方案:”
echo “1. 检查resource目录是否存在”
echo “2. 运行’hpm res update’更新资源索引”
fi

  1. 许可证合规检查

许可证验证脚本

npx license-checker --summary --excludePrivatePackages

添加开源许可证头

for file in $(find src -name “.ts"); do
if ! grep -q “SPDX-License-Identifier” $file; then
echo "/
\n * SPDX-License-Identifier: MIT\n */” > temp.txt
cat $file >> temp.txt
mv temp.txt $file
fi
done

通过这个完整指南,开发者可以系统性地学习如何为HarmonyOS的React Native适配器贡献代码,解决社区提出的问题,共同推动跨平台开发技术生态的发展。

已于2025-7-18 19:20:17修改
收藏
回复
举报
回复
    相关推荐