Merge pull request #14154 from Dimon4eg/fix-crash-in-web-view-on-android

Fix crash in web view on android
This commit is contained in:
pandamicro 2015-10-22 10:35:00 +08:00
commit a7e5946b7d
3 changed files with 45 additions and 11 deletions

View File

@ -11,6 +11,27 @@ import android.widget.FrameLayout;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.net.URI; 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 { public class Cocos2dxWebView extends WebView {
private static final String TAG = Cocos2dxWebViewHelper.class.getSimpleName(); private static final String TAG = Cocos2dxWebViewHelper.class.getSimpleName();
@ -75,7 +96,20 @@ public class Cocos2dxWebView extends WebView {
Log.d(TAG, "Failed to create URI from url"); Log.d(TAG, "Failed to create URI from url");
} }
return Cocos2dxWebViewHelper._shouldStartLoading(mViewTag, urlString); 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 @Override
@ -102,7 +136,7 @@ public class Cocos2dxWebView extends WebView {
}); });
} }
} }
public void setWebViewRect(int left, int top, int maxWidth, int maxHeight) { public void setWebViewRect(int left, int top, int maxWidth, int maxHeight) {
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT); FrameLayout.LayoutParams.WRAP_CONTENT);

View File

@ -147,10 +147,9 @@ public:
/** /**
* Call before a web view begins loading. * Call before a web view begins loading.
* Note: Any OpenGL related operations are forbidden in this callback.
* *
* @param callback The web view that is about to load new content. * @param callback The web view that is about to load new content.
* @return YES if the web view should begin loading content; otherwise, NO . * @return YES if the web view should begin loading content; otherwise, NO.
*/ */
void setOnShouldStartLoading(const std::function<bool(WebView *sender, const std::string &url)>& callback); void setOnShouldStartLoading(const std::function<bool(WebView *sender, const std::string &url)>& callback);

View File

@ -45,7 +45,7 @@
static const std::string s_defaultBaseUrl = "file:///android_asset/"; static const std::string s_defaultBaseUrl = "file:///android_asset/";
static const std::string s_sdRootBaseUrl = "file://"; static const std::string s_sdRootBaseUrl = "file://";
static std::string getFixedBaseUrl(const std::string& baseUrl) static std::string getFixedBaseUrl(const std::string& baseUrl)
{ {
std::string fixedBaseUrl; std::string fixedBaseUrl;
if (baseUrl.empty()) if (baseUrl.empty())
@ -402,20 +402,21 @@ namespace cocos2d {
} }
bool WebViewImpl::shouldStartLoading(const int viewTag, const std::string &url) { bool WebViewImpl::shouldStartLoading(const int viewTag, const std::string &url) {
bool allowLoad = true;
auto it = s_WebViewImpls.find(viewTag); auto it = s_WebViewImpls.find(viewTag);
if (it != s_WebViewImpls.end()) { if (it != s_WebViewImpls.end()) {
auto webView = s_WebViewImpls[viewTag]->_webView; auto webView = it->second->_webView;
if (webView->_onShouldStartLoading) { if (webView->_onShouldStartLoading) {
return webView->_onShouldStartLoading(webView, url); allowLoad = webView->_onShouldStartLoading(webView, url);
} }
} }
return true; return allowLoad;
} }
void WebViewImpl::didFinishLoading(const int viewTag, const std::string &url){ void WebViewImpl::didFinishLoading(const int viewTag, const std::string &url){
auto it = s_WebViewImpls.find(viewTag); auto it = s_WebViewImpls.find(viewTag);
if (it != s_WebViewImpls.end()) { if (it != s_WebViewImpls.end()) {
auto webView = s_WebViewImpls[viewTag]->_webView; auto webView = it->second->_webView;
if (webView->_onDidFinishLoading) { if (webView->_onDidFinishLoading) {
webView->_onDidFinishLoading(webView, url); webView->_onDidFinishLoading(webView, url);
} }
@ -425,7 +426,7 @@ namespace cocos2d {
void WebViewImpl::didFailLoading(const int viewTag, const std::string &url){ void WebViewImpl::didFailLoading(const int viewTag, const std::string &url){
auto it = s_WebViewImpls.find(viewTag); auto it = s_WebViewImpls.find(viewTag);
if (it != s_WebViewImpls.end()) { if (it != s_WebViewImpls.end()) {
auto webView = s_WebViewImpls[viewTag]->_webView; auto webView = it->second->_webView;
if (webView->_onDidFailLoading) { if (webView->_onDidFailLoading) {
webView->_onDidFailLoading(webView, url); webView->_onDidFailLoading(webView, url);
} }
@ -435,7 +436,7 @@ namespace cocos2d {
void WebViewImpl::onJsCallback(const int viewTag, const std::string &message){ void WebViewImpl::onJsCallback(const int viewTag, const std::string &message){
auto it = s_WebViewImpls.find(viewTag); auto it = s_WebViewImpls.find(viewTag);
if (it != s_WebViewImpls.end()) { if (it != s_WebViewImpls.end()) {
auto webView = s_WebViewImpls[viewTag]->_webView; auto webView = it->second->_webView;
if (webView->_onJSCallback) { if (webView->_onJSCallback) {
webView->_onJSCallback(webView, message); webView->_onJSCallback(webView, message);
} }