1# In-Application HSP Development 2 3An in-application Harmony Shared Package (HSP) is a file used for code and resource sharing within an application (called the host application) and can only be invoked by a HAP or HSP of the same application. 4The in-application HSP is released with the Application Package (App Pack) of the host application, shares a process with the host application, and has the same bundle name and lifecycle as the host application. 5 6## Developing an In-Application HSP 7 8[Create an HSP module in DevEco Studio](https://developer.harmonyos.com/cn/docs/documentation/doc-guides-V3/hsp-0000001521396322-V3#section7717162312546). In this example, an HSP module named **library** is created. The basic project directory structure is as follows: 9``` 10library 11├── src 12│ └── main 13│ ├── ets 14│ │ ├── pages 15│ │ └── index.ets 16│ ├── resources 17│ └── module.json5 18└── oh-package.json5 19``` 20 21### Exporting TS Classes and Methods 22Use **export** to export TS classes and methods. The sample code is as follows: 23```ts 24// library/src/main/ets/utils/test.ts 25export class Log { 26 static info(msg: string) { 27 console.info(msg); 28 } 29} 30 31export function add(a: number, b: number) { 32 return a + b; 33} 34 35export function minus(a: number, b: number) { 36 return a - b; 37} 38``` 39In the entry point file **index.ets**, declare the APIs to be exposed. 40```ts 41// library/src/main/ets/index.ets 42export { Log, add, minus } from './utils/test' 43``` 44 45### Exporting ArkUI Components 46Use **export** to export ArkUI components. The sample code is as follows: 47```ts 48// library/src/main/ets/components/MyTitleBar.ets 49@Component 50export struct MyTitleBar { 51 build() { 52 Row() { 53 Text($r('app.string.library_title')) 54 .fontColor($r('app.color.white')) 55 .fontSize(25) 56 .margin({left:15}) 57 } 58 .width('100%') 59 .height(50) 60 .padding({left:15}) 61 .backgroundColor('#0D9FFB') 62 } 63} 64``` 65In the entry point file **index.ets**, declare the APIs to be exposed. 66```ts 67// library/src/main/ets/index.ets 68export { MyTitleBar } from './components/MyTitleBar' 69``` 70 71### Accessing Resources in an HSP Through $r 72More often than not, you may need to use resources, such as strings and images, in components. For components in an HSP, such resources are typically placed in the HSP package, rather than in the package where the HSP is invoked, for the purpose of complying with the principle of high cohesion and low coupling. 73 74In a project, application resources are referenced in the $r/$rawfile format. You can use **$r**/**$rawfile** to access resources in the **resources** directory of the current module. For example, you can use **$r("app.media.example")** to access the **src/main/resources/base/media/example.png** image stored in the **resources** directory. For details about how to use **$r**/**$rawfile**, see [Resource Access: Application Resources](./resource-categories-and-access.md#application-resources). 75 76To avoid reference errors, do not use relative paths. For example, if you use **Image("../../resources/base/media/example.png")**, the image actually used will be the one in the directory of the module that invokes the HSP. That is, if the module that invokes the HSP is **entry**, then the image used will be **entry/src/main/resources/base/media/example.png**. 77 78```ts 79// library/src/main/ets/pages/Index.ets 80// Correct 81Image($r("app.media.example")) 82 .width("100%") 83// Incorrect 84Image("../../resources/base/media/example.png") 85 .width("100%") 86``` 87 88### Exporting Resources from an HSP 89When resources in an HSP need to be exported for cross-package access, it is recommended that a resource manager class be implemented to encapsulate the exported resources. In this way: 90- You can keep resources well under your control, eliminating the need for exporting resources that do not need to be exposed. 91- The invoking module does not need to be aware of the internal resource names of the HSP, or make adaptation to changes in these internal resource names. 92 93The implementation is as follows: 94 95Implement the **ResManager** class for encapsulating resources to be exported. 96```ts 97// library/src/main/ets/ResManager.ets 98export class ResManager{ 99 static getPic(): Resource{ 100 return $r("app.media.pic"); 101 } 102 static getDesc(): Resource{ 103 return $r("app.string.shared_desc"); 104 } 105} 106``` 107 108In the entry point file **index.ets**, declare the APIs to be exposed. 109```ts 110// library/src/main/ets/index.ets 111export { ResManager } from './ResManager' 112``` 113 114### Exporting Native Methods 115The HSP can contain .so files compiled in C++. The HSP indirectly exports the native method in the .so file. In this example, the **multi** API in the **libnative.so** file is exported. 116```ts 117// library/src/main/ets/utils/nativeTest.ts 118import native from "libnative.so" 119 120export function nativeMulti(a: number, b: number) { 121 let result: number = native.multi(a, b); 122 return result; 123} 124``` 125 126In the entry point file **index.ets**, declare the APIs to be exposed. 127```ts 128// library/src/main/ets/index.ets 129export { nativeMulti } from './utils/nativeTest' 130``` 131 132## Using the In-Application HSP 133To use APIs in the HSP, first [configure the dependency](https://developer.harmonyos.com/cn/docs/documentation/doc-guides-V3/hsp-0000001521396322-V3#section6161154819195) on the HSP in the **oh-package.json5** file of the module that needs to call the APIs (called the invoking module). 134You can then call the external APIs of the HSP in the same way as calling the APIs in the HAR. In this example, the external APIs are the following ones exported from **library**: 135 136```ts 137// library/src/main/ets/index.ets 138export { Log, add, minus } from './utils/test' 139export { MyTitleBar } from './components/MyTitleBar' 140export { ResManager } from './ResManager' 141export { nativeMulti } from './utils/nativeTest' 142``` 143The APIs can be used as follows in the code of the invoking module: 144```ts 145// entry/src/main/ets/pages/index.ets 146import { Log, add, MyTitleBar, ResManager, nativeMulti } from "library" 147import { BusinessError } from '@ohos.base'; 148 149@Entry 150@Component 151struct Index { 152 @State message: string = 'Hello World' 153 build() { 154 Row() { 155 Column() { 156 MyTitleBar() 157 Text(this.message) 158 .fontSize(30) 159 .fontWeight(FontWeight.Bold) 160 Button('add(1, 2)') 161 .onClick(()=>{ 162 Log.info("add button click!"); 163 this.message = "result: " + add(1, 2); 164 }) 165 // Resource object returned by ResManager, which can be passed to a component for direct use or be extracted. 166 Image(ResManager.getPic()) 167 .width("100%") 168 Button('getStringValue') 169 .onClick(()=> { 170 // Obtain the context of the HSP module based on the current context, obtain the resourceManager object of the HSP module, and then call the API of resourceManager to obtain resources. 171 getContext().createModuleContext('library').resourceManager.getStringValue(ResManager.getDesc()) 172 .then(value => { 173 console.log("getStringValue is " + value); 174 }) 175 .catch((err: BusinessError) => { 176 console.log("getStringValue promise error is " + error); 177 }); 178 }) 179 .width("50%") 180 Button('nativeMulti(3, 4)') 181 .onClick(()=>{ 182 Log.info("nativeMulti button click!"); 183 this.message = "result: " + nativeMulti(3, 4); 184 }) 185 } 186 .width('100%') 187 } 188 .height('100%') 189 } 190} 191``` 192 193### Redirecting to a Page 194 195If you want to add a button in the **entry** module to jump to the menu page (**library/src/main/ets/pages/menu.ets**) in the **library** module, you can write the following code in the **entry/src/main/ets/MainAbility/Index.ets** file of the **entry** module: 196```ts 197import router from '@ohos.router'; 198import { BusinessError } from '@ohos.base'; 199 200@Entry 201@Component 202struct Index { 203 @State message: string = 'Hello World' 204 205 build() { 206 Row() { 207 Column() { 208 Text(this.message) 209 .fontSize(50) 210 .fontWeight(FontWeight.Bold) 211 // Add a button to respond to user clicks. 212 Button() { 213 Text('click to menu') 214 .fontSize(30) 215 .fontWeight(FontWeight.Bold) 216 } 217 .type(ButtonType.Capsule) 218 .margin({ 219 top: 20 220 }) 221 .backgroundColor('#0D9FFB') 222 .width('40%') 223 .height('5%') 224 // Bind click events. 225 .onClick(() => { 226 router.pushUrl({ 227 url: '@bundle:com.example.hmservice/library/ets/pages/menu' 228 }).then(() => { 229 console.log("push page success"); 230 }).catch((err: BusinessError) => { 231 console.error(`pushUrl failed, code is ${err.code}, message is ${err.message}`); 232 }) 233 }) 234 .width('100%') 235 } 236 .height('100%') 237 } 238 } 239} 240``` 241The input parameter **url** of the **router.pushUrl** API is as follows: 242```ets 243'@bundle:com.example.hmservice/library/ets/pages/menu' 244``` 245The **url** content template is as follows: 246```ets 247'@bundle:bundle name/module name/path/page file name (without the extension .ets)' 248``` 249