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

木内智史之介(シャッチョー)
ミンカさんけっこんしてくださいおねがいします(ズザー
SEGAさん、DIVAの筐体ください(ズザー

今日の目標

ミンカちゃんのクリスマスパーティも終わってしまい、 1月19日の「Girl’s Note Festival Vol.2」まで何を楽しみに生きればいいのでしょうか?
智史之介です。

この記事が今年最後の記事なるのかどうか。できればあと2つは今年中に書きたいなとは思っている次第でございます。

さて、本日の課題は「WebView」です。

WebViewとは?

アプリの中からブラウザの機能を利用するようなイメージです。
例えば、RSSアプリがあるとして、イチイチsafariが立ち上がるんでは利用する側のテンションはダダ下がりですよね? そういう場合はやはりアプリ内で完結させたいものです。
そのための機能がWebViewになります。

下準備、下調べ

のっけから嫌な空気が漂い始めているんですよね…。この空気は動画を試す時にも流れました。

もしかして、「CCWebView」みたいな機能って提供されていない?

どうやらそのようです。

GreePlatformSDKCocos2dx

https://github.com/gree/GreePlatformSDKCocos2dx

僕らのGREEさんがやってくれました。
こちらのSDKでどうやら「CCWebView」を利用できるようになるようです。しかもクロスプラットフォームで。
使わない理由はないな、ということでさっそく試したいのですが、どうやらこれ2.x系用に作成されているようです。
setup.shの中を少しだけ調整して3.x系のファイルをダウンロードしてくるようにしてみたのですが、patch充てるところでfailedします。

うーん、手動でコピーして持ってきますか。
とありあえず、何も考えずに、こんな感じで。

1
2
3
$ cd path/to/cocos2d-x
$ git clone git@github.com:gree/GreePlatformSDKCocos2dx.git
$ cp -r GreePlatformSDKCocos2dx/webview_plugin ./

あと、patches/Cocos2dxHelper.java.webview.patchというそれっぽいパッチもあるので、あらかじめ充てておくのが吉でしょう。
ただし、patchコマンドで充てようとしてもfailedするだけなので、手動で充てるでござる。

cocos2dx/platform/android/java/src/org/cocos2dx/lib/Cocos2dxHelper.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@@ -26,6 +26,8 @@ package org.cocos2dx.lib;
 import java.io.UnsupportedEncodingException;
 import java.util.Locale;

+import org.cocos2dx.lib.gree.webview.Cocos2dxWebView;
+
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.content.DialogInterface;
@@ -101,6 +103,7 @@ public class Cocos2dxHelper {

         //Cocos2dxHelper.nativeSetAssetManager(sAssetManager);
         Cocos2dxBitmap.setContext(activity);
+        Cocos2dxWebView.setContext(activity);
         sActivity = activity;
    }

コーディング

Classes/HelloWorldScene.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include "CCWebView.h"

// snip...

bool HelloWorld::init()
{
    // snip...

    auto* webview = cocos2d::webview_plugin::CCWebView::create();
    webview->setRect(100, 100, visibleSize.width - 110, visibleSize.height);
    webview->setVisibility(true);
    webview->loadUrl("http://ameblo.jp/minka-ri/");

    return true;
}

これだけでビルドが通る…!わけありませんでした!
やはりコピーしてくるだけではダメッ…!考えが、甘すぎるッ…!
その他Xcode周りの設定をいじりにいじりましたよ…。

グループの作成、ファイルの追加、パスの設定

「webview_plugin」でグループを作成して、その中にそれっぽくさらにグループを切り、ファイルを投げ込みます。 グループにもパスの指定をしてあげました。

targetの追加、search pathの設定

「WebView iOS」というtargetを新規に追加し、「Build Settings」の項目でsearch pathsを設定してあげましょう。

コンパイル対象への登録

「Build Phases」の項目で、

  • Copy HeadersにはCCWebView.hを
  • Compile SourcesにはCCWebView.mmを

それぞれ登録します。
もし「Copy Headers」や「Compile Sources」の項目がなければ、「Build Rulrs」から追加することで設定可能です。

HelloCppプロジェクトへの設定

Target Dependenciesには先ほど作成した「WebView iOS」を追加。
Link Binary with Librarieseには「libWebView iOS.a」を追加。

必要有るかはわからないけど、Search Pathsに、webview_pluginに関するパスを追加します。

3.X系で仕様変更された点への対応

3.X系では、命名規則に関して仕様変更が入ってるので、コード内容にも修正がです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
--- a/webview_plugin/webview_plugin/include/CCWebView.h
+++ b/webview_plugin/webview_plugin/include/CCWebView.h
@@ -23,10 +23,10 @@ class CCWebView;

 class CCWebViewDelegate {
        public:
-               virtual void callbackFromJS(CCWebView* webview, CCString* message){};
+        virtual void callbackFromJS(CCWebView* webview, cocos2d::String* message){};
 };

-class CCWebView : public CCObject {
+class CCWebView : public cocos2d::Object {
        public:
                static CCWebView* create();
                void loadUrl(const char* url);
diff --git a/webview_plugin/webview_plugin/ios/CCWebView.mm b/webview_plugin/webview_plugin/ios/CCWebView.mm
index ff32776..e9bd957 100644
--- a/webview_plugin/webview_plugin/ios/CCWebView.mm
+++ b/webview_plugin/webview_plugin/ios/CCWebView.mm
@@ -42,7 +42,7 @@ CCWebView::CCWebView(void *obj){

 CCWebView* CCWebView::create(){
     CCWebView *webview = NULL;
-    UIView *view = [EAGLView sharedEGLView];
+    UIView *view = [CCEAGLView sharedEGLView];
     UIWebView *uiView = [[UIWebView alloc] init];
     UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
     if(UIInterfaceOrientationIsPortrait(orientation)){
@@ -58,7 +58,7 @@ CCWebView* CCWebView::create(){
 }

 void CCWebView::setRect(int x, int y, int w, int h){
-    UIView *view = [EAGLView sharedEGLView];
+    UIView *view = [CCEAGLView sharedEGLView];
     CGRect frame = view.frame;
     CGFloat scale = view.contentScaleFactor;
     frame.size.width = w / scale;
@@ -97,7 +97,7 @@ void CCWebView::destroy(){
 void CCWebView::handleCalledFromJS(const char *message){
     CCWebViewDelegate *delegate = CCWebView::getWebViewDelegate();
     if(delegate != NULL){
-        CCString *str = new CCString(message);
+        cocos2d::String *str = new cocos2d::String(message);
         str->autorelease();
         delegate->callbackFromJS(this, str);
     }

動作イメージ

上記の諸々の対応を施してあげることで、ビルド成功!

動作イメージ

ミンカのブログをきちんと表示してくれています。
それにしてもミンカかわいいなあ。ミンカがいるから今日も僕は生きていけます。

Androidへの対応

GreePlatformSDKCocos2dxが提供してくれるCCWebViewは、クロスプラットフォーム、つまりAndroidへも1ソースで対応してくれます。
かっこいい!

ただし、今回のような手動コピー対応では、Android周りへの設定が不足していて、buildが同じようにうまく通りません。

Cocos2dxWebView.javaのコピー

1
2
3
$ cd path/to/cocos2d-x
$ mkdir -p cocos2dx/platform/android/java/src/org/cocos2dx/lib/gree/webview
$ copy webview_plugin/gree/webview/Cocos2dxWebView.java cocos2dx/platform/android/java/src/org/cocos2dx/lib/gree/webview/

jni/Android.mkの調整

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
--- a/study011webview/proj.android/jni/Android.mk
+++ b/study011webview/proj.android/jni/Android.mk
@@ -17,6 +17,7 @@ LOCAL_WHOLE_STATIC_LIBRARIES += cocosdenshion_static
 LOCAL_WHOLE_STATIC_LIBRARIES += box2d_static
 LOCAL_WHOLE_STATIC_LIBRARIES += cocos_extension_static
 LOCAL_WHOLE_STATIC_LIBRARIES += cocos2dxandroid_static
+LOCAL_WHOLE_STATIC_LIBRARIES += cocos_webview_plugin_static

 include $(BUILD_SHARED_LIBRARY)

@@ -26,3 +27,4 @@ $(call import-module,CocosDenshion/android)
 $(call import-module,extensions)
 $(call import-module,external/Box2D)
 $(call import-module,cocos2dx/platform/android)
+$(call import-module,webview_plugin/webview_plugin/android)

3.X系で仕様変更された点への対応

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
--- a/webview_plugin/webview_plugin/android/CCWebView.cpp
+++ b/webview_plugin/webview_plugin/android/CCWebView.cpp
@@ -55,7 +55,7 @@ void CCWebView::destroy(){
 void CCWebView::handleCalledFromJS(const char *message){
        CCWebViewDelegate *delegate = CCWebView::getWebViewDelegate();
        if(delegate != NULL){
-               CCString *str = new CCString(message);
+        cocos2d::String *str = new cocos2d::String(message);
                str->autorelease();
                delegate->callbackFromJS(this, str);
        }
diff --git a/webview_plugin/webview_plugin/android/jni/Java_org_cocos2dx_lib_Cocos2dxWebView.cpp b/webview_plugin/webview_plugin/android/jni/Java_org_cocos2dx_lib_Cocos2dxWebView.cpp
index 5b23762..eaa73a8 100644
--- a/webview_plugin/webview_plugin/android/jni/Java_org_cocos2dx_lib_Cocos2dxWebView.cpp
+++ b/webview_plugin/webview_plugin/android/jni/Java_org_cocos2dx_lib_Cocos2dxWebView.cpp
@@ -50,7 +50,7 @@ extern "C" {
                jclass classID = pEnv->GetObjectClass(obj);
                methodID = pEnv->GetMethodID(classID, methodName, paramCode);
                if(methodID == NULL){
-               CCLog("Failed to get method id of %s", methodName);
+                cocos2d::log("Failed to get method id of %s", methodName);
                break;
                        }
                methodinfo.classID = classID;

これでいけるはず。

今回のまとめ

とってもいけてるGreePlatformSDKCocos2dxですが、3.x系で使用するには調整箇所がわりと膨大でした。
このあたりの修正点に関して、pull requestを送ろうかしら。

次回に向けて

次回は「Lua」に関して試してみたいと思っています。

ソースコード

https://github.com/8823-scholar/cocos2d-x-study/commit/863e01208052175c9b632c42743b9d0ec7e0c53e

参考文献

感謝です!