开发环境搭建

  • 环境搭建

    1. 安装 DevEco Studio,详情请参考开发工具官网

    2. 设置 DevEco Studio 开发环境,DevEco Studio 开发环境需要依赖于网络环境,需要连接上网络才能确保工具的正常使用,详情请参考配置开发环境

    3. 开发者可以参考以下链接,完成设备调试的相关配置:

    4. hdc环境配置

      hdc 是 OpenHarmony 为开发人员提供的用于调试的命令行工具,鸿蒙 React Native 工程使用 hdc 进行真机调试。hdc 工具通过 OpenHarmony SDK 获取,存放于 SDK 的 toolchains 目录下,请将 {DevEco Studio安装路径}/sdk/{SDK版本}/openharmony/toolchains 的完整路径添加到环境变量中。

      • windows 环境变量设置方法:

        a. 在此电脑 > 属性 > 高级系统设置 > 高级 > 环境变量中,编辑系统变量path,添加hdc工具路径。

        b. 在此电脑 > 属性 > 高级系统设置 > 高级 > 环境变量中,添加 HDC 端口变量名为:HDC_SERVER_PORT,变量值可设置为任意未被占用的端口,如 7035

        环境配置-hdc

      • macOS 环境变量设置方法:

        a. 打开终端,执行以下命令,打开 .bash_profile 文件。

        vi ~/.bash_profile
        

        输入以下内容,在 PATH 路径下添加 HDC 工具路径和添加 HDC_SERVER_PORT 端口信息:

        export PATH="/Applications/DevEco-Studio.app/Contents/sdk/{版本路径}/openharmony/toolchains:$PATH" # 按照实际 SDK 安装路径配置,需要选择{显示包内容}
        
        HDC_SERVER_PORT=7035 
        launchctl setenv HDC_SERVER_PORT $HDC_SERVER_PORT 
        export HDC_SERVER_PORT
        

        HDC 端口变量名为:HDC_SERVER_PORT,变量值可设置为任意未被占用的端口,如 7035

        b. 编辑完成后,单击 Esc 键退出编辑模式,然后输入 “wq”,单击 enter 键保存。

        c. 执行以下命令使配置的环境变量生效:

        source ~/.bash_profile
        
    5. 配置 CAPI 版本环境变量

      当前RN框架提供的 Demo 工程默认为 CAPI 版本,您需要配置环境变量 RNOH_C_API_ARCH = 1

      • Windows 环境:

        此电脑 > 属性 > 高级系统设置 > 高级 > 环境变量中,在系统变量中点击新建,添加变量名为:RNOH_C_API_ARCH,变量值为 1

        image

      • Mac环境:

        a. 打开终端应用程序(Terminal),您可以在"应用程序"文件夹的"实用工具"文件夹中找到它。在终端中,输入以下命令来设置环境变量:

        export RNOH_C_API_ARCH=1
        

        这将创建一个名为 RNOH_C_API_ARCH 的环境变量,并将其设置为 1

        b. 确认环境变量是否成功设置。在终端中输入以下命令:

        echo $RNOH_C_API_ARCH
        

        如果输出为 1,则表示环境变量已成功设置。

        c. 如果您希望在每次打开终端时都自动设置该环境变量,可以将上述 export 命令添加到你的 bash 配置文件(例如~/.bash_profile、~/.bashrc 或 ~/.zshrc)。编辑相应的文件,并在末尾添加以下行:

        export RNOH_C_API_ARCH=1
        

        d. 保存文件并关闭编辑器,重新打开终端,检查环境变量是否仍然设置为 1:

        echo $RNOH_C_API_ARCH
        

        如果输出为 1,则表示环境变量已成功设置。

    6. 编辑用户级 .npmrc 配置文件

    为了使用加速 npm 包的下载,可以配置镜像源;如果关闭 SSL 证书校验还可以进一步加速下载,但是这会降低安全性,需用户评估后再使用。配置文件位置在 C:\Users\用户名\.npmrc(Windows)或者 ~/.npmrc(macOS),如果没有则手动创建。供参考的 .npmrc 配置文件内容如下:

    strict-ssl=false
    sslVerify=false
    registry=https://repo.huaweicloud.com/repository/npm/
    

    修改 registry 后需执行 npm cache clean --force 清理缓存,以确保新的 registry 生效。

    1. 使用约束

      如果您需要自定义 CMakeLists.txt,请将 so 命名为 rnoh_app

      add_library(rnoh_app SHARED
          ···
          "${RNOH_CPP_DIR}/RNOHAppNapiBridge.cpp"
      )
      
    2. 补充说明

      完成以上环境配置即可进行鸿蒙的 React Native 项目开发,安卓和 iOS 的 React Native 完整环境搭建请参考 React Native 官网环境搭建

创建React Native工程

​ 本章节主要介绍 React Native 工程的初始化,安装鸿蒙依赖包,并成功运行的过程。

创建新项目

​可选择一个目录,例如 D 盘根目录,使用 @react-native-community/cli 创建一个名为 “AwesomeProject” 的新项目。该工具无需全局安装,可直接通过 node 自带的 npx 执行。当前 React Native for OpenHarmony 基于社区 RN 0.84.1 适配,请通过 --version 指定 RN 版本:

npx @react-native-community/cli@latest init AwesomeProject --version 0.84.1

说明npx react-native init 已废弃,请勿再使用。若出现 NPX has cached version != current release 警告,可忽略;该警告不影响项目创建。

环境搭建-AwesomeProject

​该命令在 mac 环境下初始化 React Native 项目时会下载 iOS 依赖库,耗时较长,开发者可以选择执行以下命令跳过该过程,后续根据需要自行下载,不影响鸿蒙项目开发:

npx @react-native-community/cli@latest init AwesomeProject --version 0.84.1 --skip-install

环境搭建-mac-AwesomeProject

安装鸿蒙依赖包并生成bundle

本节中使用的各类文件的版本配套关系,可以参考 React Native鸿蒙化版本信息

在本节中,您可以按照本节中的操作一步一步完成环境的搭建,也可以直接使用 templates/AwesomeProjectReplace 文件夹 中的对应文件进行一一替换,修改版本信息并运行。 注:如果要使用Codegen,请在此处配置Codegen相关命令,详细请参考 Codegen

下载并安装鸿蒙化依赖

  1. 打开 AwesomeProject 目录下的 package.json,在 scripts 下新增 OpenHarmony 的依赖:

    {
     "name": "AwesomeProject",
     "version": "0.0.1",
     "private": true,
     "scripts": {
       "android": "react-native run-android",
       "ios": "react-native run-ios",
       "lint": "eslint .",
       "start": "react-native start",
       "test": "jest",
    +    "dev": "react-native bundle-harmony --dev"
     },
     "dependencies": {
       "react": "19.2.3",
       "react-native": "0.84.1"
     },
     "devDependencies": {
       "@babel/core": "^7.25.2",
       "@babel/preset-env": "^7.25.3",
       "@babel/runtime": "^7.25.0",
       "@react-native-community/cli": "20.1.0",
       "@react-native-community/cli-platform-android": "20.1.0",
       "@react-native-community/cli-platform-ios": "20.1.0",
       "@react-native/babel-preset": "0.84.1",
       "@react-native/eslint-config": "0.84.1",
       "@react-native/metro-config": "0.84.1",
       "@react-native/typescript-config": "0.84.1",
       "@types/jest": "^29.5.13",
       "@types/react": "^19.2.0",
       "@types/react-test-renderer": "^19.1.0",
       "eslint": "^8.19.0",
       "jest": "^29.6.3",
       "prettier": "2.8.8",
       "react-test-renderer": "19.2.3",
       "typescript": "^5.8.3"
     },
     "engines": {
       "node": ">= 22.11.0"
     }
    }
    
  2. AwesomeProject 目录下运行安装依赖包命令:

    npm install @react-native-oh/react-native-harmony@x.x.x @react-native-oh/react-native-harmony-cli --legacy-peer-deps
    

    注意:

    1. 指令中@x.x.x用于指定下载的版本, 版本可以参考React Native鸿蒙化版本信息
  1. 本地安装鸿蒙化依赖,请参考如何使用本地安装鸿蒙化依赖
  2. 如何从本地依赖切换至远程依赖,请参考如何从本地依赖切换至远程依赖环境搭建-依赖下载

运行指令并生成bundle

  1. 打开 AwsomeProject\metro.config.js,并添加 OpenHarmony 的适配代码。配置文件的详细介绍,可以参考React Native 中文网。修改完成后的文件内容如下:

    const {mergeConfig, getDefaultConfig} = require('@react-native/metro-config');
    const {createHarmonyMetroConfig} = require('@react-native-oh/react-native-harmony/metro.config');
    
    /**
    * @type {import("metro-config").ConfigT}
    */
    const config = {
      transformer: {
        getTransformOptions: async () => ({
          transform: {
            experimentalImportSupport: false,
            inlineRequires: true,
          },
        }),
      },
    };
    
    module.exports = mergeConfig(getDefaultConfig(__dirname), createHarmonyMetroConfig({
      reactNativeHarmonyPackageName: '@react-native-oh/react-native-harmony',
    }), config);
    
  2. 在 AwesomeProject 目录下运行生成 bundle 文件的命令。运行成功后,会在 AwesomeProject/harmony/entry/src/main/resources/rawfile 目录下生成 bundle.harmony.jsassets 文件夹,assets 用来存放图片(如果 bundle 中不涉及本地图片,则没有 assets 文件夹)。

    npm run dev
    

    环境搭建-生成bundle

    如果运行时报错 “'react-native'不是内部或外部命令,也不是可运行的程序或批处理文件。”,请重新运行 npm install 命令。

  3. 您也可以使用 Metro 服务来加载 bundle 包。具体使用方式,可以参考Metro热加载

创建鸿蒙工程

本章节主要介绍了鸿蒙工程的创建,并加载 React Native 相关的依赖包和 bundle 包,最终完成鸿蒙工程的运行的过程。

您可以按照本节中的操作一步一步完成环境的搭建,也可以直接使用 templates/MyApplicationReplace 文件夹 中的对应文件进行一一替换,修改版本信息并运行。

新建工程或者在已有工程中集成

​ 下面演示在新建工程中集成。点击 File > New > Create Project,选择创建 Empty Ability 工程,如图所示:

环境搭建-EmptyAbility

​ 点击 Next 按钮,并在 Compile SDK 中选择 API17(RNOH 0.84.1 最低要求,需 DevEco Studio 6.1.0 及以上),创建一个名为 “MyApplication” 的项目。注意项目路径不要太长,如图所示:

环境搭建-version

​ 连接真机,点击 File > Project Structure,在弹窗界面点击 Signing Configs,勾选 Support HarmonyOSAutomatically generate signature,然后点击 Sign In 登录华为账号,并签名。

环境搭建-signing

添加 React Native 配置

entry 目录下执行以下命令:

ohpm i @rnoh/react-native-openharmony@x.x.x

执行完成后会在工程级目录以及模块级目录下生成 oh_modules 文件夹。

注意:

  1. 指令中@x.x.x用于指定下载的版本, 版本可以参考React Native鸿蒙化版本信息
  2. 由于 har 包比较大,这一步耗时会比较长,务必保证 ohpm install 和 IDE 自发的 SyncData 全都完成,否则会导致编译报错。
  3. 如何在三方库或自定义module中引入rnoh的依赖,请参考文档

在原生工程中集成RNOH

补充CPP侧代码

  1. MyApplication/entry/src/main 目录下新建 cpp 文件夹。
  2. 在 cpp 目录下新增 CMakeLists.txt,并将 RNOH 的适配层代码添加到编译构建中生成 librnoh_app.so
    project(rnapp)
    cmake_minimum_required(VERSION 3.4.1)
    set(CMAKE_SKIP_BUILD_RPATH TRUE)
    set(OH_MODULE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules")
    set(RNOH_APP_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
    
    set(RNOH_CPP_DIR "${OH_MODULE_DIR}/@rnoh/react-native-openharmony/src/main/cpp")
    set(RNOH_GENERATED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/generated")
    set(CMAKE_ASM_FLAGS "-Wno-error=unused-command-line-argument -Qunused-arguments")
    set(CMAKE_CXX_FLAGS "-fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -s -fPIE -pie")
    add_compile_definitions(WITH_HITRACE_SYSTRACE)
    set(WITH_HITRACE_SYSTRACE 1) # for other CMakeLists.txt files to use
    
    add_subdirectory("${RNOH_CPP_DIR}" ./rn)
    
    add_library(rnoh_app SHARED
        "./PackageProvider.cpp"
        "${RNOH_CPP_DIR}/RNOHAppNapiBridge.cpp"
    )
    
    target_link_libraries(rnoh_app PUBLIC rnoh)
    
  3. 在 cpp 目录下新增 PackageProvider.cpp,该文件需要满足以下要求:
    • 需要导入 RNOH/PackageProvider
    • 实现 getPackages 方法,用于创建三方库或自定义 TurboModule 或 Fabric 的 package 对象。

    此处不涉及三方库与自定义 TurboModule 或组件,需要返回空数组。

    #include "RNOH/PackageProvider.h"
    
    using namespace rnoh;
    
    std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) {
        return {};
    }
    
  4. 打开 MyApplicaton\entry\build-profile.json5,将 cpp 中的代码添加到鸿蒙的编译构建任务中;如果在 x86_64 架构的模拟器上运行应用,需在 externalNativeOptions 配置中额外添加 abiFilters 字段,并包含 x86_64 架构参数,如下所示,abiFilters 字段当前被注释,默认仅构建适用于 arm64-v8a 架构的版本。详细介绍可以参考模块级build-profile.json5
    {
     "apiType": "stageMode",
     "buildOption": {
    +   "externalNativeOptions": {
    +      "path": "./src/main/cpp/CMakeLists.txt",
    +      "arguments": "",
    +      "cppFlags": "",
    +      // "abiFilters": ["arm64-v8a", "x86_64"]
    +    }
     },
     "targets": [
       {
         "name": "default"
       },
       {
         "name": "ohosTest",
       }
     ]
    }
    

补充ArkTS侧的代码

  1. 打开 MyApplicaton\entry\src\main\ets\entryability\EntryAbility.ets,引入并使用 RNAbility,该文件需要满足以下的要求:

    • 需要重写 getPagePath,返回程序的入口 page。
    import { RNAbility } from '@rnoh/react-native-openharmony';
    
    export default class EntryAbility extends RNAbility {
      getPagePath() {
        return 'pages/Index';
      }
    }
    
    • 如果需要扩展使用对应的生命周期函数
      • 请在代码中调用 super(由于 RNAbility 在生命周期函数中进行了对应的操作,因此建议使用 super 以确保原有功能不丢失)。
      • 需确保函数的参数列表与父类保持兼容。
      • 建议添加 override 关键字,以提升代码可读性并增强编译器检查。
    import { RNAbility } from '@rnoh/react-native-openharmony';
    
    export default class EntryAbility extends RNAbility {
      getPagePath() {
        return 'pages/Index';
      }
    
      override onCreate(want: Want): void {
        super.onCreate(want);
        hilog.info(0x0000, 'testTag', '%{public}s', 'EntryAbility onCreate');
      }
    }
    
  2. MyApplicaton\entry\src\main\ets 目录下新增 RNPackagesFactory.ets,该文件需要满足以下要求:

    • @rnoh/react-native-openharmony 导入 RNPackageContextRNPackage
    • 在文件中导出 createRNPackages 方法,用于创建三方库或自定义 TurboModule、Fabric的package 对象。

    此处不涉及三方库与自定义TurboModule或组件,需要返回空数组。

    import { RNPackageContext, RNPackage } from '@rnoh/react-native-openharmony/ts';
    export function createRNPackages(ctx: RNPackageContext): RNPackage[] {
      return [];
    }
    
  3. 打开 MyApplicaton\entry\src\main\ets\pages\Index.ets,添加RNOH的使用代码,修改后如下:

    RNApp的参数appKey需要与RN工程中AppRegistry.registerComponent注册的appName保持一致,否则会导致白屏。

    import {
      AnyJSBundleProvider,
      ComponentBuilderContext,
      FileJSBundleProvider,
      MetroJSBundleProvider,
      ResourceJSBundleProvider,
      RNApp,
      RNOHErrorDialog,
      RNOHLogger,
      TraceJSBundleProviderDecorator,
      RNOHCoreContext
    } from '@rnoh/react-native-openharmony';
    import { createRNPackages } from '../RNPackagesFactory';
    
    @Builder
    export function buildCustomRNComponent(ctx: ComponentBuilderContext) {}
    
    const wrappedCustomRNComponentBuilder = wrapBuilder(buildCustomRNComponent)
    
    @Entry
    @Component
    struct Index {
      @StorageLink('RNOHCoreContext') private rnohCoreContext: RNOHCoreContext | undefined = undefined
      @State shouldShow: boolean = false
      private logger!: RNOHLogger
    
      aboutToAppear() {
        this.logger = this.rnohCoreContext!.logger.clone("Index")
        const stopTracing = this.logger.clone("aboutToAppear").startTracing();
    
        this.shouldShow = true
        stopTracing();
      }
    
      onBackPress(): boolean | undefined {
        // NOTE: this is required since `Ability`'s `onBackPressed` function always
        // terminates or puts the app in the background, but we want Ark to ignore it completely
        // when handled by RN
        this.rnohCoreContext!.dispatchBackPress()
        return true
      }
    
      build() {
        Column() {
          if (this.rnohCoreContext && this.shouldShow) {
            if (this.rnohCoreContext?.isDebugModeEnabled) {
              RNOHErrorDialog({ ctx: this.rnohCoreContext })
            }
            RNApp({
              rnInstanceConfig: {
                createRNPackages,
                enableNDKTextMeasuring: true, // 该项必须为true,用于开启NDK文本测算
                enableBackgroundExecutor: false,
                enableCAPIArchitecture: true, // 该项必须为true,用于开启CAPI
                arkTsComponentNames: []
              },
              initialProps: { "foo": "bar" } as Record<string, string>,
              appKey: "AwesomeProject",
              wrappedCustomRNComponentBuilder: wrappedCustomRNComponentBuilder,
              onSetUp: (rnInstance) => {
                rnInstance.enableFeatureFlag("ENABLE_RN_INSTANCE_CLEAN_UP")
              },
              jsBundleProvider: new TraceJSBundleProviderDecorator(
                new AnyJSBundleProvider([
                  new MetroJSBundleProvider(),
                  // NOTE: to load the bundle from file, place it in
                  // `/data/app/el2/100/base/com.rnoh.tester/files/bundle.harmony.js`
                  // on your device. The path mismatch is due to app sandboxing on OpenHarmony
                  new FileJSBundleProvider('/data/storage/el2/base/files/bundle.harmony.js'),
                  new ResourceJSBundleProvider(this.rnohCoreContext.uiAbilityContext.resourceManager, 'hermes_bundle.hbc'),
                  new ResourceJSBundleProvider(this.rnohCoreContext.uiAbilityContext.resourceManager, 'bundle.harmony.js')
                ]),
                this.rnohCoreContext.logger),
            })
          }
        }
        .height('100%')
        .width('100%')
      }
    }
    

加载bundle包

​ 在上一章节中已经完成了 bundle 文件的生成,接下来将它加载到 DevEco Studio 中以运行 MyApplication 项目。加载 bundle 有三种方式:

  • 方式一:本地加载 bundle。将 bundle 文件和 assets 图片放在 entry/src/main/resources/rawfile 路径下,在 entry/src/main/ets/pages/Index.ets 中使用。

  • 方式二:使用 Metro 服务加载 bundle。详细流程参考Metro热加载

  • 方式三:加载沙箱目录的bundle:

    • 应用沙箱是一种以安全防护为目的的隔离机制,避免数据受到恶意路径穿越访问。在这种沙箱的保护机制下,应用可见的目录范围即为“应用沙箱目录”。

    • 开发者在应用开发调试时,需要向应用沙箱下推送一些文件以期望在应用内访问或测试,此时有两种方式:

      − 第一种:可以通过 DevEco Studio 向应用安装路径中放入目标文件,详见应用安装资源访问

      − 第二种:在具备设备环境时,可以使用另一种更为灵活的方式,通过 hdc 工具来向设备中应用沙箱路径推送文件。推送命令如下,其中,沙箱路径可通过向应用沙箱推送文件查询

      hdc file send ${待推送文件的本地路径} ${沙箱路径}
      
    • 加载沙箱目录 bundle,需要在 RNApp 的 jsBundlePrivider 参数中使用 new FileJSBundleProvider('bundlePath') 将 bundle 注册进框架,并运行 bundle。

在上一章节的 MyApplicaton\entry\src\main\ets\pages\Index.ets 文件中,创建 RNApp 时传入 jsBundleProvider 用于加载 bundle。jsBundleProviderAnyJSBundleProvider 传入了 FileJSBundleProvider,用于沙箱目录加载 bundle

启动并运行工程

​ 使用 DevEco Studio 运行 MyApplication 工程。执行完成后,控制台如图所示:

环境搭建-run

全量编译 C++ 代码耗时较长,请耐心等待。

release包使用

执行完'npm i @react-native-oh/react-native-harmony@x.x.x'命令后,在生成的node_modules/@react-native-oh/react-native-harmony中即可获取release包。建议在release模式下使用。

目前的RNOH中会有两个release包,主要区别如下:

  • react_native_openharmony_release.har: 同0.72分支中的react_native_openharmony_release.har一样,这个包是在release模式下构建,cpp代码会经过编译转换成.so动态库,.ts和.ets文件保留源码形式;
  • react_native_openharmony_release2.har: 在release模式下构建,cpp代码会经过编译转换成.so动态库,同时.ts和.ets文件也会经过编译转换成.abc字节码文件,因此我们称它为字节码格式的release包,后续我们会主推字节码格式的release包。

这两种包在使用上略有区别,详细请看下面说明:

  1. MyApplication 目录下新建 libs 文件夹,将 react_native_openharmony_release.harreact_native_openharmony_release2.har 放入该目录。

  2. 打开 MyApplication/entry 下的 oh-package.json5,替换 har 包的依赖为对应版本的 release 包:

    {
      "name": "entry",
      "version": "1.0.0",
      "description": "Please describe the basic information.",
      "main": "",
      "author": "",
      "license": "",
      "dependencies": {
    +     "@rnoh/react-native-openharmony": "file:../libs/react_native_openharmony_release2.har"
      }
    }
    
  3. 根据下面的改动调整 MyApplication/entry/src/main/cpp/CMakeLists.txt 文件:

    set(OH_MODULE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules")
    set(RNOH_APP_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
    
    - set(RNOH_CPP_DIR "${OH_MODULE_DIR}/@rnoh/react-native-openharmony/src/main/cpp")
    + set(RNOH_CPP_DIR "${OH_MODULE_DIR}/@rnoh/react-native-openharmony/include")
    set(RNOH_GENERATED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/generated")
    set(CMAKE_ASM_FLAGS "-Wno-error=unused-command-line-argument -Qunused-arguments")
    set(CMAKE_CXX_FLAGS "-fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -s -fPIE -pie")
    add_compile_definitions(WITH_HITRACE_SYSTRACE)
    set(WITH_HITRACE_SYSTRACE 1) # for other CMakeLists.txt files to use
    
    - add_subdirectory("${RNOH_CPP_DIR}" ./rn)
    + include("${RNOH_CPP_DIR}/react-native-harmony.cmake")
    
  4. MyApplication/build-profile.json5 中的 useNormalizedOHMUrl 设置成 true(如果您用的是 react_native_openharmony_release.har 可以忽略此步骤):

    {
      "app": {
        "products": [
          {
            "name": "default",
            "signingConfig": "default",
            "compatibleSdkVersion": "5.0.1(13)",
            "runtimeOS": "HarmonyOS",
    +       "buildOption": {
    +         "strictMode": {
    +           "useNormalizedOHMUrl": true
    +         }
    +       }
          }
        ],
    
  5. MyApplication/entryoh_modules 文件夹删除,点击 entry 文件夹,再点击顶部菜单栏的 build>Clean Project 清除项目缓存。

  6. 点击顶部菜单栏的 File > Sync and Refresh Project 来执行 ohpm install,执行完成后会在 entry 目录下生成 oh_modules 文件夹。

  7. 点击顶部菜单栏的 Run>Run 'entry' 运行工程,运行成功后截图如下: release包运行成功