Cocos2d-x 3.17.2 集成X5WebView内核方法,完美运行
集成X5WebView内核主要是为了解决Android自带的WebView各种报错问题
研究了好几天,尝试过网上静态集成等等方法,没有一个正常的
后来在腾讯官方下载X5WebView最新SDK 2021-02-25的版本,但是官方Demo项目太老了,编译各种错误,无奈研究好久总算有点眉目,先说明下环境:
Android Studio 4.1.3
Visual studio 2019
Java 1.8
SDK Android API 28
NDK android-ndk-r21e
Cocos2d-x 3.17.2
腾讯浏览服务SDK,官方下载地址:https://x5.tencent.com/tbs/sdk.html
Cocos2d-x集成X5WebView分为两种
先说第一种:类集成,使用Activity来启动X5WebView
步骤1:
创建cocos2d-x项目
先创建一个cocos2d-x 3.17.2项目
使用Android studio 打开项目,同步可能报错,先把项目的插件版本和Gradle版本改为
3.5.3 对应Gradle版本 5.4.1
再设置NDK
设置完成以后项目会自动重新同步,若没有自动同步,请点击界面右上角的同步按钮同步项目
如图:
当项目显示可运行的时候,表示同步完成,项目可进行编译了
步骤2:
下载X5 SDK 引入jar包
https://x5.tencent.com/tbs/sdk.html
下载好后解压如图:
将tbs_sdk_thirdapp_v4.3.0.93_43993_sharewithdownloadwithfile_withoutGame_obfs_20210220_114728.jar复制到项目proj.android\app\libs目录下,没有libs文件夹自己创建
再打开Android studio界面,切换到Project样式
选择SDK文件右键Add As Library
直接确定,项目会自动同步完成
步骤3:
添加权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
Application节点添加 android:usesCleartextTraffic=“true”
解决高版本不能访问http问题,添加完成后如下:
步骤4:
参照官方Demo写一个继承WebView的类
创建名为X5WebView的类,代码如下:
package org.cocos2dx.cpp;import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;import com.tencent.smtt.sdk.WebSettings;
import com.tencent.smtt.sdk.WebView;
import com.tencent.smtt.sdk.WebViewClient;public class X5WebView extends WebView
{//防止加载网页时调起系统浏览器private WebViewClient client = new WebViewClient() {public boolean shouldOverrideUrlLoading(WebView view, String url) {view.loadUrl(url);return true;}};//重写构造函数@SuppressLint("SetJavaScriptEnabled")public X5WebView(Context context, AttributeSet attributeSet) {super(context, attributeSet);this.setWebViewClient(client);WebSettings webSetting = this.getSettings();webSetting.setJavaScriptEnabled(true);webSetting.setJavaScriptCanOpenWindowsAutomatically(true);webSetting.setAllowFileAccess(true);webSetting.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);webSetting.setSupportZoom(true);webSetting.setBuiltInZoomControls(true);webSetting.setUseWideViewPort(true);webSetting.setSupportMultipleWindows(false);webSetting.setAppCacheEnabled(true);webSetting.setDomStorageEnabled(true);webSetting.setGeolocationEnabled(true);webSetting.setAppCacheMaxSize(Long.MAX_VALUE);webSetting.setPluginState(WebSettings.PluginState.ON_DEMAND);webSetting.setCacheMode(WebSettings.LOAD_NO_CACHE);this.getView().setClickable(true);}//重写构造函数public X5WebView(Context context) {super(context);this.setBackgroundColor(85621);}
}
实现WebViewJavaScriptFunction接口,好像调用JS要
代码如下:
package org.cocos2dx.cpp;public interface WebViewJavaScriptFunction {void onJsFunctionCalled(String tag);
}
步骤5:
在 AppActivity 类中添加一个全局变量,用来记录内核初始化状态
再添加X5内核初始化代码
public static boolean mX5WebViewInitState = false; //用于记录内核是否初始化完成
package org.cocos2dx.cpp;import android.os.Bundle;
import org.cocos2dx.lib.Cocos2dxActivity;
import android.os.Build;
import android.util.Log;
import android.view.WindowManager;import com.tencent.smtt.sdk.QbSdk;public class AppActivity extends Cocos2dxActivity {public static boolean mX5WebViewInitState = false; //用于记录内核是否初始化完成public static AppActivity mActivity;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.setEnableVirtualButton(false);super.onCreate(savedInstanceState);if (!isTaskRoot()) {return;}if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {WindowManager.LayoutParams lp = getWindow().getAttributes();lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;getWindow().setAttributes(lp);}mActivity = this;//初始化内核QbSdk.initX5Environment(getApplicationContext(), new QbSdk.PreInitCallback() {@Overridepublic void onCoreInitFinished() {Log.d("调试", "内核初始化完毕");mX5WebViewInitState = true;}@Overridepublic void onViewInitFinished(boolean b) {Log.d("调试", "WebView验证完毕,状态:" + b);mX5WebViewInitState = true;}});}}
再创建布局文件夹
再创建布局文件
创建好后如下图:
创建X5WebViewActivity类,用于显示X5WebView
package org.cocos2dx.cpp;import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;import com.snail.antifake.jni.EmulatorDetectUtil;
import com.tencent.smtt.export.external.interfaces.IX5WebChromeClient;
import com.tencent.smtt.export.external.interfaces.JsResult;
import com.tencent.smtt.sdk.CookieSyncManager;
import com.tencent.smtt.sdk.WebChromeClient;
import com.tencent.smtt.sdk.WebSettings;
import com.tencent.smtt.sdk.WebView;
import com.tencent.smtt.sdk.WebViewClient;import cocos2dx.x5webview.com.R;public class X5WebViewActivity extends Activity
{private Context mContext;private Handler mHandle;private X5WebView mWebView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE); //去掉窗口标题getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); //隐藏顶部的状态栏//如果不是模拟器才开启硬件加速,X5WebView内核模拟器开启硬件加速会报错闪退if(!EmulatorDetectUtil.isEmulator(X5WebViewActivity.this)) {getWindow().setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);}setContentView(R.layout.layout_x5webview);mContext = this;//定时检测内核初始化状态mHandle = new Handler();mHandle.post(new Runnable() {@Overridepublic void run() {if(AppActivity.mX5WebViewInitState){mHandle.removeCallbacks(this);Log.d("调试", "内核初始化完成..");initX5WebView();return;}//延时调用runmHandle.postDelayed(this, 500);Log.d("调试", "内核初始化中..");}});}//初始化并创建 X5WebView,必须在内核初始化完成之后,否则X5WebView是无效的或是调用系统的WebView,通常情况下内核第一次初始化在20秒左右,第二次就很快private void initX5WebView(){mWebView = new X5WebView(mContext, null);// 创建布局文件FrameLayout layout = (FrameLayout) findViewById(android.R.id.content).getRootView();layout.setBackgroundColor(0);layout.addView(mWebView, new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,FrameLayout.LayoutParams.MATCH_PARENT));mWebView.setWebViewClient(new WebViewClient() {@Overridepublic boolean shouldOverrideUrlLoading(WebView view, String url) {return false;}@Overridepublic void onPageFinished(WebView view, String url) {super.onPageFinished(view, url);}});mWebView.setWebChromeClient(new WebChromeClient() {@Overridepublic boolean onJsConfirm(WebView arg0, String arg1, String arg2,JsResult arg3) {return super.onJsConfirm(arg0, arg1, arg2, arg3);}View myVideoView;View myNormalView;IX5WebChromeClient.CustomViewCallback callback;/*** 全屏播放配置*/@Overridepublic void onShowCustomView(View view, IX5WebChromeClient.CustomViewCallback customViewCallback) {}@Overridepublic void onHideCustomView() {if (callback != null) {callback.onCustomViewHidden();callback = null;}if (myVideoView != null) {ViewGroup viewGroup = (ViewGroup) myVideoView.getParent();viewGroup.removeView(myVideoView);viewGroup.addView(myNormalView);}}@Overridepublic boolean onJsAlert(WebView arg0, String arg1, String arg2, JsResult arg3) {//这里写入你自定义的window alertreturn super.onJsAlert(null, arg1, arg2, arg3);}});WebSettings webSetting = mWebView.getSettings();webSetting.setAppCachePath(this.getDir("appcache", 0).getPath());webSetting.setDatabasePath(this.getDir("databases", 0).getPath());webSetting.setGeolocationDatabasePath(this.getDir("geolocation", 0).getPath());webSetting.setPluginState(WebSettings.PluginState.ON_DEMAND);CookieSyncManager.createInstance(mContext);CookieSyncManager.getInstance().sync();//打开网页mWebView.loadUrl("https://www.hao123.com");}@Overridepublic boolean onKeyUp(int keyCode, KeyEvent event) {//重写返回键事件if (keyCode == KeyEvent.KEYCODE_BACK) {if (mWebView != null && mWebView.canGoBack()) {mWebView.goBack();return true;} else {mWebView.destroy();this.finish();}return true;}return super.onKeyUp(keyCode, event);}
}
对上面的代码补充说明
//补充提示:检测模拟器 EmulatorDetectUtil类 需要引入 com.snail:antifake:1.4 依赖包
AndroidManifest添加配置
<activity
android:name="org.cocos2dx.cpp.X5WebViewActivity"
android:parentActivityName="org.cocos2dx.cpp.AppActivity"
android:theme="@android:style/Animation.Activity"
android:hardwareAccelerated="false"
android:screenOrientation="portrait">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="org.cocos2dx.cpp.AppActivity" />
</activity>
添加好后如下:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="cocos2dx.x5webview.com"android:installLocation="auto"><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /><uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.READ_PHONE_STATE" /><uses-feature android:glEsVersion="0x00020000" /><applicationandroid:label="@string/app_name"android:allowBackup="true"android:icon="@mipmap/ic_launcher"android:usesCleartextTraffic="true"><!-- Tell Cocos2dxActivity the name of our .so --><meta-data android:name="android.app.lib_name"android:value="MyGame" /><activityandroid:name="org.cocos2dx.cpp.AppActivity"android:screenOrientation="landscape"android:configChanges="orientation|keyboardHidden|screenSize"android:label="@string/app_name"android:theme="@android:style/Theme.NoTitleBar.Fullscreen"android:launchMode="singleTask"android:taskAffinity="" ><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><activityandroid:name="org.cocos2dx.cpp.X5WebViewActivity"android:parentActivityName="org.cocos2dx.cpp.AppActivity"android:theme="@android:style/Animation.Activity"android:hardwareAccelerated="false"android:screenOrientation="portrait"><meta-dataandroid:name="android.support.PARENT_ACTIVITY"android:value="org.cocos2dx.cpp.AppActivity" /></activity></application></manifest>
最后在AppActivity类中添加启动函数
public boolean createX5WebView(){Intent intent = new Intent(this, X5WebViewActivity.class);startActivity(intent);return true;}public static boolean createHTML5WebView(){return mActivity.createX5WebView(url);}
到此就完成了
下面只需要在cpp文件中添加JNI调用即可,其他细节自行实现
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)bool b = JniHelper::callStaticBooleanMethod("org/cocos2dx/cpp/AppActivity", "createHTML5WebView");if(!b){log("X5WebView浏览器创建失败,内核还未初始化完成");}
#endif
#include "HelloWorldScene.h"
#include "SimpleAudioEngine.h"#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include "cocos/platform/android/jni/JniHelper.h"
#endifUSING_NS_CC;Scene* HelloWorld::createScene()
{return HelloWorld::create();
}static void problemLoading(const char* filename)
{printf("Error while loading: %s\n", filename);printf("Depending on how you compiled you might have to add 'Resources/' in front of filenames in HelloWorldScene.cpp\n");
}bool HelloWorld::init()
{if ( !Scene::init() ){return false;}auto visibleSize = Director::getInstance()->getVisibleSize();Vec2 origin = Director::getInstance()->getVisibleOrigin();auto closeItem = MenuItemImage::create("CloseNormal.png","CloseSelected.png",CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));if (closeItem == nullptr ||closeItem->getContentSize().width <= 0 ||closeItem->getContentSize().height <= 0){problemLoading("'CloseNormal.png' and 'CloseSelected.png'");}else{float x = origin.x + visibleSize.width - closeItem->getContentSize().width/2;float y = origin.y + closeItem->getContentSize().height/2;closeItem->setPosition(Vec2(x,y));}// create menu, it's an autorelease objectauto menu = Menu::create(closeItem, NULL);menu->setPosition(Vec2::ZERO);this->addChild(menu, 1);auto label = Label::createWithTTF("Hello World", "fonts/Marker Felt.ttf", 24);if (label == nullptr){problemLoading("'fonts/Marker Felt.ttf'");}else{label->setPosition(Vec2(origin.x + visibleSize.width/2,origin.y + visibleSize.height - label->getContentSize().height));this->addChild(label, 1);}//打开浏览器按钮auto btn = MenuItemLabel::create(Label::createWithTTF("Open X5WebView Browser", "fonts/arial.ttf", 20),[this](Ref* pSender) {#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)JniHelper::callStaticBooleanMethod("org/cocos2dx/cpp/AppActivity", "createHTML5WebView");
#endif});btn->setPosition(Vec2(Director::getInstance()->getVisibleSize().width / 2, Director::getInstance()->getVisibleSize().height * 0.8f));menu->addChild(btn);return true;
}void HelloWorld::menuCloseCallback(Ref* pSender)
{Director::getInstance()->end();
}
可以看到,运行后Android studio调试输出
可以看到,现在可以播放视频了哈哈
2021-04-02 最新补充:
经过测试,cocos2d-x 3.17.2 使用 X5WebView内核时,在模拟器中闪退的原因已解决
在项目中的Gradle.properties中修改
PROP_APP_ABI=armeabi-v7a
为
PROP_APP_ABI=armeabi-v7a:arm64-v8a:x86
即可解决在打开页面时闪退,原来的硬件加速可设置为默认开启
将AndroidManifest.xml文件中的
android:hardwareAccelerated=“false”
改为
android:hardwareAccelerated=“true”
X5 Activity类中的
if(!EmulatorDetectUtil.isEmulator(X5WebViewActivity.this)) {getWindow().setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
}
这条删掉即可,模拟器依然可以开启硬件加速
Cocos2d-x 3.17.2 集成X5WebView内核方法,完美运行相关推荐
- 【C语言爱心代码】不可思议!C语言仅仅用17行代码居然把爱心完美运行出来了
最近很火电视剧李峋的爱心❤️代码,前段时间我也分享过HTML的爱心代码,相似度95%,后面也有不少小伙伴问我有没有其他语言的爱心代码,然后我翻出了半年前我学习C语言写的爱心代码例子,该源码简单,适合初 ...
- 驱动框架8——将驱动集成到内核中
以下内容源于朱有鹏<物联网大讲堂>课程的学习整理,如有侵权,请告知删除. 十五.将驱动添加到内核中 1.驱动的存在形式 (1)野生,优势是方便调试开发,所以在开发阶段都是这种: (2)家养 ...
- Chrome浏览器上集成IE内核方案
Chrome浏览器上集成IE内核方案 1. 架构图 双核功能的基本思路是,在chrome原有的render 管理的基础上,添加trident内核对象并在切换时将两个渲染的内核数据进行同步,进而将内核网 ...
- Linux Hook系统调用(适用基于x86_64的4.17.0以上的内核版本)
随着rhel8.0于去年5月初发布以来,开启了rhel8.x的时代,随后一段时间里centos.oracle linux也都发布了基于rhel的8.x系统.前段时间我就安装了个centos8.0,但是 ...
- U-BOOT下使用bootm引导内核方法
U-BOOT下使用bootm引导内核方法 注: u-boot 使用的是打上: http://www.hhcn.com/cgi-bin/topic.cgi?forum=3&topic=651 ...
- linux下IPROTO_TCP,TCP/IP协议栈在Linux内核中的运行时序分析
可选题目三:TCP/IP协议栈在Linux内核中的运行时序分析 在深入理解Linux内核任务调度(中断处理.softirg.tasklet.wq.内核线程等)机制的基础上,分析梳理send和recv过 ...
- 电脑卡顿不流畅怎么解决_使命召唤17画面卡顿怎么办-使命召唤17画面卡顿解决方法...
使命召唤17画面卡顿怎么办?使命召唤17是一款备受许多玩家们喜爱的射击游戏,那么这款游戏内遇到卡顿情况要怎么办呢,接下来安卓市场小编为大家带来使命召唤17画面卡顿解决方法. 使命召唤17画面卡顿怎么办 ...
- 网站集成支付宝的方法和所需资料下载
越来越多的网站想做网站集成支付宝功能,本文就详细的讲述一下网站集成支付宝的方法和所需资料下载. 一.网站集成支付宝学习流程建议(在本篇文档中,基本都可以找到相关资源下载) 1.阅读<支付宝接口集 ...
- Spring MVC集成Tiles使用方法
Spring MVC集成Tiles使用方法 转载于:https://www.cnblogs.com/zhujiabin/p/5012129.html
- Linux内核编译和运行
内核获取网站:https://www.kernel.org/pub/linux/kernel/ 步骤如下: 1.打开终端,更改用户权限为root.具体做法是在终端输入sudo su,然后按提示输入密码 ...
最新文章
- Google Colab——用谷歌免费GPU跑你的深度学习代码
- Datawhale赛事大满贯来了!
- Py之pandas:利用pandas工具输出每行的索引值、及其对应的行数据
- 奔跑吧,OpenStack现场分享:超融合架构如何抹平物理硬件差异?
- Convert Windows 32bit dirver to Windows 64bit
- if是什么c语言,这个C语言是什么(if(1))?
- 深井软岩巷道群支护技术与应用_黑龙江优质右旋锚杆厂家量大从优_双福煤矿支护架...
- 面试专题:Python面试题陷阱,你是否会中招?
- XML与HTML区别
- verycd下载资源
- Logistic模型预测人口增长
- 原生js预览ofd文件
- MIPS32-单周期数据通路设计
- 华为悦盒EC6108V9 、EC6108V9C_1080UI_非高安版_鸿蒙动画_免拆卡刷固件
- 【美味蟹堡王今日营业】论文学习笔记10-02
- C语言对复数模运算的处理
- spring cloud搭建教程
- iOS 开发 解决UICollectionView的多组头部视图样式不一样复用时发生错乱问题
- 三角形的几何公式大全_干货2020高中数学必备公式大全,吃透它们,数学再“捡”20分...
- 2023最新抖音取图小程序源码分享,带会员功能对接支付部署教程