cocos2d-xでwebViewを使用し、コールバックで戻り値を受け取る

Pocket

スクリーンショット 2014-06-30 15.19.30

久しぶりの投稿です。
cocos2d-xでWebViewを使う方法を調べたので、メモとして残しておきます。
実はcocos2d-xにはアプリ内でWebブラウジングする機能ないみたいなんですけど、GREEさんがMITライセンスで作ってくれてました。さすがGREEさんですね。

今回はそれを利用して、Webページの表示と、Webページからの戻り値をコールバックで受け取るところまでをやってみようと思います。

【参考にしたサイト】

Cocos2d-x 勉強第11回「WebViewを試す」

まずはSDKをダウンロード

※ここから暫く設定などを長々書いてるんで、使い方だけ知りたい方はこちらのリンクへ飛んで下さい。

以下のページから、SDKをまるっとダウンロードしてきます。

GreePlatformSDKCocos2dx
https://github.com/gree/GreePlatformSDKCocos2dx

GREEのSDKにはGREEと連携する色々な機能があるみたいですが、その中のwebview_pluginを使います。

補足:対応してるバージョン

GreePlatformSDKCocos2dxが対応しているのは2014年6月30日現在2.x系となります。
ぼくも2.x系を使っているのでそのままセッティングしていきますが、
3.x系で使いたいという場合は参考にしたサイト(Cocos2d-x 勉強第11回「WebViewを試す」)に詳しくのってましたので、そっちを参考にして下さい。

それではセットアップしましょう

まだcocos2d-x自体入れてない場合、このGreePlatFormSDKCocos2dx内にあるsetup.shを使ってダウンロード&設定までまるっとできます。
やり方はGitHubにも書いていますが、まあこんな感じ。

$ cd (GreePlatformSDKCocos2dxのディレクトリ)
$ ./setup.sh -m webview

あとはそのディレクトリ内に作成されたcocos2d-xでプロジェクトを作成したらきっと幸せになれますね。
あるいはそのソースを既存のcocos2d-xディレクトリ内に投げ込んで置き換えちゃえば使えるようになります(たぶん)。

ではその方法でセットアップを済ませ、快適なWebViewライフを満喫しましょう。

 だが断る。

もう既存のcocos2d-xプロジェクトは作ってるし、置き換えとか怖くてしたくない(そもそも使ってるバージョンが違うよぉ)という場合、差分を見ながら手動で置き換えます。

多分ここはそれぞれの環境によって微妙に違ったりすると思うんで参考になるかはわかりませんが、ぼくは以下の手順で使えるようにしました。

  1. webview_pluginディレクトリをcocos2d-xディレクトリ内へ配置
  2. Androidで使えるようにあちこちいじる
  3. iOSで使えるようにあれこれいじる

※基本はGreePlatformSDKCocos2dx-master内のwebview_pluginディレクトリ内のパーツをしかるべき場所に配置したら使えるようになるかと思います。

まずはwebview-pluginディレクトリをコピー

GreePlatformSDKCocos2dx-master.zipを解凍したら、その直下にwebview_pluginディレクトリがあるかと思います。
その中に入れ子であるwebview_pluginディレクトリをコピーし、cocos2d-xディレクトリ直下に置きます。
(一応ライセンスもその中に入れておきます)

webviewplugin

webview_pluginのディレクトリには以下のものが入ってます。

・webview_plugin
 -android
 -include
 -ios

Androidで使えるようにする設定

次に、Androidで使えるようにします。
手順は以下の通りです。

  1. Cocos2dxHelper.javaをいじる
  2. Cocos2dxWebView.javaを配置する
  3. Android.mkをいじる

Cocos2dxHelper.javaをいじる

(cocos2dxディレクトリ)/platform/android/java/src/org/cocos2dx/lib/Cocos2dxHelper.javaに以下の2行を追加します。

package org.cocos2dx.lib;

import java.io.UnsupportedEncodingException;
import java.util.Locale;
//importにCocos2dxWebViewを追加
import org.cocos2dx.lib.gree.webview.Cocos2dxWebView;

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.res.AssetManager;
import android.os.Build;
import android.os.Environment;

public class Cocos2dxHelper {
/* (..省略..) */
    public static void init(final Context pContext, final Cocos2dxHelperListener pCocos2dxHelperListener) {
       /* (..省略..) */
       //メソッドの最後に追加する
       Cocos2dxWebView.setContext(pContext);
    }
/* (..以下略..) */
}

Cocos2dxWebView.javaを配置する

次に、webview_pluginディレクトリ内にあったgreeディレクトリをぬるっとコピーし、(cocos2dxディレクトリ)/platform/android/java/src/org/cocos2dx/lib/に配置します。
このディレクトリは、Eclipseではlibcocos2dxのプロジェクトとして表示されてると思うんで、ちゃんと配置できてたら以下のような感じになります。

cocos2dxwebview

Android.mkをいじる

あとは、ちゃんとコンパイルされるようにAndroid.mkを編集しましょう。

//LOCAL_WHOLE_STATIC_LIBRARIESが並んでるところの最後に追加
LOCAL_WHOLE_STATIC_LIBRARIES += cocos_webview_plugin_static

//$(call ...)が並んでるところの最後に追加
$(call import-module,webview_plugin/android)

Android側の設定は以上です。
もしかしたらWebView.hを参照できるようにパスを通す必要があるかもしれないのですが、ぼくの環境では何もしなくてもいけました。

iOS側の設定

iOS側の設定は、ぼくの場合は簡単でした。やっぱりこれもヘッダファイルまでのパスを通す必要がありそうなのに、特に何もする必要もありませんでした。
逆にぼくのやり方が変なのかな(´・ω・`)?

webview_pluginディレクトリをプロジェクトに追加

プロジェクト直下に、さっきいれたwebview_pluginディレクトリをそのまま追加しちゃいます。

webiew

 

するともれなくAndroid用のcppファイルが二つ(CCWebView.cpp、Java_org_cocos2dx_lib_Cocos2dxWebView.cpp)、Compile Sourcesリスト内に入ってしまいます。
そんなものは「自分、不器用ですから」と言いながらリストから除外しちゃいましょう。

delete

 

これで、とりあえず使用の準備完了です。
次に実際に表示をしてみます。

とりあえず使ってみる

折角なので、最初プロジェクトを作成する時に作られる「HelloWorldScene.cpp」のinit()内に実装をしてみます。

//メソッドの外、staticな変数として持っておく
CCWebView *pWebView = NULL;

//HelloWorldScene.cppのinit()メソッド内
pWebView = CCWebView::create();
CCSize eglSize = CCDirector::sharedDirector()->getOpenGLView()->getFrameSize();
pWebView->setRect(0, 0, eglSize.width , eglSize.height );
pWebView->setVisibility(true);
pWebView->loadUrl("http://yahoo.co.jp");

GreePlatformSDKCocos2dx内のサンプルを参考にしました。
setRect()内に指定するサイズはCCDirector::sharedDirector()->getVisibleSize()だとなぜかはみ出てしまいますが(マルチ解像度対応がまた悪さしてるかも)、CCDirector::sharedDirector()->getOpenGLView()->getFrameSize()だとぴったりでした。

実行してみる

スクリーンショット 2014-06-30 17.12.44

ばっちりですね。

メモリ管理をどうすればいいかはまだよくわかりませんが(このstaticのやり方でいいのかも)、とりあえず表示は簡単にできました。

Webサイト側からコールバックで戻り値を受け取る

このWebView、Javascriptを使って戻り値を受け取ることもできます。
やり方は以下の通りです。

  1. CCWebViewDelegateインターフェイスを実装したクラスを作成してセット
  2. Webページ側に専用のコールバック用関数を記述

これも簡単ですね。

CCWebViewDelegateインターフェイスを実装

これも、サンプルを参考にしました。HelloWorldSceneに実装しちゃいましょう。

class HelloWorld : public cocos2d::CCLayer, public cocos2d::webview_plugin::CCWebViewDelegate
{
public:
    /* (..省略..) */
    //サンプルにあったやつそのままです。メッセージボックスを呼び出してくれます
    void showResult(std::string* str1, std::string* str2);
    //CCWebViewDelegateで実装しないといけないメソッド
    void callbackFromJS(CCWebView *webview, CCString *message);
};

次に、ソースファイルの実装です。

bool HelloWorld::init() {
    /*(..省略..)*/
    //CCWebViewDelegateインターフェイスをセットする
    CCWebView::setWebViewDelegate(this);
    pWebView = CCWebView::create();
	CCSize eglSize = CCDirector::sharedDirector()->getOpenGLView()->getFrameSize();
    pWebView->setRect(0, 0, eglSize.width , eglSize.height );
    pWebView->setVisibility(true);
    pWebView->loadUrl("http://brbranch.jp/test/test.html");

    return true;
}
/*  以下はGreePlatformSDKCocos2dxのサンプルソースをほぼそのまま使ってます  */
void HelloWorld::showResult(std::string* str1, std::string* str2){
    CCMessageBox(str1->c_str(), str2->c_str());
}

void HelloWorld::callbackFromJS(CCWebView *webview, CCString *message){
    CCLog("++++++++++callbackFromJS %s", message->getCString());
    std::string str1 = "Callback";
    std::string str2 = "Message From JS";
    showResult(&str2, &(message->m_sString));
    pWebView->destroy();
}

このcallbackFromJS内で色々と処理を書けばいいわけですね。
ちなみに、コールバックが呼ばれるとメッセージボックスが表示され、WebViewは破棄されるという動きをします。

Webページからコールバックする

非常に長くなってしまいましたが、いよいよラストです。
WebページからJavascriptを使ってアプリへ戻り値を投げます。

ただ、それをする為にはiOS、Androidで処理を分けなければなりません。
それぞれコールバックの仕方が以下のように違うからです。

Android・・・window.Cocos2dx.call(テキスト)メソッドを使う
iOS・・・リンク「cocos2dx:テキスト」へ移動する

これは、AndroidとiOSそれぞれでネイティブとWebViewとの連携方法がそもそも違うので、仕方ありません。

というわけで、クロスプラットフォーム対応のJavaScriptファイルを作成しましょう。

(function() {
   var sp = {};
   var isAndroid = navigator.userAgent.match(/Android/);
   var isIOs = navigator.userAgent.match(/iPhone/) ||
   navigator.userAgent.match(/iPod/) ||
   navigator.userAgent.match(/iPad/);
   sp.call = function(text) {
      if (isAndroid) {
         window.Cocos2dx.call(text);
      } else if(isIOs) {
         window.location.href = "cocos2dx:" + text;
      } else {
         window.location.href = text;
      }
   };
   window.sp = sp;
})();

これで、sp.call()というのを呼べばそれぞれの動きをさせることができます。
というわけで、次はhtmlファイルを作成します。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <style type="text/css" media="screen">...</style>
  <script type="text/javascript" src="sp.js"></script>
  <title>コールバックテスト</title>
</head>
<body>
  <p><ul>
    <li><a href="#" onclick='sp.call("test")'>テスト</a></li>
    <li><a href="#" onclick='sp.call("test2")'>テスト2</a></li>
    <li><a href="#" onclick='sp.call("test3")'>テスト3</a></li>
  </ul></p>
</body>
</html>

じゃあ、実行してみましょう

実行するとこんな感じです。

スクリーンショット 2014-06-30 17.56.56

たとえばテスト3をクリックすると

スクリーンショット 2014-06-30 17.57.08

 

ちゃんとメッセージボックスが呼ばれました。
Android端末でも同様にメッセージボックスが呼ばれます。

思った以上に記事が長くなったし、正直コールバックが出来るから何しようというヴィジョンがぼくにはないのですが(´・ω・`)

でも、GREEさんさすがすぎですね。これから色々と使わせて貰いたいです。

cocos2d-xでwebViewを使用し、コールバックで戻り値を受け取る” への1件のコメント

  1. ピンバック: Cocos2d-x v3.系 WebViewについて | Curry is Drink!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です