cocos2d-x를 이용하여 Youtube동영상을 재생하는 웹화면을 개발 중인데
cocos2d-x 3.3 이상부터 Webview를 지원하여 걱정없이 개발 하고 있었습니다.
개발 다 끝내고 iOS테스트 완료 하였습니다..
Android 테스트하는데... 좌절하고 말았습니다.
3가지 문제가 발생했습니다.
- 유투브 동영상 전체화면을 지원불가.
- 동영상 전체화면까지 수정했으나 전체화면에서 가로/세로 화면전환 불가.
- Webview를 remove하여도 동영상 사운드 계속 재생.
1, 2번 문제 부터 해결해 보도록 하겠습니다.
cocos2d에 아래 경로로 가시면 Cocos2dxWebView.java 파일이 있습니다.
"프로젝트명"/cocos2d/cocos/platform/android/java/src/org/cocos2dx/lib/Cocos2dxWebView.java
이 파일을 아래의 소스로 교체 합니다.
[ Cocos2dxWebView.java File ]
package org.cocos2dx.lib;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.os.Build;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.webkit.JsResult;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.FrameLayout;
import android.widget.Toast;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.concurrent.CountDownLatch;
class ShouldStartLoadingWorker implements Runnable {
private CountDownLatch mLatch;
private boolean[] mResult;
private final int mViewTag;
private final String mUrlString;
ShouldStartLoadingWorker(CountDownLatch latch, boolean[] result, int viewTag, String urlString) {
this.mLatch = latch;
this.mResult = result;
this.mViewTag = viewTag;
this.mUrlString = urlString;
}
@Override
public void run() {
this.mResult[0] = Cocos2dxWebViewHelper._shouldStartLoading(mViewTag, mUrlString);
this.mLatch.countDown(); // notify that result is ready
}
}
public class Cocos2dxWebView extends WebView {
private static final String TAG = Cocos2dxWebViewHelper.class.getSimpleName();
private int mViewTag;
private String mJSScheme;
public Cocos2dxWebView(Context context) {
this(context, -1);
}
@SuppressLint("SetJavaScriptEnabled")
public Cocos2dxWebView(Context context, int viewTag) {
super(context);
this.mViewTag = viewTag;
this.mJSScheme = "";
this.setFocusable(true);
this.setFocusableInTouchMode(true);
this.getSettings().setSupportZoom(false);
this.getSettings().setJavaScriptEnabled(true);
this.getSettings().setDisplayZoomControls(true);
// `searchBoxJavaBridge_` has big security risk. http://jvn.jp/en/jp/JVN53768697
try {
Method method = this.getClass().getMethod("removeJavascriptInterface", new Class[]{String.class});
method.invoke(this, "searchBoxJavaBridge_");
} catch (Exception e) {
Log.d(TAG, "This API level do not support `removeJavascriptInterface`");
}
this.setWebViewClient(new Cocos2dxWebViewClient());
//this.setWebChromeClient(new WebChromeClient());
// 새로만든 Chromeclient를 추가.
this.setWebChromeClient(new ChromeClient((Cocos2dxActivity)getContext()));
}
public void setJavascriptInterfaceScheme(String scheme) {
this.mJSScheme = scheme != null ? scheme : "";
}
public void setScalesPageToFit(boolean scalesPageToFit) {
this.getSettings().setSupportZoom(scalesPageToFit);
}
class Cocos2dxWebViewClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, final String urlString) {
Cocos2dxActivity activity = (Cocos2dxActivity)getContext();
try {
URI uri = URI.create(urlString);
if (uri != null && uri.getScheme().equals(mJSScheme)) {
activity.runOnGLThread(new Runnable() {
@Override
public void run() {
Cocos2dxWebViewHelper._onJsCallback(mViewTag, urlString);
}
});
return true;
}
} catch (Exception e) {
Log.d(TAG, "Failed to create URI from url");
}
boolean[] result = new boolean[] { true };
CountDownLatch latch = new CountDownLatch(1);
// run worker on cocos thread
activity.runOnGLThread(new ShouldStartLoadingWorker(latch, result, mViewTag, urlString));
// wait for result from cocos thread
try {
latch.await();
} catch (InterruptedException ex) {
Log.d(TAG, "'shouldOverrideUrlLoading' failed");
}
return result[0];
}
@Override
public void onPageFinished(WebView view, final String url) {
super.onPageFinished(view, url);
Cocos2dxActivity activity = (Cocos2dxActivity)getContext();
activity.runOnGLThread(new Runnable() {
@Override
public void run() {
Cocos2dxWebViewHelper._didFinishLoading(mViewTag, url);
}
});
}
@Override
public void onReceivedError(WebView view, int errorCode, String description, final String failingUrl) {
super.onReceivedError(view, errorCode, description, failingUrl);
Cocos2dxActivity activity = (Cocos2dxActivity) getContext();
activity.runOnGLThread(new Runnable() {
@Override
public void run() {
Cocos2dxWebViewHelper._didFailLoading(mViewTag, failingUrl);
}
});
}
}
public void setWebViewRect(int left, int top, int maxWidth, int maxHeight) {
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT);
layoutParams.leftMargin = left;
layoutParams.topMargin = top;
layoutParams.width = maxWidth;
layoutParams.height = maxHeight;
layoutParams.gravity = Gravity.TOP | Gravity.LEFT;
this.setLayoutParams(layoutParams);
}
// 전체화면 가능한 ChromeClient를 WebVhromeClient를 상속받아 새로 만듬...
public final class ChromeClient extends WebChromeClient {
private View mCustomView;
private Activity mActivity;
public ChromeClient(Activity activity) {
this.mActivity = activity;
}
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
result.confirm();
return super.onJsAlert(view, url, message, result);
}
private int mOriginalOrientation;
private FullscreenHolder mFullscreenContainer;
private CustomViewCallback mCustomViewCollback;
@Override
public void onShowCustomView(View view, CustomViewCallback callback) {
if (mCustomView != null) {
callback.onCustomViewHidden();
return;
}
mOriginalOrientation = mActivity.getRequestedOrientation();
FrameLayout decor = (FrameLayout) mActivity.getWindow().getDecorView();
mFullscreenContainer = new FullscreenHolder(mActivity);
mFullscreenContainer.addView(view, ViewGroup.LayoutParams.MATCH_PARENT);
decor.addView(mFullscreenContainer, ViewGroup.LayoutParams.MATCH_PARENT);
mCustomView = view;
mCustomViewCollback = callback;
//mActivity.setRequestedOrientation(mOriginalOrientation);
// 기존의 프로젝트의 Orientation을 따르는 것이 아니라 전체화면일 경우는 Sensor의 의해 Orientation결정
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
}
@Override
public void onHideCustomView() {
if (mCustomView == null) {
return;
}
FrameLayout decor = (FrameLayout) mActivity.getWindow().getDecorView();
decor.removeView(mFullscreenContainer);
mFullscreenContainer = null;
mCustomView = null;
mCustomViewCollback.onCustomViewHidden();
mActivity.setRequestedOrientation(mOriginalOrientation);
}
}
static class FullscreenHolder extends FrameLayout {
public FullscreenHolder(Context ctx) {
super(ctx);
setBackgroundColor(ctx.getResources().getColor(android.R.color.black));
}
@Override
public boolean onTouchEvent(MotionEvent evt) {
return true;
}
}
}
위 소스로 교체시 WebView에서 동영상 전체화면과 가로/세로는 해결 됩니다.
그 다음 WebView종료시 계속 재생되는 사운드가 문제인데 이부분은 아래 파일을 수정해야 합니다.
"프로젝트명"/cocos2d/cocos/platform/android/java/src/org/cocos2dx/lib/Cocos2dxWebViewHelper.java
[ Cocos2dxWebViewHelper.java File ]
public static void removeWebView(final int index) {
sCocos2dxActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
Cocos2dxWebView webView = webViews.get(index);
if (webView != null) {
webViews.remove(index);
sLayout.removeView(webView);
// webview를 Destory 해야 사운드 재생이 멈춘다.
webView.destroy();
webView = null;
}
}
});
}
removeWebView Method를 위와 같이 수정시 WebView를 remove할 경우 사운드 재생이 멈춥니다.
또는 setStopWebView와 같은 Method를 새로 만들어 사운드 재생만을 멈추게 할수도 있습니다.
위 2가지를 수정하면 정상적으로 유투브 동영상을 재생할 수 있습니다.
cocos2d에서 하루 빨리 수정해주었으면 하내요 ^^
그전에 조금이나마 도움이 될 수 있을 것 같아 공유합니다.
근데 더 큰 문제 점이 있었내요.
Android 문제를 해결 하고 마켓에 올렸는데
유투브 동영상을 제 앱에서 바로 실행하면 앱이 거절 당한다는 메시지가 날라 왔습니다.
유투브 동영상으로 수입을 벌면 안된다는 얘기더군요.
결국 유투브 동영상을 제 앱에 웹브라우저 에서 실행하면 안되고
유투브 사이트로 이동하여 플레이 하는 걸로 변경하여 해결해야 했습니다.
막상 이렇게 해결 하고 나니 제 앱이 쓸모가 없어졌내요. ㅠㅠ
구글이 점점 앱 제한이 커지는 것 같습니다.
그래도 안전을 위한 구글에 선택이니 믿고 따라야죠. ^^
'- cocos2d-x ' 카테고리의 다른 글
[ cocos2d-x] cocos2d-x에서 지원하는 Texture 포맷 (0) | 2016.09.30 |
---|---|
[ cocos2d-x 3.9 ] ui::EditBox Keyboard 활성/비활성 이벤트 (0) | 2015.12.23 |
[ cocos2d-x 3.9 ] cocos2d-x에서 Thread 쉽게 이용하기. (6) | 2015.12.22 |
[ cocos2d-x 3.9 ] Sprite Copy 활용하기 (앱 속도 및 메모리 최적화) (1) | 2015.12.09 |
[ cocos2d-x 3.9 ] ScrollView 사용시 Menu 부분 터치하면 스크롤 안되는 문제 (7) | 2015.12.08 |