Currently, Lynx is not suitable for building a new application from scratch. You need to integrate Lynx (engine) with your native mobile app or web app, and load Lynx apps through Lynx views. With a few steps, you can start developing with Lynx in your application.
Choose your target platform to view the specific integration steps:
Using Cocoapods can easily integrate Lynx into your application
The core capabilities of Lynx Engine include basic capabilities such as parsing Bundle, style parsing, layout, and rendering views
Get the latest version of Lynx from Cocoapods. Then add Lynx to your Podfile:
source 'https://cdn.cocoapods.org/'
platform :ios, '10.0'
target 'YourTarget' do
pod 'Lynx', '3.4.1', :subspecs => [
'Framework',
]
pod 'PrimJS', '2.14.1', :subspecs => ['quickjs', 'napi']
endLynx Service includes LynxImageService, LynxLogService, etc. It aims to provide the ability to strongly correlate some host App features, allowing the App to inject custom Services at runtime, or use the default implementation provided by the official. For example, LynxImageService is implemented using the SDWebImage image library by default. Apps that do not integrate SDWebImage components can rely on other image libraries to implement Image Service.
Lynx provides standard native Image, Log, and Http service capabilities, which can be quickly accessed and used by the access party;
Get the latest version of Lynx Service from Cocoapods. Then add Lynx Service to your Podfile:
source 'https://cdn.cocoapods.org/'
platform :ios, '10.0'
target 'YourTarget' do
pod 'Lynx', '3.4.1', :subspecs => [
'Framework',
]
pod 'PrimJS', '2.14.1', :subspecs => ['quickjs', 'napi']
# integrate image-service, log-service, and http-service
pod 'LynxService', '3.4.1', :subspecs => [
'Image',
'Log',
'Http',
]
# ImageService dependencies:
pod 'SDWebImage','5.15.5'
pod 'SDWebImageWebPCoder', '0.11.0'
endXElement is an extend native elements library maintained by the Lynx team. It provides richer component capabilities, enabling faster adoption of Lynx in production environments and enhancing the vibrancy of the Lynx ecosystem.
source 'https://cdn.cocoapods.org/'
platform :ios, '10.0'
target 'YourTarget' do
pod 'Lynx', '3.4.1', :subspecs => [
'Framework',
]
pod 'PrimJS', '2.14.1', :subspecs => ['quickjs', 'napi']
# integrate image-service, log-service, and http-service
pod 'LynxService', '3.4.1', :subspecs => [
'Image',
'Log',
'Http',
]
# ImageService
pod 'SDWebImage','5.15.5'
pod 'SDWebImageWebPCoder', '0.11.0'
pod 'XElement', '3.4.1'
endRun pod install to install dependencies, then open your Xcode project. Additionally, make sure to disable the Sandbox Scripting capability.
In order to disable the Sandbox scripting, in Xcode click on your app, then on build settings. Filter for script and set the User Script Sandboxing to NO.

LynxEnv provides a global initialization interface for the Lynx Engine. Please ensure that the initialization of LynxEnv occurs before any interface call of the Lynx Engine.
For example, it can be initialized in AppDelegate
#import <Lynx/LynxEnv.h>
#import <Lynx/LynxView.h>
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[LynxEnv sharedInstance];
return YES;
}LynxView is the basic rendering unit provided by Lynx Engine. LynxView is an implementation inherited from iOS native UIView. You can quickly construct a LynxView and add it to the ViewController.
Lynx Engine itself does not have the ability to load resources, so it is necessary to initialize LynxEnv, or when constructing LynxView to pass in the specific implementation of the LynxTemplateProvider protocol. Lynx will use the injected resource loader to obtain the Bundle content
You can use various methods to obtain the contents of the Bundle. Here, we choose to embed the contents of the Bundle within the application.
Steps to embed files:
#import <Foundation/Foundation.h>
#import <Lynx/LynxTemplateProvider.h>
NS_ASSUME_NONNULL_BEGIN
@interface DemoLynxProvider : NSObject <LynxTemplateProvider>
@end
NS_ASSUME_NONNULL_END#import <Foundation/Foundation.h>
#import "DemoLynxProvider.h"
@implementation DemoLynxProvider
- (void)loadTemplateWithUrl:(NSString*)url onComplete:(LynxTemplateLoadBlock)callback {
NSString *filePath = [[NSBundle mainBundle] pathForResource:url ofType:@"bundle"];
if (filePath) {
NSError *error;
NSData *data = [NSData dataWithContentsOfFile:filePath options:0 error:&error];
if (error) {
NSLog(@"Error reading file: %@", error.localizedDescription);
callback(nil, error);
} else {
callback(data, nil);
}
} else {
NSError *urlError = [NSError errorWithDomain:@"com.lynx"
code:400
userInfo:@{NSLocalizedDescriptionKey : @"Invalid URL."}];
callback(nil, urlError);
}
}
@endyou may construct a basic LynxView as follows:
#import <Lynx/LynxView.h>
#import "ViewController.h"
#import "DemoLynxProvider.h"
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
LynxView *lynxView = [[LynxView alloc] initWithBuilderBlock:^(LynxViewBuilder *builder) {
builder.config = [[LynxConfig alloc] initWithProvider:[[DemoLynxProvider alloc] init]];
builder.screenSize = self.view.frame.size;
builder.fontScale = 1.0;
}];
lynxView.preferredLayoutWidth = self.view.frame.size.width;
lynxView.preferredLayoutHeight = self.view.frame.size.height;
lynxView.layoutWidthMode = LynxViewSizeModeExact;
lynxView.layoutHeightMode = LynxViewSizeModeExact;
}
@endand then, adding the LynxView to the window.
#import <Lynx/LynxView.h>
#import "ViewController.h"
#import "DemoLynxProvider.h"
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// ...
[self.view addSubview:lynxView];
}
@endAfter completing the above steps, all the work of initializing LynxView have been completed. Call the lynxView.loadTemplateFromURL method to render the corresponding Bundle onto the LynxView.
#import <Lynx/LynxView.h>
#import "ViewController.h"
#import "DemoLynxProvider.h"
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// ...
[lynxView loadTemplateFromURL:@"main.lynx" initData:nil];
}
@endThen you will see the following interface on the screen:

Congratulations, you have now completed all the work of integrating Lynx Engine!
At this stage, you have successfully integrated Lynx into your App. Refer to our developing and debugging docs for in-depth insights on working with Lynx.
The core capabilities of Lynx Engine include basic capabilities such as parsing Bundle, style parsing, layout, rendering views and the basic code of the javascript runtime that Lynx pages rely on
dependencies {
// lynx dependencies
implementation "org.lynxsdk.lynx:lynx:3.4.1"
implementation "org.lynxsdk.lynx:lynx-jssdk:3.4.1"
implementation "org.lynxsdk.lynx:lynx-trace:3.4.1"
implementation "org.lynxsdk.lynx:primjs:2.14.1"
}Lynx Service includes LynxImageService, LynxLogService, etc. It aims to provide the ability to strongly correlate some host App features, allowing the App to inject custom Services at runtime, or use the default implementation provided by the official.For example, LynxImageService is implemented using the Fresco image library by default. Apps that do not integrate Fresco components can rely on other image libraries, such as Glide to implement Image Service.
Lynx provides standard native Image, Log, and Http service capabilities, which can be quickly accessed and used by the access party;
dependencies {
// lynx dependencies
implementation "org.lynxsdk.lynx:lynx:3.4.1"
implementation "org.lynxsdk.lynx:lynx-jssdk:3.4.1"
implementation "org.lynxsdk.lynx:lynx-trace:3.4.1"
implementation "org.lynxsdk.lynx:primjs:2.14.1"
// integrating image-service
implementation "org.lynxsdk.lynx:lynx-service-image:3.4.1"
// image-service dependencies, if not added, images cannot be loaded; if the host APP needs to use other image libraries, you can customize the image-service and remove this dependency
implementation "com.facebook.fresco:fresco:2.3.0"
implementation "com.facebook.fresco:animated-gif:2.3.0"
implementation "com.facebook.fresco:animated-webp:2.3.0"
implementation "com.facebook.fresco:webpsupport:2.3.0"
implementation "com.facebook.fresco:animated-base:2.3.0"
implementation "com.squareup.okhttp3:okhttp:4.9.0"
// integrating log-service
implementation "org.lynxsdk.lynx:lynx-service-log:3.4.1"
// integrating http-service
implementation "org.lynxsdk.lynx:lynx-service-http:3.4.1"
}The obfuscation rules for Lynx Engine are as follows. It is recommended to refer to the latest source code configuration.
# LYNX START
# use @Keep to annotate retained classes.
-dontwarn android.support.annotation.Keep
-keep @android.support.annotation.Keep class **
-keep @android.support.annotation.Keep class ** {
@android.support.annotation.Keep <fields>;
@android.support.annotation.Keep <methods>;
}
-dontwarn androidx.annotation.Keep
-keep @androidx.annotation.Keep class **
-keep @androidx.annotation.Keep class ** {
@androidx.annotation.Keep <fields>;
@androidx.annotation.Keep <methods>;
}
# native method call
-keepclasseswithmembers,includedescriptorclasses class * {
native <methods>;
}
-keepclasseswithmembers class * {
@com.lynx.tasm.base.CalledByNative <methods>;
}
# to customize a module, you need to keep the class name and the method annotated as LynxMethod.
-keepclasseswithmembers class * {
@com.lynx.jsbridge.LynxMethod <methods>;
}
-keepclassmembers class * {
@com.lynx.tasm.behavior.LynxProp <methods>;
@com.lynx.tasm.behavior.LynxPropGroup <methods>;
@com.lynx.tasm.behavior.LynxUIMethod <methods>;
}
-keepclassmembers class com.lynx.tasm.behavior.ui.UIGroup {
public boolean needCustomLayout();
}
# in case R8 compiler may remove mLoader in bytecode.
# as mLoader is not used in java and passed as a WeakRef in JNI.
-keepclassmembers class com.lynx.tasm.LynxTemplateRender {
private com.lynx.tasm.core.LynxResourceLoader mLoader;
}
# the automatically generated setter classes use the class names of LynxBaseUI and ShadowNode and their subclasses.
-keep class com.lynx.tasm.behavior.ui.LynxBaseUI
-keep class com.lynx.tasm.behavior.shadow.ShadowNode
-keep class com.lynx.jsbridge.LynxModule { *; }
-keep class * extends com.lynx.tasm.behavior.ui.LynxBaseUI
-keep class * extends com.lynx.tasm.behavior.shadow.ShadowNode
-keep class * extends com.lynx.jsbridge.LynxModule { *; }
-keep class * extends com.lynx.jsbridge.LynxContextModule
-keep class * implements com.lynx.tasm.behavior.utils.Settable
-keep class * implements com.lynx.tasm.behavior.utils.LynxUISetter
-keep class * implements com.lynx.tasm.behavior.utils.LynxUIMethodInvoker
-keep class com.lynx.tasm.rendernode.compat.**{
*;
}
-keep class com.lynx.tasm.rendernode.compat.RenderNodeFactory{
*;
}
# LYNX ENDApplication#onCreate lifecycle of the application.Please specify your custom Application class in the AndroidManifest.xml file, since Lynx needs to perform some global initialization operations when the application starts.
<application
android:name=".YourApplication">
</application>import android.app.Application;
import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.imagepipeline.core.ImagePipelineConfig;
import com.facebook.imagepipeline.memory.PoolConfig;
import com.facebook.imagepipeline.memory.PoolFactory;
import com.lynx.service.http.LynxHttpService;
import com.lynx.service.image.LynxImageService;
import com.lynx.service.log.LynxLogService;
import com.lynx.tasm.service.LynxServiceCenter;
public class YourApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
initLynxService();
}
private void initLynxService() {
// init Fresco which is needed by LynxImageService
final PoolFactory factory = new PoolFactory(PoolConfig.newBuilder().build());
ImagePipelineConfig.Builder builder =
ImagePipelineConfig.newBuilder(getApplicationContext()).setPoolFactory(factory);
Fresco.initialize(getApplicationContext(), builder.build());
LynxServiceCenter.inst().registerService(LynxImageService.getInstance());
LynxServiceCenter.inst().registerService(LynxLogService.INSTANCE);
LynxServiceCenter.inst().registerService(LynxHttpService.INSTANCE);
}
}LynxEnv provides the global initialization interface for the Lynx Engine. Please ensure that the initialization of LynxEnv occurs before any interface calls to the Lynx Engine. It is recommended to complete the initialization of LynxEnv during the Application#onCreate lifecycle of the application.
import com.lynx.tasm.LynxEnv;
public class YourApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
initLynxService();
initLynxEnv();
}
private void initLynxEnv() {
LynxEnv.inst().init(
this,
null,
null,
null
);
}
}The parameters for the LynxEnv initialization method are described as follows:
Lynx Engine itself does not have the ability to integrate downloading resources, so the existing app needs to provide the specific implementation of AbsTemplateProvider, and inject it when initializing LynxEnv or constructing LynxView. Lynx will use the injected resource loader to obtain the Bundle content
You can use various methods to obtain the contents of the Bundle. Here, we choose to embed the contents of the Bundle within the application.
app
└── src
└── main
├── java
├── res
└── assets
└── main.lynx.bundleimport android.content.Context;
import com.lynx.tasm.provider.AbsTemplateProvider;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
public class DemoTemplateProvider extends AbsTemplateProvider {
private Context mContext;
DemoTemplateProvider(Context context) {
this.mContext = context.getApplicationContext();
}
@Override
public void loadTemplate(String uri, Callback callback) {
new Thread(new Runnable() {
@Override
public void run() {
try (InputStream inputStream = mContext.getAssets().open(uri);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) != -1) {
byteArrayOutputStream.write(buffer, 0, length);
}
callback.onSuccess(byteArrayOutputStream.toByteArray());
} catch (IOException e) {
callback.onFailed(e.getMessage());
}
}
}).start();
}
}LynxView is the basic rendering view provided by Lynx Engine. LynxView inherits from the native Android View. You can quickly construct a LynxView and add it arbitrarily to the native Android view tree.
import android.app.Activity;
import android.os.Bundle;
import com.lynx.tasm.LynxView;
import com.lynx.tasm.LynxViewBuilder;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LynxView lynxView = buildLynxView();
setContentView(lynxView);
}
private LynxView buildLynxView() {
LynxViewBuilder viewBuilder = new LynxViewBuilder();
viewBuilder.setTemplateProvider(new DemoTemplateProvider(this));
return viewBuilder.build(this);
}
}XElement is an extend native elements library maintained by the Lynx team. It provides richer component capabilities, enabling faster adoption of Lynx in production environments and enhancing the vibrancy of the Lynx ecosystem.
dependencies {
// lynx dependencies
implementation "org.lynxsdk.lynx:lynx:3.4.1"
implementation "org.lynxsdk.lynx:lynx-jssdk:3.4.1"
implementation "org.lynxsdk.lynx:lynx-trace:3.4.1"
implementation "org.lynxsdk.lynx:primjs:2.14.1"
// integrating image-service
implementation "org.lynxsdk.lynx:lynx-service-image:3.4.1"
// image-service dependencies, if not added, images cannot be loaded; if the host APP needs to use other image libraries, you can customize the image-service and remove this dependency
implementation "com.facebook.fresco:fresco:2.3.0"
implementation "com.facebook.fresco:animated-gif:2.3.0"
implementation "com.facebook.fresco:animated-webp:2.3.0"
implementation "com.facebook.fresco:webpsupport:2.3.0"
implementation "com.facebook.fresco:animated-base:2.3.0"
implementation "com.squareup.okhttp3:okhttp:4.9.0"
// integrating log-service
implementation "org.lynxsdk.lynx:lynx-service-log:3.4.1"
// integrating http-service
implementation "org.lynxsdk.lynx:lynx-service-http:3.4.1"
// integrating XElement
implementation "org.lynxsdk.lynx:xelement:3.4.1"
implementation "org.lynxsdk.lynx:xelement:3.4.1"
}XElement requires additional importation in the LynxViewBuilder:
import android.app.Activity;
import android.os.Bundle;
import com.lynx.tasm.LynxView;
import com.lynx.tasm.LynxViewBuilder;
import com.lynx.xelement.XElementBehaviors;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LynxView lynxView = buildLynxView();
setContentView(lynxView);
}
private LynxView buildLynxView() {
LynxViewBuilder viewBuilder = new LynxViewBuilder();
viewBuilder.addBehaviors(new XElementBehaviors().create());
viewBuilder.setTemplateProvider(new DemoTemplateProvider(this));
return viewBuilder.build(this);
}
}After completing the above steps, all the work of initializing LynxView have been completed. Call the lynxView.renderTemplateUrl method to render the corresponding Bundle onto the LynxView view.
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LynxView lynxView = buildLynxView();
setContentView(lynxView);
String url = "main.lynx.bundle";
lynxView.renderTemplateUrl(url, "");
}
}Then you will see the following interface on the screen:

Congratulations, you have now completed all the work of rendering the LynxView!
At this stage, you have successfully integrated Lynx into your App. Refer to our developing and debugging docs for in-depth insights on working with Lynx.
The core capabilities of Lynx Engine include basic capabilities such as parsing Bundle, style parsing, layout, rendering views and the basic code of the javascript runtime that Lynx pages rely on
"dependencies": {
"@ohos/imageknife": "3.2.6",
"@lynx/lynx": "3.4.0",
"@lynx/primjs": "2.14.0",
},Lynx Service includes LynxDevtoolService, LynxLogService, etc. It aims to provide the ability to strongly correlate some host App features, allowing the App to inject custom Services at runtime, or use the default implementation provided by the official. For example, LynxHttpService is implemented using the built-in HTTP module of HarmonyOS by default. Lynx provides standard native Log and HTTP service capabilities, which can be quickly accessed and used by the access party;
"dependencies": {
"@ohos/imageknife": "3.2.6",
"@lynx/lynx": "3.4.1",
"@lynx/lynx_devtool": "3.4.1",
"@lynx/lynx_devtool_service": "3.4.1",
"@lynx/lynx_http_service": "3.4.1",
"@lynx/lynx_log_service": "3.4.1",
"@lynx/primjs": "2.14.1",
},To import libc++_shared.so, you need to configure Native C++. This requires defining a CMakeLists.txt file.
# the minimum version of CMake.
cmake_minimum_required(VERSION 3.5.0)
project(MyApplication)And modify the buildOptions in entry/build-profile.json5:
{
buildOption: {
externalNativeOptions: {
path: './src/main/cpp/CMakeLists.txt',
arguments: '',
cppFlags: '',
},
},
}If you need to request network resources, configure requestPermissions in module.json5 to enable network requests.
{
module: {
requestPermissions: [
{
name: 'ohos.permission.INTERNET',
reason: '$string:network',
usedScene: {
abilities: ['FormAbility'],
when: 'inuse',
},
},
],
},
}And configure the network key field in entry/src/main/resources/base/element/string.json:
{
"string": [
{
"name": "network",
"value": "Request network"
}
]
}UIAbility#onCreate lifecycle of the application.import { LLog, LynxServiceCenter, LynxEnv, LynxServiceType } from '@lynx/lynx';
import { LynxDevToolService } from '@lynx/lynx_devtool_service';
import { LynxLogService } from '@lynx/lynx_log_service';
import { LynxHttpService } from '@lynx/lynx_http_service';
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
// Init LynxDevtoolService
LynxServiceCenter.registerService(
LynxServiceType.DevTool,
LynxDevToolService.instance,
);
// Init LynxHttpService
LynxServiceCenter.registerService(
LynxServiceType.Http,
LynxHttpService.instance,
);
// Init LynxLogService
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate');
LynxServiceCenter.registerService(LynxServiceType.Log, LynxLogService.instance);
}
}LynxEnv provides the global initialization interface for the Lynx Engine. Please ensure that the initialization of LynxEnv occurs before any interface calls to the Lynx Engine. It is recommended to complete the initialization of LynxEnv during the UIAbility#onCreate lifecycle of the application.
import { LLog, LynxEnv } from '@lynx/lynx';
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
// Init LynxService
// ...
// Init LynxEnv
LLog.useSysLog(true);
LynxEnv.initialize(this.context);
let options = new Map<string, string>();
options.set('App', 'LynxExplorer');
options.set('AppVersion', '0.0.1');
LynxEnv.setAppInfo(options);
LynxEnv.enableDevtool(true);
}
}Lynx Engine itself does not have the ability to integrate downloading resources, so the existing app needs to provide the specific implementation of LynxResourceProvider, and inject it when constructing LynxView. Lynx will use the injected resource loader to obtain the Bundle content
You can use various methods to obtain the contents of the Bundle. Here, we choose to embed the contents of the Bundle within the application.
First, please place the Bundle file generated in the Quick Start stage in the src/main/resources/rawfile directory, or you can download the file below to your local machine and place it in the same directory:
entry
└── src
└── main
└── resources
└── rawfile
└── main.lynx.bundleLynxTemplateResourceFetcher provides the capability to load Bundle template resources. You need to implement the fetchTemplate method to handle the loading.
import { LLog, LynxResourceRequest, LynxTemplateResourceFetcher, TemplateProviderResult } from '@lynx/lynx';
import { AsyncCallback, BusinessError } from '@ohos.base';
import http from '@ohos.net.http';
import resourceManager from '@ohos.resourceManager';
export class ExampleTemplateResourceFetcher extends LynxTemplateResourceFetcher {
fetchTemplate(request: LynxResourceRequest,
callback: AsyncCallback<TemplateProviderResult, void>) {
if (request.url.startsWith('http')) {
let httpRequest = http.createHttp();
httpRequest.request(
request.url, {
expectDataType: http.HttpDataType.ARRAY_BUFFER,
}, (err: BusinessError, data: http.HttpResponse) => {
callback(err, {
binary: data?.result as ArrayBuffer
});
httpRequest.destroy();
});
} else {
// local file
const context: Context = getContext(this);
const resourceMgr: resourceManager.ResourceManager = context.resourceManager;
resourceMgr.getRawFileContent(request.url, (err: BusinessError, data: Uint8Array) => {
callback(err, {
binary: data?.buffer as ArrayBuffer
})
});
}
}
fetchSSRData(request: LynxResourceRequest, callback: AsyncCallback<ArrayBuffer, void>) {
let httpRequest = http.createHttp();
httpRequest.request(request.url, {
expectDataType: http.HttpDataType.ARRAY_BUFFER
}, (err: BusinessError, data: http.HttpResponse) => {
callback(err, data?.result as ArrayBuffer)
httpRequest.destroy();
})
}
}
LynxMediaResourceFetcher provides the capability to load media resources.
import { LynxMediaResourceFetcher, LynxResourceRequest, LynxOptionalBool } from '@lynx/lynx';
export class ExampleMediaResourceFetcher extends LynxMediaResourceFetcher {
shouldRedirectUrl(request: LynxResourceRequest): string {
// just return the input url;
return request.url;
}
isLocalResource(url: string): LynxOptionalBool {
return LynxOptionalBool.UNDEFINED;
}
}LynxGenericResourceFetcher provides the capability to load generic resources. You need to implement the fetchResource method to handle the loading.
import { LynxError, LynxSubErrorCode, LynxGenericResourceFetcher, LynxResourceRequest, LynxResourceType, LynxStreamDelegate } from '@lynx/lynx';
import { AsyncCallback, BusinessError } from '@ohos.base';
import http from '@ohos.net.http';
import { ImageKnife, ImageKnifeOption, CacheStrategy } from '@ohos/imageknife';
export class ExampleGenericResourceFetcher extends LynxGenericResourceFetcher {
fetchResource(request: LynxResourceRequest, callback: AsyncCallback<ArrayBuffer, void>): void {
let httpRequest = http.createHttp();
httpRequest.request(request.url, {
expectDataType: http.HttpDataType.ARRAY_BUFFER
}, (err: BusinessError, data: http.HttpResponse) => {
callback(err, data?.result as ArrayBuffer)
httpRequest.destroy();
})
}
fetchResourcePath(request: LynxResourceRequest, callback: AsyncCallback<string, void>): void {
if (request.type === LynxResourceType.LYNX_RESOURCE_TYPE_IMAGE) {
let option = new ImageKnifeOption();
option.loadSrc = request.url;
option.writeCacheStrategy = CacheStrategy.File;
let error: BusinessError | undefined = undefined;
ImageKnife.getInstance().preLoadCache(option).then((data: string) => {
if (data.length > 0) {
callback(error, data);
} else {
error = {
code: LynxSubErrorCode.E_RESOURCE_IMAGE_PIC_SOURCE,
message: 'Image path is invalid',
name: 'Image Error',
}
callback(error, '');
}
}).catch((e: string) => {
error = {
code: LynxSubErrorCode.E_RESOURCE_IMAGE_FROM_NETWORK_OR_OTHERS,
message: e,
name: 'Image Error',
}
callback(error, '');
})
} else {
callback({
code: LynxError.LYNX_ERROR_CODE_RESOURCE,
message: 'unsupported type: ' + request.type,
name: 'Resource Error',
}, '');
}
}
fetchStream(request: LynxResourceRequest, delegate: LynxStreamDelegate): void {
// TODO(Lynx): support fetching stream.
delegate.onStart(100);
let a = new ArrayBuffer(10);
delegate.onData(a, 0, 10);
delegate.onEnd();
}
cancel(request: LynxResourceRequest): void {
// TODO(Lynx)
}
}
Once you have completed the steps above, you have finished all the necessary work for creating the LynxView and reading its resources. You can now render the corresponding Bundle content onto the LynxView.
import {
LynxTemplateResourceFetcher,
LynxMediaResourceFetcher,
LynxGenericResourceFetcher,
LynxView,
} from '@lynx/lynx';
import { ExampleTemplateResourceFetcher } from '../provider/ExampleTemplateResourceFetcher';
import { ExampleMediaResourceFetcher } from '../provider/ExampleMediaResourceFetcher';
import { ExampleGenericResourceFetcher } from '../provider/ExampleGenericResourceFetcher';
@Entry
@Component
struct Index {
templateResourceFetcher: LynxTemplateResourceFetcher = new ExampleTemplateResourceFetcher();
mediaResourceFetcher: LynxMediaResourceFetcher = new ExampleMediaResourceFetcher();
genericResourceFetcher: LynxGenericResourceFetcher = new ExampleGenericResourceFetcher();
private url: string = 'your bundle file';
build() {
Column() {
LynxView({
templateResourceFetcher: this.templateResourceFetcher,
mediaResourceFetcher: this.mediaResourceFetcher,
genericResourceFetcher: this.genericResourceFetcher,
url: this.url,
}).width('100%').height('100%');
}
.size({ width: '100%', height: '100%' })
}
}You will then see the following content on your screen:

Congratulations! You have now completed the full integration of the Lynx Engine.
Now that you have integrated Lynx into your application, please refer to the Development and Debugging documentation to further explore the world of Lynx!
Lynx for Web implements the Lynx engine in web browsers. With Lynx for Web, you can easily integrate Lynx apps into any existing web project, regardless of whether the project uses React, Vue, Svelte, or plain HTML.
We need you to have read and created a Lynx project according to Quick Start.
cd <lynx-project-name>environments.web) to lynx.config.ts:import { defineConfig } from '@lynx-js/rspeedy';
import { pluginReactLynx } from '@lynx-js/react-rsbuild-plugin';
export default defineConfig({
plugins: [pluginReactLynx()],
environments: {
web: {
output: {
assetPrefix: '/',
},
},
lynx: {},
},
});Run:
npm run buildYou will see an additional dist/main.web.bundle file in this project, which is the final web build artifact.
Now that you have a Lynx for Web build artifact, we need to create a web project to use it. Here we use Rsbuild.
Create a new project at the same level as the Lynx project above and run:
npm create rsbuild@latestFollow the prompts to create a React project.
cd <web-project-name>npm install @lynx-js/web-core @lynx-js/web-elementssrc/app.tsximport './App.css';
import '@lynx-js/web-core/index.css';
import '@lynx-js/web-elements/index.css';
import '@lynx-js/web-core';
import '@lynx-js/web-elements/all';
const App = () => {
return (
<lynx-view
style={{ height: '100vh', width: '100vw' }}
url="/main.web.bundle"
></lynx-view>
);
};
export default App;rsbuild.config.ts
server.publicDir needs to be replaced with your actual Lynx project path.
import { defineConfig } from '@rsbuild/core';
import { pluginReact } from '@rsbuild/plugin-react';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
export default defineConfig({
plugins: [pluginReact()],
server: {
publicDir: [
{
name: path.join(
__dirname,
'../',
// Please replace this with your actual Lynx project name
'lynx-project',
'dist',
),
},
],
},
});Run:
npm run devVisit http://localhost:3000 to see your Lynx application.
See LynxView for more API details.