Javascript での JSBridge に関する予備的研究

Javascript での JSBridge に関する予備的研究

JSBridgeの起源

近年、モバイル端末の普及が進み、開発プロセスにおいてネイティブとH5のどちらを選択するかは常に話題になっています。 Native と H5 はそれぞれ長所と短所があり、ビジネスニーズを満たすために、実際のプロジェクト開発では、この 2 つを組み合わせてハイブリッド開発を行う企業が多くあります。 Native と H5 は 2 つの異なる場所にあり、接続されていないように見えますが、どのようにして 2 つの側が連携して機能を実現できるのでしょうか?

このとき、デバイス関連の API セットを提供し、初期の js がネイティブ コードを呼び出してネイティブ機能を実装するための一般的なソリューションである Codova について考えました。しかし、モバイルインターネットの普及により、JSBridge は国内で広く使用されています。

JSBridge は、ブリッジの両端で Native と H5 を接続する、JS 実装のブリッジです。これにより、APP 内で Native が JS を呼び出したり、JS が Native を呼び出したりすることが簡単にできる、双方向の通信チャネルになります。 JSBridge は主に、JS がネイティブ コードを呼び出して、ローカル フォト アルバムの表示、カメラの起動、指紋決済などのネイティブ機能を実装する機能を提供します。

H5 対 ネイティブ

名前H5ネイティブ
安定性システムブラウザカーネルの呼び出しは安定性が低いネイティブカーネルを使用し、より安定
柔軟性迅速なバージョン反復と柔軟なリリース反復が遅く、アプリストアのレビューが必要で、起動速度が制限される
ネットワーク速度の影響を受ける大きい小さい
流暢さ読み込みが遅くなり、ユーザーに「カクツキ」を感じさせることがある読み込み速度が速く、スムーズ
ユーザーエクスペリエンスブラウザによって機能が制限され、エクスペリエンスが悪くなることがあるネイティブシステムAPIは豊富で、多くの機能を実現でき、より良い体験を提供します。
携帯性PCとモバイル、iOSとAndroidなど、クロスプラットフォームおよびクロスシステムに対応移植性が低いため、iOS と Android 用に 2 セットのコードを維持する必要がある

JSBridgeの双方向通信原理

JSはネイティブを呼び出す

ネイティブを呼び出す JS を実装する方法は多数ありますが、主に URL スキームのインターセプト、プロンプトの書き換え、API の挿入などのメソッドがあります。

URLスキームの傍受

Android と iOS はどちらも URL スキームをインターセプトし、スキームを解析して、対応するネイティブ コード ロジック処理を実行するかどうかを決定できます。

Android の場合、Webview は shouldOverrideUrlLoading メソッドを提供し、ネイティブが H5 によって送信された URL スキーム要求をインターセプトできるようにします。コードは次のとおりです。

パブリッククラス CustomWebViewClient は WebViewClient を拡張します {
    @オーバーライド
    パブリックブール値の shouldOverrideUrlLoading(WebView ビュー、文字列 URL) {
      ......
      // シナリオ 1: 要求を傍受して受信する方式
        url.equals("xxx") の場合 {

            // ハンドル
            ...
            // 折り返し電話
            view.loadUrl("JavaScript:setAllContent(" + json + ");")
            true を返します。
        }
        super.shouldOverrideUrlLoading(url); を返します。
     }
}

iOS の WKWebview は、インターセプトされた URL スキームと対応するパラメータに基づいて関連する操作を実行できます。コードは次のとおりです。

- (void)webView:(WKWebView *)webView decisionPolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
    if ([navigationAction.request.URL.absoluteString hasPrefix:@"xxx"]) {
        [[UIApplication sharedApplication] openURL:navigationAction.request.URL];
    }
    決定ハンドラ(WKNavigationActionPolicyAllow);
}

この方法の利点は、脆弱性がなく、柔軟に使用でき、H5 ページとネイティブ ページ間のシームレスな切り替えを実現できることです。たとえば、ページをすぐに公開する必要がある場合は、まず H5 ページを開発します。リンクが H5 リンクとして記入されている場合、対応するネイティブ ページが展開される前に H5 ページにジャンプします。ネイティブ ページが展開された後、インターセプトされてネイティブ ページにジャンプします。このとき、H5 リンクを変更する必要はありません。ただし、iframe.src を使用して URL スキームを送信するには、URL の長さを制御する必要があり、これは複雑で時間がかかります。

promptなどのネイティブJSメソッドを書き換える

Android 4.2 より前では、オブジェクトを挿入するためのインターフェースは addJavaScriptInterface でしたが、セキュリティ上の理由から徐々に非推奨になっています。通常、この操作はブラウザの Window オブジェクトのいくつかのメソッドを変更することによって完了します。主に、Webview の onJsAlert、onJsConfirm、onConsoleMessage、onJsPrompt によってそれぞれ監視される、alert、confirm、prompt、console.log の 4 つのメソッドをインターセプトします。 onJsPrompt 監視コードは次のとおりです。

パブリック ブール onJsPrompt(WebView ビュー、文字列 origin、文字列 message、文字列 defaultValue、最終的な JsPromptResult 結果) {
  文字列は、parentEngine.bridge.promptOnJsPrompt(origin, message,defaultValue) で処理されます。
  xxx;
  true を返します。
}

iOS のセキュリティ メカニズムにより、WKWebView は alert、confirm、prompt などのメソッドをインターセプトします。ネイティブと JS がこのように相互作用する場合は、WKWebView の 3 つの WKUIDelegate プロキシ メソッドを実装する必要があります。コード例は次のとおりです。

-(void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame 完了ハンドラー:(void (^)(void))完了ハンドラー{

  UIAlertController *alertController = [UIAlertController alertControllerWithTitle:nil message:message?:@"" preferredStyle:UIAlertControllerStyleAlert];

  [alertController addAction:([UIAlertAction actionWithTitle:@"Confirm" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {

      完了ハンドラ();

  }])];

  [self presentViewController:alertController アニメーション:YES 完了:nil];

}

この方法を使用すると、パラメータの受け渡しの形式について Android と iOS と合意できるため、H5 はクライアントを識別せずに異なるパラメータを渡して Native を直接呼び出すことができます。残りは、同じメソッドをインターセプトし、同じパラメータを識別し、独自の処理ロジックを実行して、複数の端末で一貫したパフォーマンスを実現するクライアントに任されます。のように:

alert("xxx でよろしいですか?", "キャンセル", "OK", callback());

また、メソッド名やパラメータの受け渡しなどの呼び出しプロトコル仕様を Native で判別できれば、他の形式のプロンプトや他のメソッドは認識されず、分離の役割を果たすことができます。

##### インジェクション API

Webview が提供する機能に基づいて、Window にオブジェクトまたはメソッドを挿入できます。 JS がこのオブジェクトまたはメソッドを介して呼び出すと、対応する論理演算が実行され、ネイティブ メソッドを直接呼び出すことができます。このメソッドを使用する場合、JS はコールバックで操作を実行する前に、ネイティブが対応するロジックの実行を完了するまで待機する必要があります。

Android の Webview は、Android 4.2 以降をサポートする addJavascriptInterface メソッドを提供します。

gpcWebView.addJavascriptInterface(新しい JavaScriptInterface()、'nativeApiBridge'); 
パブリッククラス JavaScriptInterface {
    コンテキスト mContext;

  JavaScriptインターフェース(コンテキストc) {
    mContext = c;
  }

  パブリック void share(String webMessage){            
    // ネイティブロジック}
}

JS 呼び出しの例:

ウィンドウのネイティブ API を共有します (xxx);

iOS UIWebview は、iOS 7.0 以降をサポートする JavaScriptScore メソッドを提供します。 WKWebview は、iOS 8.0 以降をサポートする window.webkit.messageHandlers メソッドを提供します。 UIWebview は数年前はよく使われていましたが、今では一般的ではありません。以下は、WKWebViewConfiguration と WKWebView を作成する例です。

WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
WKPreferences *preferences = [WKPreferences new];
preference.javaScriptCanOpenWindowsAutomatically = YES;
設定.最小フォントサイズ = 40.0;
設定.preferences = 設定;
    

- (void)viewWillAppear:(BOOL)アニメーション
{
    [スーパービューが表示される:アニメーション];
    [self.webView.configuration.userContentController addScriptMessageHandler:self name:@"share"];
      [self.webView.configuration.userContentController addScriptMessageHandler:self name:@"pickImage"];
}
- (void)viewWillDisappear:(BOOL)アニメーション
{
    [スーパービューWillDisappear:アニメーション];
    [self.webView.configuration.userContentController スクリプトメッセージハンドラーの名前を削除します:@"share"];
    [self.webView.configuration.userContentController スクリプトメッセージハンドラーの名前を削除します:@"pickImage"];
}

JS 呼び出しの例:

window.webkit.messageHandlers.share.postMessage(xxx);

ネイティブコールJS

ネイティブが JS を呼び出すのは比較的簡単です。ネイティブが呼び出す JS メソッドをウィンドウに公開するだけです。

Android でこれを実装するには、主に 2 つの方法があります。 4.4 より前では、これは loadUrl メソッドを通じて JS コードを実行することによって実現されていました。 4.4 以降では、evaluateJavascript メソッドを使用してこれを実現できます。 loadUrl メソッドは便利で簡潔に使用できますが、非効率的で結果を返すことができず、呼び出されると WebView が更新されます。 assessJavascript メソッドは効率的で、戻り値を取得するのが簡単です。呼び出されても WebView は更新されませんが、Android 4.4 以降のみをサポートします。関連するコードは次のとおりです。

webView.loadUrl("javascript:" + javaScriptString);
webView.evaluateJavascript(javaScriptString, 新しいValueCallback<String>() {
  @オーバーライド
  パブリックvoid onReceiveValue(文字列値){
    xxx
  }
});

iOS は、iOS 8.0 以降をサポートする assessJavaScript:javaScriptString を通じて WKWebview に実装できます。

// スウィフト
functionevaluateJavaScript(_ javaScriptString: String, 
    完了ハンドラ: ((Any?、Error?) -> Void)? = nil)
// 呼び出される javascriptString JS コード // 実行後の completionHandler コールバック // objective-c
[jsContext の評価 JavaScript:@"ZcyJsBridge(ev, data)"]

JSBridgeの使用

引用方法

  • この方法は、弊社のモバイル端末の初期バージョンで H5 が参照されていたときに使用されており、npm パッケージをローカルに導入して呼び出しが行われました。このメソッドは、JSBridge が存在することを確認し、ネイティブ メソッドを直接呼び出すことができます。しかし、Bridge の実​​装が後から変更された場合、両者はさらなる互換性を確保する必要があり、メンテナンスコストが高くなります。
  • ネイティブインジェクションは、現在当社のモバイル端末で使用されている方法です。今後のビジネスニーズを考慮し、再設計を行い、JSBridgeを参考にネイティブインジェクション方式を採用しました。これにより、API と Native 間の一貫性が保たれますが、Native の注入方法とタイミングが制限されるという欠点があります。JS が Native を呼び出す前に、JSBridge が正常に注入されたかどうかを判断する必要があります。

使用ガイドライン

H5 がネイティブ メソッドを呼び出す擬似コードの例:

パラメータ = {
  api_version: "xxx", // API バージョン title: "xxx", // タイトル filename: "xxx", // ファイル名 image: "xxx", // 画像リンク url: "xxx", // URL リンク success: function (res) {
    xxx; //呼び出しが成功した後に実行},
  失敗: 関数 (err) {
    (エラーコード == '-2')の場合{
      fail && fail(err); // 現在のクライアントに存在しない API バージョンが呼び出されました } else {
      const msg = err.msg; //例外情報 Toast.fail(msg);
    }
  }
};
ウィンドウのネイティブ API を共有します。

以下に、一般的なメソッドの抽象化を簡単に示します。現在、双方向通信は基本的に以下の仕様に従います。

ウィンドウ.NativeApi.xxx({
    api_version:''、
    名前: "xxx",
    パス: "xxx",
    id: "xxx",
    成功: 関数 (res) {
      コンソールログ(res);
    },
    失敗: 関数 (err) {
      コンソールログ(エラー);
    }
});

最初のバージョンでは、H5 でローカルに JSBridge を使用することを選択したため、後のバージョンではネイティブ インジェクション方式が採用されました。既存の H5 は、さまざまな状況に対応する必要があります。論理的な抽象化は次のとおりです。

reqNativeBridge(vm, fn) {
  もし(!isApp()) {
    // 呼び出しがAPP内で行われなかった場合 vm.$dialog.alert({
      メッセージ: 「この機能を使用するにはアプリへのアクセスが必要です」
    });
  } それ以外 {
    ネイティブAPIの場合
      // 初期バージョンの場合 vm.$dialog.alert({
        メッセージ:「この機能を使用するには、最新のアプリに更新してください」
      });
    } それ以外 {
      // ここでは、「現在のクライアントに存在しない API バージョンを呼び出しています」というエラー メッセージのみを処理します // その他の種類のエラー情報は、特定のビジネスによって処理されます fn && fn((err) => {
        vm.$dialog.alert({
          メッセージ:「この機能を使用するには、最新のアプリに更新してください」
        });
      });
    }
  }
}

要約する

上記の内容は、JSBridge のいくつかの原理を簡単に紹介したものです。JSBridge を初めて知る学生にとって役立つことを願っています。 JSBridge インターフェース呼び出しのカプセル化実装、JS が Native を呼び出すときのコールバックの一意性など、JSBridge の原理と実装についてさらに深く理解する必要がある場合。さらに詳しい情報を確認するには、より詳しい関連文書や、他の人がまとめた降水量を参照してください。

上記は、Javascript での JSBridge の初期調査の詳細な内容です。Javascript での JSBridge の詳細については、123WORDPRESS.COM の他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • FlutterはWebviewとH5間の通信を処理するためにJsBridgeを使用します。
  • Android と JS 間のインタラクションに jsbridge を使用するチュートリアル
  • WeChatブラウザに組み込まれたWeixinJSBridgeのJavaScriptオブジェクト
  • jsBridgeの動作メカニズムを1つの記事で学ぶ

<<:  Jenkins でユーザー ロールの権限を設定する方法

>>:  MySQL 5.7.20\5.7.21 無料インストール版のインストールと設定のチュートリアル

推薦する

CSS 画面サイズ適応実装例

CSS 画面サイズの適応を実現するには、まず CSS3 @media メディア クエリを導入する必要...

VUEはタイムライン再生コンポーネントを実装します

この記事の例では、タイムライン再生コンポーネントを実装するためのVUEの具体的なコードを参考までに共...

MySQL における 8 つの一般的な SQL 使用例

序文MySQL は、2016 年もデータベースの人気において力強い成長傾向を維持し続けました。 My...

MySQL 8のパスワードを忘れた場合のベストな対処法の簡単な分析

序文MySQL に精通している読者は、MySQL が非常に迅速に更新されることに気付くかもしれません...

Windows での MySQL コミュニティ サーバー 8.0.16 のインストールと構成方法のグラフィック チュートリアル

最近、MySQL関連の構文をよく見かけます。また、MySQLストアドプロシージャの書き方も学びたいの...

Kubernetes オブジェクトボリュームの詳細な使用方法

概要ボリュームは、さまざまなストレージ リソースを抽象化および仮想化したものです。ストレージ リソー...

VUE+Canvasは、インゴットを受け取る富の神のゲームを実装します

前回のキャンバス ゲーム シリーズへようこそ: 《VUEがFlappy Birdを実装しました〜〜〜...

純粋なCSSを使用してスイッチ効果を実現する

まずアイデアはこの効果を実現するには、 <input type="checkbox&...

Docker Compose マルチコンテナデプロイメントの実装

目次1. WordPressの導入1. 環境を整える(II) イメージを実行するDocker の作成...

vue $setは配列コレクションオブジェクトへの値の割り当てを実装します

Vue $set 配列コレクションオブジェクトの割り当てVue カスタム配列オブジェクト コレクショ...

forループ内のvarの問題の解決

序文var は ES5 における変数宣言方法です。var で変数を宣言するとループ変数がグローバル変...

MySQL 8.0.19 winx64 インストールチュートリアルと Windows 10 での初期パスワードの変更

この記事では、参考までにMySQL 8.0.19 winx64のインストールチュートリアルを紹介しま...

Mybatis mysqlの削除操作では、最初のデータメソッドのみを削除できます。

バグ図のように、削除文とパラメータをデータベースにコピーして実行し、2つのデータを削除しようとしたの...

MySQL 学習ノート: データ エンジン

現在のデータベースでサポートされているエンジンを表示します エンジンを表示 +-----------...

Docker-compose インストール db2 データベース操作

db2 データベースをホストマシンに直接インストールするのは面倒で、ユーザーや権限を巻き込むのも不便...