Lynx

subscribeMessage

为指定的调试消息类型注册处理器,用于获取并处理该类型的消息。

配合 sendMessage 方法,支持与消息发出方(如 DevTool 桌面应用)进行双向通信。

语法

iOS

LynxBaseInspectorOwnerNG.h
- (void)subscribeMessage:(nonnull NSString *)type withHandler:(nonnull id<MessageHandler>)handler;

Android

LynxBaseInspectorOwnerNG.java
void subscribeMessage(String type, MessageHandler handler);

Harmony

LynxBaseInspectorOwner.ets
subscribeMessage(type: string, handler: MessageHandler): void;

参数说明

  • type: 要订阅的消息类型,如 CDP 或其他自定义消息类型。
  • handler: 实现了 MessageHandler 的对象,用于接收调试消息。
Warning

DevTool 内部只会持有 MessageHandler 对象的弱引用,开发者需要自行管理其生命周期。

使用示例

使用步骤

  1. 实现 MessageHandler,处理收到的调试消息。
  2. 获取 LynxBaseInspectorOwner 实例,在 iOS 和 Android 端需要转换为 LynxBaseInspectorOwnerNG 类型。
  3. 调用 subscribeMessage 方法,订阅指定类型的调试消息。

代码示例

下列示例代码订阅了 CDP 消息,当收到 Page.enable 消息时,会发送一条内容为 Hello, Lynx DevTool!Log.entryAdded 消息。

最终效果是在 DevTool 桌面应用Console 面板中会展示这条日志。

Subscribe Message

iOS

TestMessageHandler.h
#import <Lynx/LynxBaseInspectorOwnerNG.h>

@interface TestMessageHandler : NSObject <MessageHandler>

- (instancetype)initWithInspectorOwner:(id<LynxBaseInspectorOwnerNG>)owner;

@end
TestMessageHandler.m
#import <UIKit/UIKit.h>
#import <Lynx/CustomizedMessage.h>

#import "TestMessageHandler.h"

@implementation TestMessageHandler {
  __weak id<LynxBaseInspectorOwnerNG> _owner;
}

- (instancetype)initWithInspectorOwner:(id<LynxBaseInspectorOwnerNG>)owner {
  self = [super init];
  if (self) {
    _owner = owner;
  }
  return self;
}

- (void)onMessage:(nonnull NSString *)message {
  NSData *data = [message dataUsingEncoding:NSUTF8StringEncoding];
  NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];

  if ([[dic objectForKey:@"method"] isEqualToString:@"Page.enable"]) {
    id<LynxBaseInspectorOwnerNG> strongOwner = _owner;
    if (!strongOwner) {
      return;
    }

    long long timestamp = (long long)([[NSDate date] timeIntervalSince1970] * 1000);
    NSDictionary *logJSON = @{
      @"method": @"Log.entryAdded",
      @"params": @{
        @"entry": @{
          @"level": @"info",
          @"source": @"javascript",
          @"text": @"Hello, Lynx DevTool!",
          @"timestamp": @(timestamp)
        }
      }
    };

    NSData *logData = [NSJSONSerialization dataWithJSONObject:logJSON options:0 error:nil];
    NSString *logString = [[NSString alloc] initWithData:logData encoding:NSUTF8StringEncoding];
    if (logString) {
      CustomizedMessage *customizedMessage = [[CustomizedMessage alloc] init];
      customizedMessage.type = @"CDP";
      customizedMessage.data = logString;
      [strongOwner sendMessage:customizedMessage];
    }
  }
}

@end
ViewController.m
#import <Lynx/LynxView.h>
#import <Lynx/LynxBaseInspectorOwner.h>

#import "TestMessageHandler.h"

@implementation ViewController {
  TestMessageHandler *_handler;
}

- (void)viewDidLoad {
  [super viewDidLoad];

  // ...

  id<LynxBaseInspectorOwnerNG> owner = (id<LynxBaseInspectorOwnerNG>)lynxView.baseInspectorOwner;
  _handler = [[TestMessageHandler alloc] initWithInspectorOwner:owner];
  [owner subscribeMessage:@"CDP" withHandler:_handler];
  __weak id<LynxBaseInspectorOwnerNG> weakOwner = owner;
  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)),
                 dispatch_get_main_queue(), ^{
                   id<LynxBaseInspectorOwnerNG> strongOwner = weakOwner;
                   [strongOwner unsubscribeMessage:@"CDP"];
                 });
}

@end

Android

TestMessageHandler.java
import com.lynx.devtoolwrapper.CustomizedMessage;
import com.lynx.devtoolwrapper.LynxBaseInspectorOwnerNG;
import com.lynx.devtoolwrapper.MessageHandler;

import java.lang.ref.WeakReference;

import org.json.JSONException;
import org.json.JSONObject;

public class TestMessageHandler implements MessageHandler {
  private final WeakReference<LynxBaseInspectorOwnerNG> mOwner;

  public TestMessageHandler(LynxBaseInspectorOwnerNG owner) {
    mOwner = new WeakReference<>(owner);
  }

  @Override
  public void onMessage(String message) {
    try {
      JSONObject jsonObject = new JSONObject(message);
      String method = jsonObject.getString("method");
      if ("Page.enable".equals(method)) {
        LynxBaseInspectorOwnerNG owner = mOwner.get();
        if (owner == null) {
          return;
        }
        JSONObject logJSON = new JSONObject();
        logJSON.put("method", "Log.entryAdded");
        logJSON.put("params", new JSONObject().put("entry", new JSONObject()
            .put("level", "info")
            .put("source", "javascript")
            .put("text", "Hello, Lynx DevTool!")
            .put("timestamp", System.currentTimeMillis())));
        CustomizedMessage customizedMessage = new CustomizedMessage("CDP", logJSON.toString());
        owner.sendMessage(customizedMessage);
      }
    } catch (JSONException e) {
      // ...
    }
  }
}
MainActivity.java
import android.os.Handler;
import android.os.Looper;

import com.lynx.devtoolwrapper.LynxBaseInspectorOwnerNG;

import java.lang.ref.WeakReference;

public class MainActivity extends Activity {
  private TestMessageHandler mTestMessageHandler = null;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // ...

    subscribeCDPMessage(lynxView);
  }

  private void subscribeCDPMessage(LynxView lynxView) {
    LynxBaseInspectorOwnerNG owner = (LynxBaseInspectorOwnerNG) lynxView.getBaseInspectorOwner();
    if (owner == null) {
      return;
    }
    mTestMessageHandler = new TestMessageHandler(owner);
    owner.subscribeMessage("CDP", mTestMessageHandler);
    Handler mainHandler = new Handler(Looper.getMainLooper());
    WeakReference<LynxBaseInspectorOwnerNG> weakOwner = new WeakReference<>(owner);
    mainHandler.postDelayed(() -> {
      LynxBaseInspectorOwnerNG strongOwner = weakOwner.get();
      strongOwner.unsubscribeMessage("CDP");
    }, 10000);
  }
}

Harmony

TestMessageHandler.ets
import { LynxBaseInspectorOwner, MessageHandler } from '@lynx/lynx';

interface LogEntry {
  level: string;
  source: string;
  text: string;
  timestamp: number;
}

interface LogParams {
  entry: LogEntry;
}

interface LogMessage {
  method: string;
  params: LogParams;
}

export class TestMessageHandler implements MessageHandler {
  private owner: WeakRef<LynxBaseInspectorOwner>;

  constructor(owner: LynxBaseInspectorOwner) {
    this.owner = new WeakRef(owner);
  }

  public onMessage(msg: string): void {
    let json: object = JSON.parse(msg);
    if (json['method'] === 'Page.enable') {
      let owner = this.owner.deref();
      if (!owner) {
        return;
      }
      let log: LogMessage = {
        method: 'Log.entryAdded',
        params: {
          entry: {
            level: 'info',
            source: 'javascript',
            text: 'Hello, Lynx DevTool!',
            timestamp: Date.now(),
          },
        },
      };
      owner.sendMessage('CDP', JSON.stringify(log));
    }
  }
}
Index.ets
import { LynxView, LynxContext } from '@lynx/lynx';
import { TestMessageHandler } from './TestMessageHandler'

@Entry
@Component
struct Index {
  // ...
  private handler?: TestMessageHandler;

  build() {
    Column() {
      LynxView({
        // ...
        onCreate: (context: LynxContext) => {
          let owner = context?.getBaseInspectorOwner();
          if (owner) {
            this.handler = new TestMessageHandler(owner);
            owner.subscribeMessage('CDP', this.handler);
            let weakOwner = new WeakRef(owner);
            setTimeout(() => {
              let owner = weakOwner.deref();
              owner?.unsubscribeMessage('CDP');
            }, 10000);
          }
        }
      }).width('100%').height('100%');
    }
  }
}

兼容性

LCD tables only load in the browser

除非另有说明,本项目采用知识共享署名 4.0 国际许可协议进行许可,代码示例采用 Apache License 2.0 许可协议进行许可。