APPとJs間の相互呼び出し方法


前言:
プロジェクトではAPPとH 5の相互呼び出し方法が必要になる場合がありますが、AndroidとiOSが相互呼び出し相手をどのように実現するかについて説明します.
一、APPがH 5を呼び出す方法
APPで生成された情報は、基本データ型またはJson文字列(比較的多くの情報を伝えることができる)の形でH 5に伝達される.
Android——webviewでロードし直し、対応するH 5をロードする方法
webView.loadUrl(“javascript:methodName(parameterValues)”;

例:
/**
 * APP        H5   
 * @param method     
 * @param param     
 */

    private void reloadJs(String method, String param) {
        String url = String.format("javascript:%s(\"%s\")", method, param);
        webview.loadUrl(url);
    }

 
必要な場所でreloadJsを呼び出す
 
H 5には、以下の方法が存在する.
//Android          H5   
function alert(message){
document.getElementById("change").innerHTML = message;
}

iOS-webviewで提供された方法で対応するH 5をロードする方法
 [self.webView stringByEvaluatingJavaScriptFromString:@"methodName(parameterValues)"];

例:
[self.webView stringByEvaluatingJavaScriptFromString:@"alert(\"iOS change javascript to message for H5\")"];

H 5にalertメソッドを追加すればよい 
 function alert(message){
      document.getElementById("change").innerHTML = message;
    }

二、H 5 APPを呼び出す方法——APPはいくつかの機能を実現する
H 5必要なパラメータをJson文字列でAPPに渡す
Android--webviewのオリジナルメソッドに基づいてこの機能を実現
1、以下の方法でwebviewのインタフェースをH 5に渡す
 @param object the Java object to inject into this WebView's JavaScript
* @param name the name used to expose the object in JavaScript
webview.addJavascriptInterface(Object object, String name));

本プロジェクトのコードは次のとおりです.
 webview.addJavascriptInterface(new JsAction(), "action");

2、JsActionクラスに相応のインタフェース方法を追加する
Android原生は注釈方式@JavascriptInterfaceを提供しています.JsActionのクラスで定義されているメソッドに@JavascriptInterfaceを付けるだけです.
 private class JsAction {

        @JavascriptInterface //H5  Android    
        public void toast(final String jsonString) {
            //  @JavascriptInterface         activity        ,      H5       H5      runOnUiThread。         
            runOnUiThread(new Runnable() {
               @Override
              public void run() {
            JSONObject object = null;
            try {
                object = new JSONObject(jsonString);
            } catch (JSONException e) {
                e.printStackTrace();
            }
            AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
            builder.setTitle("H5  Android     ");
            if (object != null) {
                builder.setMessage(object.optString("message", ""));
            }
            builder.setNegativeButton(android.R.string.ok, null);
            AlertDialog dialog = builder.create();
            dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
                @Override
                public void onDismiss(DialogInterface dialog) {
                    // dialog     ,   H5   
                    reloadJs("alert", "iOS change javascript to message for H5");
                }
            });
            dialog.show();
               }
             });


        }
    }

H 5呼び出しのメソッドに次のコードを追加すればよい
    //H5  Android      dialog
    function toast(){
        window.action.toast("{\"message\":\"From H5 message\"}");
    }

 
@JavascriptInterfaceのこのメソッドと現在のactivityは同じスレッドではないので、H 5の呼び出しとH 5にコールバックするコードを追加してrunOnUIThreadに書きます.そうでないと以下の異常が放出されます
05-17 16:11:00.847 13875-14010/com.j1 E/AndroidRuntime: FATAL EXCEPTION: JavaBridge
    Process: com.j1, PID: 13875
    java.lang.RuntimeException: java.lang.Throwable: A WebView method was called on thread 'JavaBridge'. All WebView methods must be called on the same thread. (Expected Looper Looper (main, tid 2) {839b89} called on Looper (JavaBridge, tid 349) {a0a3877}, FYI main Looper is Looper (main, tid 2) {839b89})
        at android.webkit.WebView.checkThread(WebView.java:2486)
        at android.webkit.WebView.loadUrl(WebView.java:938)
        at com.j1.MainActivity.reloadJs(MainActivity.java:89)
        at com.j1.MainActivity.access$100(MainActivity.java:18)
        at com.j1.MainActivity$JsAction$1.onDismiss(MainActivity.java:76)
        at android.app.Dialog$ListenersHandler.handleMessage(Dialog.java:1361)
        at android.os.Handler.dispatchMessage(Handler.java:105)
        at android.os.Looper.loop(Looper.java:164)
        at android.os.HandlerThread.run(HandlerThread.java:65)
     Caused by: java.lang.Throwable: A WebView method was called on thread 'JavaBridge'. All WebView methods must be called on the same thread. (Expected Looper Looper (main, tid 2) {839b89} called on Looper (JavaBridge, tid 349) {a0a3877}, FYI main Looper is Looper (main, tid 2) {839b89})
        at android.webkit.WebView.checkThread(WebView.java:2476)
        at android.webkit.WebView.loadUrl(WebView.java:938) 
        at com.j1.MainActivity.reloadJs(MainActivity.java:89) 
        at com.j1.MainActivity.access$100(MainActivity.java:18) 
        at com.j1.MainActivity$JsAction$1.onDismiss(MainActivity.java:76) 
        at android.app.Dialog$ListenersHandler.handleMessage(Dialog.java:1361) 
        at android.os.Handler.dispatchMessage(Handler.java:105) 
        at android.os.Looper.loop(Looper.java:164) 
        at android.os.HandlerThread.run(HandlerThread.java:65) 

IOS-UIWebviewを通るdelegate
主に(BOOL)webViewで: shouldStartLoadWithRequest:navigationType:プロトコルメソッドではrequestを解析することでiOSメソッドの情報を得る.
例:
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
    
    NSURL *url = [request URL];
    NSString *method = [url host];
    NSString *queryString = [url query];
    if (queryString == nil) {
        [self trigger:method jsonParam:nil];
        return YES;
    }
    [self trigger:method jsonParam:nil];
    return YES;
}

iOSの既存のメソッドに直接呼び出して対応するメソッドに呼び出せばよい
-(void)trigger:(NSString *)method jsonParam:(NSString *)jsonParam{
    
    NSString * methodName = [NSString stringWithFormat: jsonParam!=nil?@"%@:param:":@"%@",method];
    NSLog(@"methodName = %@",methodName);
    SEL sel = NSSelectorFromString(methodName);
    if( [self respondsToSelector:sel] ) {
        [self performSelector:sel  withObject:jsonParam];        
    }
}

H 5でiframeを追加することによってiOSプロトコルへのコールバックを実現する方法
var  src = schemename + action +"?"+"message=2"; //       url   
var iframe = document.createElement("iframe");
iframe.src = src;
document.documentElement.appendChild(iframe);
iframe.parentNode.removeChild(iframe);
iframe = null;

 
具体的なコードはダウンロードできます.
コードは具体的に実現する:ボタンをクリックして、H 5がAPPの方法を呼び出すことを実現して、同時にAPPがH 5の方法を呼び出してH 5の関連する内容を変える
Androidコードダウンロードアドレス:クリックしてリンクを開く
iOSコードダウンロードアドレス:クリックしてリンクを開く