galapagosit’s blog

本家 > http://galapagosit.com/

Cocos2d-JS WebView連携

Cocos2d-JSはCocos2d-x v3.3rc0ベースなので下記の方が作成された仕組みが使えるはず!

cocos2d-x-3.x系で使えるWebView作った - 銀の人のメモ帳

と思ったのだがjsから叩けるインターフェースは未だ用意されていなかった。。。
のでbindingした話。

結果

こんな感じで一部webviewにすることが可能になった!

f:id:galapagosit:20141212102529p:plain

やり方

Cocos2d-JS v3.0 で他の言語とやり取り (JavaScript → C++ 編) | ましろいろのねこ

上記の方法を参考に下記のソースをbindingする

WebViewBridge.h

#ifndef WEBVIEWBRIDGE_H
#define WEBVIEWBRIDGE_H

#include <iostream>

class WebViewBridge {
public:
    static void addWebView(const std::string rootNodeName,
                           const std::string webViewNodeName,
                           float positionX,
                           float positionY,
                           float sizeX,
                           float sizeY,
                           const std::string loadURL,
                           bool scalesPageToFit);
};

#endif

WebViewBridge.cpp

#include "WebViewBridge.h"
#include "cocos2d.h"

#include "ui/CocosGUI.h"

USING_NS_CC;

void WebViewBridge::addWebView(const std::string rootNodeName,
                               const std::string webViewNodeName,
                               float positionX,
                               float positionY,
                               float sizeX,
                               float sizeY,
                               const std::string loadURL,
                               bool scalesPageToFit){
    
    auto webView = cocos2d::experimental::ui::WebView::create();
    webView->setContentSize(Size(sizeX, sizeY));
    webView->setPosition(Point(positionX, positionY));
    webView->loadURL(loadURL);
    webView->setScalesPageToFit(scalesPageToFit);
    // js側で取得できるように名前をつける
    webView->setName(webViewNodeName);
    
    // コールバック関数を登録
    webView->setOnShouldStartLoading(
                                [](cocos2d::experimental::ui::WebView *sender, const std::string &url) {
                                    // TODO androidだと呼ばれないっぽい
                                    CCLOG("WebViewBridge OnShouldStartLoading");
                                    return true;
                                });
    webView->setOnDidFinishLoading(
                                     [](cocos2d::experimental::ui::WebView *sender, const std::string &url) {
                                         CCLOG("WebViewBridge OnDidFinishLoading");
                                     });
    webView->setOnDidFailLoading(
                                     [](cocos2d::experimental::ui::WebView *sender, const std::string &url) {
                                         CCLOG("WebViewBridge setOnShouldStartLoading");
                                     });
    
    Scene* scene = Director::getInstance()->getRunningScene();
    Node* root = scene->getChildByName(rootNodeName);
    root->addChild(webView);
}

引数にObjectではなくstringでnode名などを渡しているのは、ジェネレート時にヘッダーファイルの解決でこけてしまうので止むなくこうしています。

補足

自分の場合、この仕組を使ってwebview内で自分で作ったアプリのリンク一覧のあるページを載せようと思っていました。

しかしandroidのwebviewで

market://
を踏んでも反応しない
http://play.google.com/...
なリンクも内部で展開されてしまう(そこからインストール出来ない)

ため、下記を参考に処理を加えました

http://stackoverflow.com/questions/14555040/allow-all-market-links-from-inside-a-webview-to-open-google-play-store

frameworks/js-bindings/cocos2d-x/cocos/platform/android/java/src/org/cocos2dx/lib/Cocos2dxWebView.java

        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String urlString) {
            URI uri = URI.create(urlString);
            if (uri != null && uri.getScheme().equals(jsScheme)) {
                Cocos2dxWebViewHelper._onJsCallback(viewTag, urlString);
                return true;
            }

            // マーケットの場合はplay storeに飛ばす処理 START
            Uri _uri = Uri.parse(urlString);
            if (_uri.getScheme().equals("market") || (_uri.getScheme().startsWith("http") && _uri.getHost().equals("play.google.com"))) {
                try {
                    Intent intent = new Intent(Intent.ACTION_VIEW);
                    intent.setData(_uri);
                    Activity host = (Activity) view.getContext();
                    host.startActivity(intent);
                    return true;
                } catch (ActivityNotFoundException e) {
                  Log.d(TAG, "shouldOverrideUrlLoading ActivityNotFoundException");
                }
            }
            // マーケットの場合はplay storeに飛ばす処理 END

            return Cocos2dxWebViewHelper._shouldStartLoading(viewTag, urlString);
        }