• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# NativeBundle开发指导
2<!--Kit: Ability Kit-->
3<!--Subsystem: BundleManager-->
4<!--Owner: @wanghang904-->
5<!--Designer: @hanfeng6-->
6<!--Tester: @kongjing2-->
7<!--Adviser: @Brilliantry_Rui-->
8
9## 场景介绍
10
11开发者可以通过本指导了解在OpenHarmony应用中,如何使用Native Bundle接口获取应用自身相关信息。
12
13## 接口说明
14
15| 接口名                                                       | 描述                                     |
16| :----------------------------------------------------------- | :--------------------------------------- |
17| [OH_NativeBundle_GetCurrentApplicationInfo](../reference/apis-ability-kit/capi-native-interface-bundle-h.md#oh_nativebundle_getcurrentapplicationinfo) | 获取应用自身相关信息。          |
18| [OH_NativeBundle_GetAppId](../reference/apis-ability-kit/capi-native-interface-bundle-h.md#oh_nativebundle_getappid) | 获取自身应用的appId信息。 |
19| [OH_NativeBundle_GetAppIdentifier](../reference/apis-ability-kit/capi-native-interface-bundle-h.md#oh_nativebundle_getappidentifier) | 获取自身应用的appIdentifier信息。 |
20| [OH_NativeBundle_GetMainElementName](../reference/apis-ability-kit/capi-native-interface-bundle-h.md#oh_nativebundle_getmainelementname) | 获取自身应用入口的信息。 |
21| [OH_NativeBundle_GetCompatibleDeviceType](../reference/apis-ability-kit/capi-native-interface-bundle-h.md#oh_nativebundle_getcompatibledevicetype) | 获取自身应用适用的设备类型。 |
22| [OH_NativeBundle_IsDebugMode](../reference/apis-ability-kit/capi-native-interface-bundle-h.md#oh_nativebundle_isdebugmode) | 查询当前应用的调试模式。|
23| [OH_NativeBundle_GetModuleMetadata](../reference/apis-ability-kit/capi-native-interface-bundle-h.md#oh_nativebundle_getmodulemetadata) | 获取当前应用的元数据信息。 |
24
25
26## 开发步骤
27
28**1. 创建工程**
29
30![native](figures/rawfile1.png)
31
32
33**2. 添加依赖**
34
35创建完成后,DevEco Studio会在工程生成cpp目录,目录有types/libentry/index.d.tsnapi_init.cppCMakeLists.txt等文件。
36
371. 打开src/main/cpp/CMakeLists.txt,在target_link_libraries依赖中添加包管理的libbundle_ndk.z.so38
39    ```c++
40    target_link_libraries(entry PUBLIC libace_napi.z.so libbundle_ndk.z.so)
41    ```
42
432. 打开src/main/cpp/napi_init.cpp文件,添加头文件。
44
45    ```c++
46    //napi依赖头文件
47    #include "napi/native_api.h"
48    //NDK接口依赖头文件
49    #include "bundle/native_interface_bundle.h"
50    //free()函数依赖的基础库
51    #include <cstdlib>
52    ```
53
54**3. 修改源文件**
55
561. 打开src/main/cpp/napi_init.cpp文件,文件Init会对当前方法进行初始化映射,这里定义对外的接口。
57
58    ```c++
59    EXTERN_C_START
60    static napi_value Init(napi_env env, napi_value exports)
61    {
62        napi_property_descriptor desc[] = {
63            { "add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr },
64            { "getCurrentApplicationInfo", nullptr, GetCurrentApplicationInfo, nullptr, nullptr, nullptr, napi_default, nullptr},   // 新增方法 getCurrentApplicationInfo
65            { "getAppId", nullptr, GetAppId, nullptr, nullptr, nullptr, napi_default, nullptr},                                     // 新增方法 getAppId
66            { "getAppIdentifier", nullptr, GetAppIdentifier, nullptr, nullptr, nullptr, napi_default, nullptr},                     // 新增方法 getAppIdentifier
67            { "getMainElementName", nullptr, GetMainElementName, nullptr, nullptr, nullptr, napi_default, nullptr},                 // 新增方法 getMainElementName
68            { "getCompatibleDeviceType", nullptr, GetCompatibleDeviceType, nullptr, nullptr, nullptr, napi_default, nullptr},       // 新增方法 getCompatibleDeviceType
69            { "isDebugMode", nullptr, IsDebugMode, nullptr, nullptr, nullptr, napi_default, nullptr},                               // 新增方法 isDebugMode
70            { "getModuleMetadata", nullptr, GetModuleMetadata, nullptr, nullptr, nullptr, napi_default, nullptr}                    // 新增方法 getModuleMetadata
71        };
72        napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
73        return exports;
74    }
75    EXTERN_C_END
76    ```
77
782. 在src/main/cpp/napi_init.cpp文件中,增加对应的方法,如下所示:
79
80    ```c++
81    static napi_value GetCurrentApplicationInfo(napi_env env, napi_callback_info info);
82    static napi_value GetAppId(napi_env env, napi_callback_info info);
83    static napi_value GetAppIdentifier(napi_env env, napi_callback_info info);
84    static napi_value GetMainElementName(napi_env env, napi_callback_info info);
85    static napi_value GetCompatibleDeviceType(napi_env env, napi_callback_info info);
86    static napi_value IsDebugMode(napi_env env, napi_callback_info info);
87    static napi_value GetModuleMetadata(napi_env env, napi_callback_info info);
883. 在src/main/cpp/napi_init.cpp文件中获取Native的包信息对象,并转为js的包信息对象,即可在js侧获取应用的信息:
89
90    ```c++
91    static napi_value GetCurrentApplicationInfo(napi_env env, napi_callback_info info)
92    {
93        // 调用Native接口获取应用信息
94        OH_NativeBundle_ApplicationInfo nativeApplicationInfo = OH_NativeBundle_GetCurrentApplicationInfo();
95        napi_value result = nullptr;
96        napi_create_object(env, &result);
97        // Native接口获取的应用包名转为js对象里的bundleName属性
98        napi_value bundleName;
99        napi_create_string_utf8(env, nativeApplicationInfo.bundleName, NAPI_AUTO_LENGTH, &bundleName);
100        napi_set_named_property(env, result, "bundleName", bundleName);
101        // Native接口获取的指纹信息转为js对象里的fingerprint属性
102        napi_value fingerprint;
103        napi_create_string_utf8(env, nativeApplicationInfo.fingerprint, NAPI_AUTO_LENGTH, &fingerprint);
104        napi_set_named_property(env, result, "fingerprint", fingerprint);
105
106        // 最后为了防止内存泄漏,手动释放
107        free(nativeApplicationInfo.bundleName);
108        free(nativeApplicationInfo.fingerprint);
109        return result;
110    }
111
112    static napi_value GetAppId(napi_env env, napi_callback_info info)
113    {
114        // 调用Native接口获取应用appId
115        char* appId = OH_NativeBundle_GetAppId();
116        // Native接口转成nAppId返回
117        napi_value nAppId;
118        napi_create_string_utf8(env, appId, NAPI_AUTO_LENGTH, &nAppId);
119        // 最后为了防止内存泄漏,手动释放
120        free(appId);
121        return nAppId;
122    }
123
124    static napi_value GetAppIdentifier(napi_env env, napi_callback_info info)
125    {
126        // 调用Native接口获取应用appIdentifier
127        char* appIdentifier = OH_NativeBundle_GetAppIdentifier();
128        // Native接口转成nAppIdentifier返回
129        napi_value nAppIdentifier;
130        napi_create_string_utf8(env, appIdentifier, NAPI_AUTO_LENGTH, &nAppIdentifier);
131        // 最后为了防止内存泄漏,手动释放
132        free(appIdentifier);
133        return nAppIdentifier;
134    }
135
136    static napi_value GetMainElementName(napi_env env, napi_callback_info info)
137    {
138        // 调用Native接口获取应用入口的信息
139        OH_NativeBundle_ElementName elementName = OH_NativeBundle_GetMainElementName();
140        napi_value result = nullptr;
141        napi_create_object(env, &result);
142        // Native接口获取的应用包名转为js对象里的bundleName属性
143        napi_value bundleName;
144        napi_create_string_utf8(env, elementName.bundleName, NAPI_AUTO_LENGTH, &bundleName);
145        napi_set_named_property(env, result, "bundleName", bundleName);
146        // Native接口获取的模块名称转为js对象里的moduleName属性
147        napi_value moduleName;
148        napi_create_string_utf8(env, elementName.moduleName, NAPI_AUTO_LENGTH, &moduleName);
149        napi_set_named_property(env, result, "moduleName", moduleName);
150        // Native接口获取的ability名称转为js对象里的abilityName属性
151        napi_value abilityName;
152        napi_create_string_utf8(env, elementName.abilityName, NAPI_AUTO_LENGTH, &abilityName);
153        napi_set_named_property(env, result, "abilityName", abilityName);
154        // 最后为了防止内存泄漏,手动释放
155        free(elementName.bundleName);
156        free(elementName.moduleName);
157        free(elementName.abilityName);
158        return result;
159    }
160
161    static napi_value GetCompatibleDeviceType(napi_env env, napi_callback_info info)
162    {
163        // 调用Native接口获取应用deviceType
164        char* deviceType = OH_NativeBundle_GetCompatibleDeviceType();
165        // Native接口转成nDeviceType返回
166        napi_value nDeviceType;
167        napi_create_string_utf8(env, deviceType, NAPI_AUTO_LENGTH, &nDeviceType);
168        // 最后为了防止内存泄漏,手动释放
169        free(deviceType);
170        return nDeviceType;
171    }
172
173    static napi_value IsDebugMode(napi_env env, napi_callback_info info)
174    {
175        bool isDebug = false;
176        // 调用Native接口获取应用DebugMode的信息
177        bool isSuccess = OH_NativeBundle_IsDebugMode(&isDebug);
178        // 调用Native接口失败抛出异常
179        if (isSuccess == false) {
180            napi_throw_error(env, nullptr, "call failed");
181            return nullptr;
182        }
183        // Native接口转成debug返回
184        napi_value debug;
185        napi_get_boolean(env, isDebug, &debug);
186        return debug;
187    }
188
189    static napi_value GetModuleMetadata(napi_env env, napi_callback_info info)
190    {
191        size_t moduleCount = 0;
192        // 调用Native接口获取应用元数据的信息
193        OH_NativeBundle_ModuleMetadata* modules = OH_NativeBundle_GetModuleMetadata(&moduleCount);
194        if (modules == nullptr || moduleCount == 0) {
195            napi_throw_error(env, nullptr, "no metadata found");
196            return nullptr;
197        }
198
199        napi_value result;
200        napi_create_array(env, &result);
201
202        for (size_t i = 0; i < moduleCount; i++) {
203            napi_value moduleObj;
204            napi_create_object(env, &moduleObj);
205
206            // Native接口获取的模块名转为js对象里的moduleName属性
207            napi_value moduleName;
208            napi_create_string_utf8(env, modules[i].moduleName, NAPI_AUTO_LENGTH, &moduleName);
209            napi_set_named_property(env, moduleObj, "moduleName", moduleName);
210
211            napi_value metadataArray;
212            napi_create_array(env, &metadataArray);
213
214            for (size_t j = 0; j < modules[i].metadataArraySize; j++) {
215                napi_value metadataObj;
216                napi_create_object(env, &metadataObj);
217
218                napi_value name;
219                napi_value value;
220                napi_value resource;
221
222                napi_create_string_utf8(env, modules[i].metadataArray[j].name, NAPI_AUTO_LENGTH, &name);
223                napi_create_string_utf8(env, modules[i].metadataArray[j].value, NAPI_AUTO_LENGTH, &value);
224                napi_create_string_utf8(env, modules[i].metadataArray[j].resource, NAPI_AUTO_LENGTH, &resource);
225
226                // Native接口获取的元数据名称转为js对象里的name属性
227                napi_set_named_property(env, metadataObj, "name", name);
228                // Native接口获取的元数据值名称转为js对象里的value属性
229                napi_set_named_property(env, metadataObj, "value", value);
230                // Native接口获取的元数据资源转为js对象里的resource属性
231                napi_set_named_property(env, metadataObj, "resource", resource);
232
233                napi_set_element(env, metadataArray, j, metadataObj);
234            }
235
236            napi_set_named_property(env, moduleObj, "metadata", metadataArray);
237            napi_set_element(env, result, i, moduleObj);
238        }
239
240        // 最后为了防止内存泄漏,手动释放
241        for (size_t i = 0; i < moduleCount; i++) {
242            free(modules[i].moduleName);
243            for (size_t j = 0; j < modules[i].metadataArraySize; j++) {
244                free(modules[i].metadataArray[j].name);
245                free(modules[i].metadataArray[j].value);
246                free(modules[i].metadataArray[j].resource);
247            }
248            free(modules[i].metadataArray);
249        }
250        free(modules);
251        return result;
252    }
253    ```
254
255**4. 接口暴露**
256
257src/main/cpp/types/libentry/Index.d.ts文件中,声明暴露接口。
258
259```js
260export const add: (a: number, b: number) => number;
261export const getCurrentApplicationInfo: () => object;   // 新增暴露方法 getCurrentApplicationInfo
262export const getAppId: () => string;                    // 新增暴露方法 getAppId
263export const getAppIdentifier: () => string;            // 新增暴露方法 getAppIdentifier
264export const getMainElementName: () => object;          // 新增暴露方法 getMainElementName
265export const getCompatibleDeviceType: () => string;     // 新增暴露方法 getCompatibleDeviceType
266export const isDebugMode: () => string;                 // 新增暴露方法 isDebugMode
267export const getModuleMetadata: () => object;           // 新增暴露方法 getModuleMetadata
268```
269
270**5. js侧调用**
271
2721. 打开src\main\ets\pages\index.ets, 导入"libentry.so"。
273
274
2752. 调用Native接口打印出获取的信息内容。示例如下:
276
277    ```js
278    import { hilog } from '@kit.PerformanceAnalysisKit';
279    import testNapi from 'libentry.so';
280
281    const DOMAIN = 0x0000;
282
283    @Entry
284    @Component
285    struct Index {
286    @State message: string = 'Hello World';
287
288    build() {
289        Row() {
290        Column() {
291            Text(this.message)
292            .fontSize($r('app.float.page_text_font_size'))
293            .fontWeight(FontWeight.Bold)
294            .onClick(() => {
295                this.message = 'Welcome';
296                hilog.info(DOMAIN, 'testTag', 'Test NAPI 2 + 3 = %{public}d', testNapi.add(2, 3));
297                let appInfo = testNapi.getCurrentApplicationInfo();
298                console.info("bundleNDK getCurrentApplicationInfo success, data is " + JSON.stringify(appInfo));
299                let appId = testNapi.getAppId();
300                console.info("bundleNDK getAppId success, appId is " + appId);
301                let appIdentifier = testNapi.getAppIdentifier();
302                console.info("bundleNDK getAppIdentifier success, appIdentifier is " + appIdentifier);
303                let mainElement = testNapi.getMainElementName();
304                console.info("bundleNDK getMainElementName success, data is " + JSON.stringify(mainElement));
305                let deviceType = testNapi.getCompatibleDeviceType();
306                console.info("bundleNDK getCompatibleDeviceType success, deviceType is " + deviceType);
307                let isDebugMode = testNapi.isDebugMode();
308                console.info("bundleNDK isDebugMode success, isDebugMode is " + isDebugMode);
309                let moduleMetadata = testNapi.getModuleMetadata();
310                console.info("bundleNDK getModuleMetadata success, data is " + JSON.stringify(moduleMetadata));
311            })
312        }
313        .width('100%')
314        }
315        .height('100%')
316    }
317    }
318    ```
319
320关于包管理NDK接口说明,可参考[Native_Bundle模块介绍](../reference/apis-ability-kit/capi-native-bundle.md)。
321