This commit is contained in:
blank 2021-06-07 15:13:32 +08:00
parent 74d5947e9d
commit 346fc42e67
500 changed files with 77303 additions and 1 deletions

27
.gitignore vendored Normal file
View File

@ -0,0 +1,27 @@
#///////////////////////////
# Cocos Creator 3D Project
#///////////////////////////
build/
library/
local/
native
temp/
#//////////////////////////
# NPM
#//////////////////////////
node_modules/
#//////////////////////////
# VSCode
#//////////////////////////
.vscode/
#//////////////////////////
# WebStorm
#//////////////////////////
.idea/
.gradle/
*.iml

288
README.cn.md Normal file
View File

@ -0,0 +1,288 @@
# cx-cocos
**一个基于cocos creator3.1.1的应用App和游戏开发框架**
关键词cocos creator、应用开发、App开发、游戏开发、跨平台、框架
cocos creator是一个开源的游戏开发引擎在游戏开发方面拥有大量开发者。然而在应用App方面却少有人使用cx-cocos的出现填补了cocos creator在应用App开发上的空白。
使用cx-cocos你可以轻松愉快地开发出一个跨平台应用App包括ios、mac、android、web等当然你也可以使用cx-cocos开发游戏这是一个高效简洁的开发框架极大提升开发者的效率。
**本说明文档包括以下内容:**
- cx-cocos主要功能
- cx-cocos结构和原理
- 如何运行demo app
- 如何使用cx-cocos开始一个自己的项目
- 问题和技术支持
## 1. 主要功能
**cx-cocos的主要功能包括以下内容**
- 应用App的核心UI交互
- 页面和组件访问、资源访问、远程服务访问
- 与原生代码的交互
- 真正的启动屏
- 热更新
### 1.1 应用App的核心UI交互
----
cx-cocos在页面的显示与交互细节上与iOS原生App有着相似的体验
包括页面的进入退出与手势、提示弹窗、ScrollView、Loading等待、选择器等等。
cx3-demo是一个demo建议你从它入手了解cx-cocos。
- **屏幕适配:** 通常情况下应用App是宽度适应fitWidth、高度随着屏幕高度自动铺满。cx-cocos提供了一个“最小设计宽/高度”的配置即使在浏览器或Pad上App也能按最佳的方式显示界面——你只需按你的设计尺寸来设计UI。
- **刘海屏适配:** 对于iphoneX等屏幕通过添加cx.safearea脚本可自动调节标题栏、内容层、底部导航栏的高度和位置。
- **界面进入与退出:** 动画进入与退出、手势划动退出、上一页面随动、阴影效果、响应android返回键。
- **对话框:** Alert提示框、Confirm确认框。框架还提供了一种Hint动画文字提示你可以多点击几次试试。
- **选择器:** 框架提供了1栏或多栏的选择器你可以轻松地实现年月日选择、年月选择、文字或对象列表选择。
- **ScrollView** 扩展了下拉刷新、上滑增量添加数据的能力。
- **PageView** 扩展了定时自动下一页、循环播放、点击回调的能力。
- **等待动画:** 可以在页面正中或任意控件内显示Loading动画并且有延时显示能力这在查询数据时非常实用比如0.5秒后还没有返回数据才显示Loading动画。
- **原生视图:** 原生UI在cocos UI中显示并且随着ScrollView滚动或窗体滑动原生UI遮罩能力例如对话弹框、标题栏在原生UI之上显示不被遮挡。
### 1.2 页面和组件访问、资源访问、远程服务访问
----
操作UI组件在应用开发中非常频繁cx-cocos提供了便捷的方式对组件进行访问和操作。
| UI常用方法 | 说明 |
| ---- | ---- |
| cx.sw | 适配后的屏幕宽度 |
| cx.sh | 适配后的屏幕高度 |
| cx.gn(pageOrNode, nodeName) | 获取场景树中的节点 |
| setTouchCallback(page, callback, ...params) | 给Node添加点击事件 |
| cx.hint(content) | 显示提示 |
| cx.alert(content, callback?, labelOK?) | 显示对话窗 |
| cx.confrm(content, callback?, labelOK?, labelCancel?) | 显示确认窗 |
| cx.showLoading(page, parentNode, delayShowSeconds?) | 显示等待动画 |
| cx.removeLoading(parentNode) | 移除等待动画 |
| cx.addPage(parentNode, prefabName, scripts?, callbackOrParams, runAction?) | 添加一个页面 |
| cx.showPage(prefabName, scripts?, callbackOrParams) | 添加一个页面(动画进入) |
| cx.closePage(pageOrSender) | 关闭本页面 |
| | |
**示例代码:**
```typescript
var lblTitle: Node = cx.gn(this, "lblTitle"); //获取场景树中的名称为lblTitle的节点
//给lblTitle添加一个点击事件
lblTitle.setTouchCallback(this, this.myClick);
//你也可以定义回调时的参数:
lblTitle.setTouchCallback(this, this.myClick, 1, "a", {tip:"任意类型和数量的参数"});
myClick(sender, p1, p2, p3)
{
//sender = lblTitle
//p1 = 1
//p2 = "a"
//p3 = {remark:"任意类型和数量的参数"}
}
cx.showPage("ui/pageChild"); //显示ui/pageChild.prefab
cx.hint("cx.hint(content)");
cx.alert("cx.alert(content, callback, labelOk)");
cx.confirm("cx.confirm(content, callback, labelOk, labelCancel)", cx.hint);
cx.showLoading(this);
cx.removeLoading(this);
cx.closePage(this);
//给scrollView添加增量新增数据能力
cx.script.scrollView.initDeltaInsert(this, "view", this.queryData);
//给scrollView添加下拉刷新能力
cx.script.scrollView.initDropRefresh(this, "view", this.refreshData);
//给PageView添加自动循环滚动能力
cx.script.pageView.initAutoScroll(this, "viewBanner", 2, true, this.onBannerClick);
````
| 资源常用方法 | 说明 |
| ---- | ---- |
| cx.setImageFromRes(spriteOrNode, prefab, sizeMode?, callback?) | 给节点设置图片(从resources) |
| cx.setImageFromBundle(spriteOrNode, prefab, sizeMode?, callback?) | 给节点设置图片(从bundle) |
| cx.setImageFromRemote(spriteOrNode, url, localPath?, sizeMode?, callback?) | 给节点设置图片(从远程url存储至本地localPath并优先从localPath加载图片) |
| cx.loadBundleRes(prefab, callback?) | 加载1个或多个prefab |
| | |
| 远程访问常用方法 | 说明 |
| ---- | ---- |
| cx.call(url, callback?, context?) | 调用服务端服务(call方式) |
| cx.post(url, data?, callback?, context?) | 调用服务端服务(post方式) |
| cx.upload(url, filePath, callback?) | 调用服务端服务,上传文件 |
| cx.setCommonHeaders(headers: string[]) | 设置http请求的默认headers |
| cx.loadFile(url, localPath?, callback?) | 从url加载文件存储至本地并优先从本地加载 |
| cx.loadAsset(url: string, callback?) | 从url加载Asset |
| | |
| utils常用方法 | 说明 |
| ---- | ---- |
| cx.utils.xxx | cx.func中定义了常用的工具方法如时间等具体参见cx.d.ts |
| | |
### 1.3 与原生代码的交互
----
cx-cocos提供了一个cxnative原生类通过它可以方便地与原生代码、第三方SDK交互。
与iOS/mac的交互是通过jsb/c++ ———— 避免了苹果审核风险
与android的交互是通过jsb.reflection
* 可参照demo中的SystemIntf编写你自己的原生类
**原生类的定义:**
iOS/mac在jsIntf.cpp中定义你的类名和处理类类继承自cxDefine.h中的NativeIntfClass
android在jsIntf.java中定义你的类名和处理类
- 在JavaScript/TypeScript中调用原生方法
```typescript
cx.native.ins("className").call("functionName", [...params], callback);
````
- 在iOS/mac中调用JS方法
```c++
this->callback(int, string);
````
- 在android中调用JS方法
```java
NativeIntf.callJs("className", int, string);
````
### 1.4 真正的启动屏
----
cocos creator提供了一个定时长的启动画面你无法在首页渲染完成后再移除画面也无法提前移除。并且它只能在加载cc.js之后显示而不是在App真正启动时。
cx-cocos针对iOS/mac和Android提供了原生的启动画面处理你可以在App启动时显示在任意时刻移除。
iOS/mac启动屏实现代码见demo中的AppController.mm
android启动屏实现代码见demo中的CocosActivity.java
```typescript
// ios/Mac: LaunchImage.png
// android: lanuch_image.png
// 移除启动屏如果你在config.ts中配置了自动移除那么不需要执行这句cx会在开始页(startPage)加入场景时自动调用
cx.removeLaunchImage();
````
### 1.5 热更新
----
cx-cocos在执行main.js之前执行热更新。
cx-cocos提供了一个update.js工具用于生成热更新需要的manifest文件执行命令为
$ node update.js -v 1.0
* 在执行之前你需要将update.js中的更新地址替换为你的服务器地址。
****实现原理见demo中的boot.js***
## 2. cx-cocos结构和原理
>**cx-framework目录结构**
- **cocos3-libs:** 这里是从creator构建项目中提取的引擎libs我们把它独立出来所有项目就只需要assets
- **cocos-libcc:** cocos android jar你的android工程需要依赖它
- **cocos-libso:** cocos android so编译生成libcocos.so的工程android需要这个.so
- **cocos3-ios.xcodeproj:** 编译生成libcocos3 iOS.a的工程iOS需要这个.a
- **cocos3-mac.xcodeproj:** 编译生成libcocos3 Mac.a的工程mac需要这个.a
- **cx:** cx-cocos的ts代码你的creator工程需要它请拷贝到你项目中的assets目录或在assets目录中建立链接cx链接到它链接命令ln -s ../../cx-framework3.1/cx cx
- **core:** cx-cocos框架实现类
- **prefab:** cx-cocos内置的预制资源
- **scripts:** cx-cocos内置的组件脚本
- **template:** cx-cocos提供的组件模板在设计页面时可以使用它
- **cx-native:** 负责原生交互你的iOS/mac工程需要它android不需要它已经在libcocos.so中
- **cx.d.ts:** cx-cocos的TypeScript声明文件
>**demo的目录结构**
- **project:** 原生工程都在这里了并非creator构建生成的工程
- **assets: 注意,** 它来源于cocos构建发布你可以创建iOS、mac、android任意一种构建将生成的assets拷贝到这里建议你在这里建立一个assets链接链接到你构建生成的assets目录这样在每次重新构建后就不需再拷贝assets链接命令ln -s 路径 assets
- **boot:** 启动js和热更新manifest文件
- **cxdemo.android:** demo android studio工程
- **cxdemo.ios:** demo iOS/mac工程
- **statics:** 一些仅供原生使用的静态资源
- **update.js:** 生成热更新文件的脚本
- **其他目录:** cocos creator生成的目录
>**cx-cocos设计结构**
- 在ts层面cx-cocos包括
- cx: 常用变量、常用方法、UI方法
- cx.native: 与原生交互相关
- cx.picker: 选择器相关
- cx.res: 资源处理相关
- cx.script: 组件扩展功能脚本例如为ScrollView扩展下拉刷新能力
- cx.serv: 服务交互相关
- cx.sys: 系统环境和配置相关
- 在原生层面cx-cocos包括
- cxnative: 原生JSB接口类对应于cx.native的实现
- sysIntf: 内置的系统原生类,用于获取包名、环境等
- maskIntf内置的遮罩原生类用于给原生UI添加遮罩
>**cx-cocos运行机制**
- app启动首先加载boot.js处理热更新然后加载assets的main.js、cc.js等
- app加载cc.js后加载项目jscx作为项目的一部分被加载cx作为全局对象存储于window.cx
- 在你的组件脚本中你不需要import cx-cocos的任何脚本因为它是全局的直接使用就可以
- **整个app只有一个场景所有页面都是预制资源**
- 在主场景中有一个根节点RootNode负责滑动事件、android返回键的处理
- 你在config.ts中定义的startPage在主场景启动时被addPage到RootNode中
- 其他页面你可以通过addPage或showPage方法显示默认会运行与页面同名的脚本可在该方法的参数中指定加载的脚本
- 通过addPage或showPage方法显示的页面它们的parent都是RootNode
- 在addPage或showPage方法回调参数中你可以向子页面传递参数或控制子页面
- 如果页面定义了onChildPageClosed方法那么子页面在关闭时会触发这个方法
- 你可以自定义页面进入和退出时的动画
- cx-cocos定义和实现了通用的原生交互方式
- 通过cx.native.ins("名称").call("方法", [...参数], 回调方法)调用原生方法
- 分别在iOS的jsIntf-ios.mm、android的jsIntf.java定义你自己的“名称”处理类
## 3 如何运行demo app
1. 安装cocos creator 3.1.1
2. 确保cx-framework3.1和cx3-demo在同一目录下
3. iOS/mac环境在xcode中打开cx3-demo/project/cxdemo.ios/cx3-demo.xcodeproj运行
4. android环境在android studio中打开cx3-demo/project/cxdemo.android运行
```typescript
* 在iOS/mac、android上编译或运行demo你可以不需要打开cocos creator
* android的video遮罩暂未完成技术困难如果你有好的实现方式请告诉我
```
## 4 如何使用cx-cocos开始一个自己的项目
1. 使用cocos creator3.1.1创建一个项目与cx-framework3.1在同一目录下
```typescript
* 建议你使用cocos creator3.1.1 (2021.06.01发布)
* 如果你使用的是creator3.1.0可能需要重新编译cx-framework3.1中.so和.a
重新编译前可使用vscode编辑器查找3.1.1全部替换成3.1.0
* 如果你使用的是creator3.0.x那么cx-framework3.1中的libs工程不适用你需要从creator构建生成的项目中提取cocos2d支持3.0.x的框架我并未上传至git如有需要请联系我
```
2. 拷贝cx3-demo中的tsconfig.json文件和project目录到你的项目目录下
```typescript
* 拷贝tsconfig.json的目的仅仅是因为——它定义了cx.d.ts的引用你也可以不拷贝而自行定义
"compilerOptions": {"types": ["../cx-framework3.1/cx"]}
```
3. 根据自己的需要修改project目录内的工程的内容
4. creator项目设置
- 项目数据
- 设计宽度750
- 设计高度1334
- 适配屏幕宽度:是
- 适配屏幕高度:否
- 功能裁剪:
- 去掉3D
- 去掉2D中的2D物理系统、2D相交检测算法、2D粒子系统、Tiled地图、Spine动画
5. creator构建发布设置
- 发布路径不要填写成project那会弄乱你的project目录建议设置为native或build
- MD5缓存不要勾选
- 替换插屏:**勾选并且最小显示时间设置为0**
- 屏幕方向(Orientation)只勾选portrait
## 5 问题和技术支持

291
README.md
View File

@ -1,2 +1,291 @@
todo: Waiting for English translation
# cx-cocos
App development framework based on cocos creator3.1.0
**一个基于cocos creator3.1.1的应用App和游戏开发框架**
关键词cocos creator、应用开发、App开发、游戏开发、跨平台、框架
cocos creator是一个开源的游戏开发引擎在游戏开发方面拥有大量开发者。然而在应用App方面却少有人使用cx-cocos的出现填补了cocos creator在应用App开发上的空白。
使用cx-cocos你可以轻松愉快地开发出一个跨平台应用App包括ios、mac、android、web等当然你也可以使用cx-cocos开发游戏这是一个高效简洁的开发框架极大提升开发者的效率。
**本说明文档包括以下内容:**
- cx-cocos主要功能
- cx-cocos结构和原理
- 如何运行demo app
- 如何使用cx-cocos开始一个自己的项目
- 问题和技术支持
## 1. 主要功能
**cx-cocos的主要功能包括以下内容**
- 应用App的核心UI交互
- 页面和组件访问、资源访问、远程服务访问
- 与原生代码的交互
- 真正的启动屏
- 热更新
### 1.1 应用App的核心UI交互
----
cx-cocos在页面的显示与交互细节上与iOS原生App有着相似的体验
包括页面的进入退出与手势、提示弹窗、ScrollView、Loading等待、选择器等等。
cx3-demo是一个demo建议你从它入手了解cx-cocos。
- **屏幕适配:** 通常情况下应用App是宽度适应fitWidth、高度随着屏幕高度自动铺满。cx-cocos提供了一个“最小设计宽/高度”的配置即使在浏览器或Pad上App也能按最佳的方式显示界面——你只需按你的设计尺寸来设计UI。
- **刘海屏适配:** 对于iphoneX等屏幕通过添加cx.safearea脚本可自动调节标题栏、内容层、底部导航栏的高度和位置。
- **界面进入与退出:** 动画进入与退出、手势划动退出、上一页面随动、阴影效果、响应android返回键。
- **对话框:** Alert提示框、Confirm确认框。框架还提供了一种Hint动画文字提示你可以多点击几次试试。
- **选择器:** 框架提供了1栏或多栏的选择器你可以轻松地实现年月日选择、年月选择、文字或对象列表选择。
- **ScrollView** 扩展了下拉刷新、上滑增量添加数据的能力。
- **PageView** 扩展了定时自动下一页、循环播放、点击回调的能力。
- **等待动画:** 可以在页面正中或任意控件内显示Loading动画并且有延时显示能力这在查询数据时非常实用比如0.5秒后还没有返回数据才显示Loading动画。
- **原生视图:** 原生UI在cocos UI中显示并且随着ScrollView滚动或窗体滑动原生UI遮罩能力例如对话弹框、标题栏在原生UI之上显示不被遮挡。
### 1.2 页面和组件访问、资源访问、远程服务访问
----
操作UI组件在应用开发中非常频繁cx-cocos提供了便捷的方式对组件进行访问和操作。
| UI常用方法 | 说明 |
| ---- | ---- |
| cx.sw | 适配后的屏幕宽度 |
| cx.sh | 适配后的屏幕高度 |
| cx.gn(pageOrNode, nodeName) | 获取场景树中的节点 |
| setTouchCallback(page, callback, ...params) | 给Node添加点击事件 |
| cx.hint(content) | 显示提示 |
| cx.alert(content, callback?, labelOK?) | 显示对话窗 |
| cx.confrm(content, callback?, labelOK?, labelCancel?) | 显示确认窗 |
| cx.showLoading(page, parentNode, delayShowSeconds?) | 显示等待动画 |
| cx.removeLoading(parentNode) | 移除等待动画 |
| cx.addPage(parentNode, prefabName, scripts?, callbackOrParams, runAction?) | 添加一个页面 |
| cx.showPage(prefabName, scripts?, callbackOrParams) | 添加一个页面(动画进入) |
| cx.closePage(pageOrSender) | 关闭本页面 |
| | |
**示例代码:**
```typescript
var lblTitle: Node = cx.gn(this, "lblTitle"); //获取场景树中的名称为lblTitle的节点
//给lblTitle添加一个点击事件
lblTitle.setTouchCallback(this, this.myClick);
//你也可以定义回调时的参数:
lblTitle.setTouchCallback(this, this.myClick, 1, "a", {tip:"任意类型和数量的参数"});
myClick(sender, p1, p2, p3)
{
//sender = lblTitle
//p1 = 1
//p2 = "a"
//p3 = {remark:"任意类型和数量的参数"}
}
cx.showPage("ui/pageChild"); //显示ui/pageChild.prefab
cx.hint("cx.hint(content)");
cx.alert("cx.alert(content, callback, labelOk)");
cx.confirm("cx.confirm(content, callback, labelOk, labelCancel)", cx.hint);
cx.showLoading(this);
cx.removeLoading(this);
cx.closePage(this);
//给scrollView添加增量新增数据能力
cx.script.scrollView.initDeltaInsert(this, "view", this.queryData);
//给scrollView添加下拉刷新能力
cx.script.scrollView.initDropRefresh(this, "view", this.refreshData);
//给PageView添加自动循环滚动能力
cx.script.pageView.initAutoScroll(this, "viewBanner", 2, true, this.onBannerClick);
````
| 资源常用方法 | 说明 |
| ---- | ---- |
| cx.setImageFromRes(spriteOrNode, prefab, sizeMode?, callback?) | 给节点设置图片(从resources) |
| cx.setImageFromBundle(spriteOrNode, prefab, sizeMode?, callback?) | 给节点设置图片(从bundle) |
| cx.setImageFromRemote(spriteOrNode, url, localPath?, sizeMode?, callback?) | 给节点设置图片(从远程url存储至本地localPath并优先从localPath加载图片) |
| cx.loadBundleRes(prefab, callback?) | 加载1个或多个prefab |
| | |
| 远程访问常用方法 | 说明 |
| ---- | ---- |
| cx.call(url, callback?, context?) | 调用服务端服务(call方式) |
| cx.post(url, data?, callback?, context?) | 调用服务端服务(post方式) |
| cx.upload(url, filePath, callback?) | 调用服务端服务,上传文件 |
| cx.setCommonHeaders(headers: string[]) | 设置http请求的默认headers |
| cx.loadFile(url, localPath?, callback?) | 从url加载文件存储至本地并优先从本地加载 |
| cx.loadAsset(url: string, callback?) | 从url加载Asset |
| | |
| utils常用方法 | 说明 |
| ---- | ---- |
| cx.utils.xxx | cx.func中定义了常用的工具方法如时间等具体参见cx.d.ts |
| | |
### 1.3 与原生代码的交互
----
cx-cocos提供了一个cxnative原生类通过它可以方便地与原生代码、第三方SDK交互。
与iOS/mac的交互是通过jsb/c++ ———— 避免了苹果审核风险
与android的交互是通过jsb.reflection
* 可参照demo中的SystemIntf编写你自己的原生类
**原生类的定义:**
iOS/mac在jsIntf.cpp中定义你的类名和处理类类继承自cxDefine.h中的NativeIntfClass
android在jsIntf.java中定义你的类名和处理类
- 在JavaScript/TypeScript中调用原生方法
```typescript
cx.native.ins("className").call("functionName", [...params], callback);
````
- 在iOS/mac中调用JS方法
```c++
this->callback(int, string);
````
- 在android中调用JS方法
```java
NativeIntf.callJs("className", int, string);
````
### 1.4 真正的启动屏
----
cocos creator提供了一个定时长的启动画面你无法在首页渲染完成后再移除画面也无法提前移除。并且它只能在加载cc.js之后显示而不是在App真正启动时。
cx-cocos针对iOS/mac和Android提供了原生的启动画面处理你可以在App启动时显示在任意时刻移除。
iOS/mac启动屏实现代码见demo中的AppController.mm
android启动屏实现代码见demo中的CocosActivity.java
```typescript
// ios/Mac: LaunchImage.png
// android: lanuch_image.png
// 移除启动屏如果你在config.ts中配置了自动移除那么不需要执行这句cx会在开始页(startPage)加入场景时自动调用
cx.removeLaunchImage();
````
### 1.5 热更新
----
cx-cocos在执行main.js之前执行热更新。
cx-cocos提供了一个update.js工具用于生成热更新需要的manifest文件执行命令为
$ node update.js -v 1.0
* 在执行之前你需要将update.js中的更新地址替换为你的服务器地址。
****实现原理见demo中的boot.js***
## 2. cx-cocos结构和原理
>**cx-framework目录结构**
- **cocos3-libs:** 这里是从creator构建项目中提取的引擎libs我们把它独立出来所有项目就只需要assets
- **cocos-libcc:** cocos android jar你的android工程需要依赖它
- **cocos-libso:** cocos android so编译生成libcocos.so的工程android需要这个.so
- **cocos3-ios.xcodeproj:** 编译生成libcocos3 iOS.a的工程iOS需要这个.a
- **cocos3-mac.xcodeproj:** 编译生成libcocos3 Mac.a的工程mac需要这个.a
- **cx:** cx-cocos的ts代码你的creator工程需要它请拷贝到你项目中的assets目录或在assets目录中建立链接cx链接到它链接命令ln -s ../../cx-framework3.1/cx cx
- **core:** cx-cocos框架实现类
- **prefab:** cx-cocos内置的预制资源
- **scripts:** cx-cocos内置的组件脚本
- **template:** cx-cocos提供的组件模板在设计页面时可以使用它
- **cx-native:** 负责原生交互你的iOS/mac工程需要它android不需要它已经在libcocos.so中
- **cx.d.ts:** cx-cocos的TypeScript声明文件
>**demo的目录结构**
- **project:** 原生工程都在这里了并非creator构建生成的工程
- **assets: 注意,** 它来源于cocos构建发布你可以创建iOS、mac、android任意一种构建将生成的assets拷贝到这里建议你在这里建立一个assets链接链接到你构建生成的assets目录这样在每次重新构建后就不需再拷贝assets链接命令ln -s 路径 assets
- **boot:** 启动js和热更新manifest文件
- **cxdemo.android:** demo android studio工程
- **cxdemo.ios:** demo iOS/mac工程
- **statics:** 一些仅供原生使用的静态资源
- **update.js:** 生成热更新文件的脚本
- **其他目录:** cocos creator生成的目录
>**cx-cocos设计结构**
- 在ts层面cx-cocos包括
- cx: 常用变量、常用方法、UI方法
- cx.native: 与原生交互相关
- cx.picker: 选择器相关
- cx.res: 资源处理相关
- cx.script: 组件扩展功能脚本例如为ScrollView扩展下拉刷新能力
- cx.serv: 服务交互相关
- cx.sys: 系统环境和配置相关
- 在原生层面cx-cocos包括
- cxnative: 原生JSB接口类对应于cx.native的实现
- sysIntf: 内置的系统原生类,用于获取包名、环境等
- maskIntf内置的遮罩原生类用于给原生UI添加遮罩
>**cx-cocos运行机制**
- app启动首先加载boot.js处理热更新然后加载assets的main.js、cc.js等
- app加载cc.js后加载项目jscx作为项目的一部分被加载cx作为全局对象存储于window.cx
- 在你的组件脚本中你不需要import cx-cocos的任何脚本因为它是全局的直接使用就可以
- **整个app只有一个场景所有页面都是预制资源**
- 在主场景中有一个根节点RootNode负责滑动事件、android返回键的处理
- 你在config.ts中定义的startPage在主场景启动时被addPage到RootNode中
- 其他页面你可以通过addPage或showPage方法显示默认会运行与页面同名的脚本可在该方法的参数中指定加载的脚本
- 通过addPage或showPage方法显示的页面它们的parent都是RootNode
- 在addPage或showPage方法回调参数中你可以向子页面传递参数或控制子页面
- 如果页面定义了onChildPageClosed方法那么子页面在关闭时会触发这个方法
- 你可以自定义页面进入和退出时的动画
- cx-cocos定义和实现了通用的原生交互方式
- 通过cx.native.ins("名称").call("方法", [...参数], 回调方法)调用原生方法
- 分别在iOS的jsIntf-ios.mm、android的jsIntf.java定义你自己的“名称”处理类
## 3 如何运行demo app
1. 安装cocos creator 3.1.1
2. 确保cx-framework3.1和cx3-demo在同一目录下
3. iOS/mac环境在xcode中打开cx3-demo/project/cxdemo.ios/cx3-demo.xcodeproj运行
4. android环境在android studio中打开cx3-demo/project/cxdemo.android运行
```typescript
* 在iOS/mac、android上编译或运行demo你可以不需要打开cocos creator
* android的video遮罩暂未完成技术困难如果你有好的实现方式请告诉我
```
## 4 如何使用cx-cocos开始一个自己的项目
1. 使用cocos creator3.1.1创建一个项目与cx-framework3.1在同一目录下
```typescript
* 建议你使用cocos creator3.1.1 (2021.06.01发布)
* 如果你使用的是creator3.1.0可能需要重新编译cx-framework3.1中.so和.a
重新编译前可使用vscode编辑器查找3.1.1全部替换成3.1.0
* 如果你使用的是creator3.0.x那么cx-framework3.1中的libs工程不适用你需要从creator构建生成的项目中提取cocos2d支持3.0.x的框架我并未上传至git如有需要请联系我
```
2. 拷贝cx3-demo中的tsconfig.json文件和project目录到你的项目目录下
```typescript
* 拷贝tsconfig.json的目的仅仅是因为——它定义了cx.d.ts的引用你也可以不拷贝而自行定义
"compilerOptions": {"types": ["../cx-framework3.1/cx"]}
```
3. 根据自己的需要修改project目录内的工程的内容
4. creator项目设置
- 项目数据
- 设计宽度750
- 设计高度1334
- 适配屏幕宽度:是
- 适配屏幕高度:否
- 功能裁剪:
- 去掉3D
- 去掉2D中的2D物理系统、2D相交检测算法、2D粒子系统、Tiled地图、Spine动画
5. creator构建发布设置
- 发布路径不要填写成project那会弄乱你的project目录建议设置为native或build
- MD5缓存不要勾选
- 替换插屏:**勾选并且最小显示时间设置为0**
- 屏幕方向(Orientation)只勾选portrait
## 5 问题和技术支持

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:/Users/blank/ccapp3/cx-framework3.1/cocos3-libs/cocos3-ios.xcodeproj">
</FileRef>
</Workspace>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BuildSystemType</key>
<string>Latest</string>
<key>DisableBuildSystemDeprecationWarning</key>
<true/>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BuildLocationStyle</key>
<string>UseAppPreferences</string>
<key>CustomBuildIntermediatesPath</key>
<string>cocos3.1-libs/Intermediates.noindex</string>
<key>CustomBuildLocationType</key>
<string>RelativeToDerivedData</string>
<key>CustomBuildProductsPath</key>
<string>cocos3.1-libs/Products</string>
<key>DerivedDataLocationStyle</key>
<string>Default</string>
<key>IssueFilterStyle</key>
<string>ShowActiveSchemeOnly</string>
<key>LiveSourceIssuesEnabled</key>
<true/>
<key>ShowSharedSchemesAutomaticallyEnabled</key>
<true/>
</dict>
</plist>

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1240"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "46916E52264CD4B0000C7B53"
BuildableName = "libcocos3 iOS.a"
BlueprintName = "cocos3 iOS"
ReferencedContainer = "container:cocos3-iOS.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "46916E52264CD4B0000C7B53"
BuildableName = "libcocos3 iOS.a"
BlueprintName = "cocos3 iOS"
ReferencedContainer = "container:cocos3-iOS.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>cocos3 iOS.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>1</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
<dict>
<key>46916BBC264CCEF4000C7B53</key>
<dict>
<key>primary</key>
<true/>
</dict>
<key>46916D11264CD362000C7B53</key>
<dict>
<key>primary</key>
<true/>
</dict>
<key>46916E52264CD4B0000C7B53</key>
<dict>
<key>primary</key>
<true/>
</dict>
<key>C0436D9181584B92A7E37006</key>
<dict>
<key>primary</key>
<true/>
</dict>
</dict>
</dict>
</plist>

View File

@ -0,0 +1,4 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.cocos.lib">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
</manifest>

View File

@ -0,0 +1,33 @@
apply plugin: 'com.android.library'
android {
compileSdkVersion PROP_COMPILE_SDK_VERSION.toInteger()
defaultConfig {
minSdkVersion PROP_MIN_SDK_VERSION
targetSdkVersion PROP_TARGET_SDK_VERSION
versionCode 1
versionName "1.0"
}
sourceSets.main {
aidl.srcDir "../java/src"
java.srcDir "../java/src"
manifest.srcFile "AndroidManifest.xml"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: '../java/libs')
}

View File

@ -0,0 +1,17 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in E:\developSoftware\Android\SDK/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- 填充颜色 -->
<solid android:color="@color/navy"></solid>
<!-- 线的宽度,颜色 -->
<stroke android:width="0dp" android:color="@color/navy"></stroke>
<!-- 矩形的圆角半径 -->
<corners android:radius="20dp" />
</shape>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- 填充颜色 -->
<solid android:color="#00000000"></solid>
<!-- 线的宽度,颜色 -->
<stroke android:width="1dp" android:color="@color/navy"></stroke>
<!-- 矩形的圆角半径 -->
<corners android:radius="20dp" />
</shape>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<size android:width="4dp"
android:height="4dp" />
<solid android:color="@android:color/transparent" />
</shape>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- 填充颜色 -->
<solid android:color="#33fff000"></solid>
<!-- 线的宽度,颜色 -->
<stroke android:width="1dp" android:color="@color/navy"></stroke>
<!-- 矩形的圆角半径 -->
<corners android:radius="6dp" />
<padding android:left="5dp" android:right="5dp" />
</shape>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- 填充颜色 -->
<solid android:color="@color/white_e0"></solid>
<!-- 线的宽度,颜色 -->
<stroke android:width="1dp" android:color="@color/gray9"></stroke>
<!-- 矩形的圆角半径 -->
<corners android:radius="6dp" />
<padding android:left="5dp" android:right="5dp" />
</shape>

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- 填充颜色 -->
<solid android:color="@color/white_f7"></solid>
<!-- 线的宽度,颜色 -->
<stroke android:width="1dp" android:color="@color/gray9"></stroke>
<!-- 矩形的圆角半径 -->
<corners android:radius="6dp" />
<padding android:left="5dp" android:right="5dp" />
</shape>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="@drawable/edit_focus"/>
<item android:state_focused="true" android:drawable="@drawable/edit_focus" />
<item android:state_pressed="true" android:drawable="@drawable/edit_focus"/>
<item android:drawable="@drawable/edit_normal"/>
</selector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 B

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--EditBox Confirm Button Name-->
<string name="done" translatable="false">完成</string>
<string name="next" translatable="false">下一个</string>
<string name="search" translatable="false">搜索</string>
<string name="go" translatable="false">前往</string>
<string name="send" translatable="false">发送</string>
</resources>

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="none">#00000000</color>
<color name="white">#ffffff</color>
<color name="white_f7">#f7f7f7</color>
<color name="white_f0">#f0f0f0</color>
<color name="white_d0">#d0d0d0</color>
<color name="white_e0">#e0e0e0</color>
<color name="black">#000000</color>
<color name="gray3">#333333</color>
<color name="gray4">#444444</color>
<color name="gray7">#777777</color>
<color name="gray9">#999999</color>
<color name="red">#ff0000</color>
<color name="red1">#e51300</color>
<color name="red2">#ff6900</color>
<color name="blue">#0000ff</color>
<color name="blue1">#009ecf</color>
<color name="blue2">#41a9b6</color>
<color name="navy">#333b73</color>
<color name="navy1">#1d2241</color>
<color name="green">#00ff00</color>
<color name="yellow">#ffff00</color>
<color name="gold">#fff000</color>
</resources>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="title_size">16sp</dimen>
</resources>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--EditBox Confirm Button Title-->
<string name="done" translatable="false">Done</string>
<string name="next" translatable="false">Next</string>
<string name="search" translatable="false">Search</string>
<string name="go" translatable="false">Go</string>
<string name="send" translatable="false">Send</string>
</resources>

View File

@ -0,0 +1,18 @@
<resources>
<style name="notAnimation">
<item name="android:activityOpenEnterAnimation">@null</item>
<item name="android:activityOpenExitAnimation">@null</item>
<item name="android:activityCloseEnterAnimation">@null</item>
<item name="android:activityCloseExitAnimation">@null</item>
<item name="android:taskOpenEnterAnimation">@null</item>
<item name="android:taskOpenExitAnimation">@null</item>
<item name="android:taskCloseEnterAnimation">@null</item>
<item name="android:taskCloseExitAnimation">@null</item>
<item name="android:taskToFrontEnterAnimation">@null</item>
<item name="android:taskToFrontExitAnimation">@null</item>
<item name="android:taskToBackEnterAnimation">@null</item>
<item name="android:taskToBackExitAnimation">@null</item>
</style>
</resources>

View File

@ -0,0 +1,509 @@
/****************************************************************************
* Copyright (c) 2018 Xiamen Yaji Software Co., Ltd.
*
* http://www.cocos.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
****************************************************************************/
package com.cocos.lib;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Typeface;
import android.os.Build;
import android.text.TextPaint;
import android.util.Log;
import java.lang.ref.WeakReference;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.HashMap;
public class CanvasRenderingContext2DImpl {
private static final String TAG = "CanvasContext2D";
private static final int TEXT_ALIGN_LEFT = 0;
private static final int TEXT_ALIGN_CENTER = 1;
private static final int TEXT_ALIGN_RIGHT = 2;
private static final int TEXT_BASELINE_TOP = 0;
private static final int TEXT_BASELINE_MIDDLE = 1;
private static final int TEXT_BASELINE_BOTTOM = 2;
private static final int TEXT_BASELINE_ALPHABETIC = 3;
private static WeakReference<Context> sContext;
private TextPaint mTextPaint;
private Paint mLinePaint;
private Path mLinePath;
private Canvas mCanvas = new Canvas();
private Bitmap mBitmap;
private int mTextAlign = TEXT_ALIGN_LEFT;
private int mTextBaseline = TEXT_BASELINE_BOTTOM;
private int mFillStyleR = 0;
private int mFillStyleG = 0;
private int mFillStyleB = 0;
private int mFillStyleA = 255;
private int mStrokeStyleR = 0;
private int mStrokeStyleG = 0;
private int mStrokeStyleB = 0;
private int mStrokeStyleA = 255;
private String mFontName = "Arial";
private float mFontSize = 40.0f;
private float mLineWidth = 0.0f;
private static float _sApproximatingOblique = -0.25f;//please check paint api documentation
private boolean mIsBoldFont = false;
private boolean mIsItalicFont = false;
private boolean mIsObliqueFont = false;
private boolean mIsSmallCapsFontVariant = false;
private String mLineCap = "butt";
private String mLineJoin = "miter";
private class Size {
Size(float w, float h) {
this.width = w;
this.height = h;
}
Size() {
this.width = 0;
this.height = 0;
}
public float width;
public float height;
}
private class Point {
Point(float x, float y) {
this.x = x;
this.y = y;
}
Point() {
this.x = this.y = 0.0f;
}
Point(Point pt) {
this.x = pt.x;
this.y = pt.y;
}
void set(float x, float y) {
this.x = x;
this.y = y;
}
public float x;
public float y;
}
static void init(Context context) {
sContext = new WeakReference<>(context);
}
static void destroy() {
sContext = null;
}
private static HashMap<String, Typeface> sTypefaceCache = new HashMap<>();
// url is a full path started with '@assets/'
private static void loadTypeface(String familyName, String url) {
if (!sTypefaceCache.containsKey(familyName)) {
try {
Typeface typeface = null;
if (url.startsWith("/")) {
typeface = Typeface.createFromFile(url);
} else if (sContext.get() != null) {
final String prefix = "@assets/";
if (url.startsWith(prefix)) {
url = url.substring(prefix.length());
}
typeface = Typeface.createFromAsset(sContext.get().getAssets(), url);
}
if (typeface != null) {
sTypefaceCache.put(familyName, typeface);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
// REFINE:: native should clear font cache before exiting game.
private static void clearTypefaceCache() {
sTypefaceCache.clear();
}
private static TextPaint newPaint(String fontName, int fontSize, boolean enableBold, boolean enableItalic, boolean obliqueFont, boolean smallCapsFontVariant) {
TextPaint paint = new TextPaint();
paint.setTextSize(fontSize);
paint.setAntiAlias(true);
paint.setSubpixelText(true);
String key = fontName;
if (enableBold) {
key += "-Bold";
paint.setFakeBoldText(true);
}
if (enableItalic) {
key += "-Italic";
}
Typeface typeFace;
if (sTypefaceCache.containsKey(key)) {
typeFace = sTypefaceCache.get(key);
} else {
int style = Typeface.NORMAL;
if (enableBold && enableItalic) {
style = Typeface.BOLD_ITALIC;
} else if (enableBold) {
style = Typeface.BOLD;
} else if (enableItalic) {
style = Typeface.ITALIC;
}
typeFace = Typeface.create(fontName, style);
}
paint.setTypeface(typeFace);
if(obliqueFont) {
paint.setTextSkewX(_sApproximatingOblique);
}
if(smallCapsFontVariant && Build.VERSION.SDK_INT >= 21) {
CocosReflectionHelper.<Void>invokeInstanceMethod(paint,
"setFontFeatureSettings",
new Class[]{String.class},
new Object[]{"smcp"});
}
return paint;
}
private CanvasRenderingContext2DImpl() {
// Log.d(TAG, "constructor");
}
private void recreateBuffer(float w, float h) {
// Log.d(TAG, "recreateBuffer:" + w + ", " + h);
if (mBitmap != null) {
mBitmap.recycle();
}
mBitmap = Bitmap.createBitmap((int)Math.ceil(w), (int)Math.ceil(h), Bitmap.Config.ARGB_8888);
// FIXME: in MIX 2S, its API level is 28, but can not find invokeInstanceMethod. It seems
// devices may not obey the specification, so comment the codes.
// if (Build.VERSION.SDK_INT >= 19) {
// CocosReflectionHelper.<Void>invokeInstanceMethod(mBitmap,
// "setPremultiplied",
// new Class[]{Boolean.class},
// new Object[]{Boolean.FALSE});
// }
mCanvas.setBitmap(mBitmap);
}
private void beginPath() {
if (mLinePath == null) {
mLinePath = new Path();
}
mLinePath.reset();
}
private void closePath() {
mLinePath.close();
}
private void moveTo(float x, float y) {
mLinePath.moveTo(x, y);
}
private void lineTo(float x, float y) {
mLinePath.lineTo(x, y);
}
private void stroke() {
if (mLinePaint == null) {
mLinePaint = new Paint();
mLinePaint.setAntiAlias(true);
}
if(mLinePath == null) {
mLinePath = new Path();
}
mLinePaint.setARGB(mStrokeStyleA, mStrokeStyleR, mStrokeStyleG, mStrokeStyleB);
mLinePaint.setStyle(Paint.Style.STROKE);
mLinePaint.setStrokeWidth(mLineWidth);
this.setStrokeCap(mLinePaint);
this.setStrokeJoin(mLinePaint);
mCanvas.drawPath(mLinePath, mLinePaint);
}
private void setStrokeCap(Paint paint) {
switch (mLineCap) {
case "butt":
paint.setStrokeCap(Paint.Cap.BUTT);
break;
case "round":
paint.setStrokeCap(Paint.Cap.ROUND);
break;
case "square":
paint.setStrokeCap(Paint.Cap.SQUARE);
break;
}
}
private void setStrokeJoin(Paint paint) {
switch (mLineJoin) {
case "bevel":
paint.setStrokeJoin(Paint.Join.BEVEL);
break;
case "round":
paint.setStrokeJoin(Paint.Join.ROUND);
break;
case "miter":
paint.setStrokeJoin(Paint.Join.MITER);
break;
}
}
private void fill() {
if (mLinePaint == null) {
mLinePaint = new Paint();
}
if(mLinePath == null) {
mLinePath = new Path();
}
mLinePaint.setARGB(mFillStyleA, mFillStyleR, mFillStyleG, mFillStyleB);
mLinePaint.setStyle(Paint.Style.FILL);
mCanvas.drawPath(mLinePath, mLinePaint);
// workaround: draw a hairline to cover the border
mLinePaint.setStrokeWidth(0);
this.setStrokeCap(mLinePaint);
this.setStrokeJoin(mLinePaint);
mLinePaint.setStyle(Paint.Style.STROKE);
mCanvas.drawPath(mLinePath, mLinePaint);
mLinePaint.setStrokeWidth(mLineWidth);
}
private void setLineCap(String lineCap) {
mLineCap = lineCap;
}
private void setLineJoin(String lineJoin) {
mLineJoin = lineJoin;
}
private void saveContext() {
mCanvas.save();
}
private void restoreContext() {
// If there is no saved state, this method should do nothing.
if (mCanvas.getSaveCount() > 1){
mCanvas.restore();
}
}
private void rect(float x, float y, float w, float h) {
// Log.d(TAG, "this: " + this + ", rect: " + x + ", " + y + ", " + w + ", " + h);
beginPath();
moveTo(x, y);
lineTo(x, y + h);
lineTo(x + w, y + h);
lineTo(x + w, y);
closePath();
}
private void clearRect(float x, float y, float w, float h) {
// Log.d(TAG, "this: " + this + ", clearRect: " + x + ", " + y + ", " + w + ", " + h);
int clearSize = (int)(w * h);
int[] clearColor = new int[clearSize];
for (int i = 0; i < clearSize; ++i) {
clearColor[i] = Color.TRANSPARENT;
}
mBitmap.setPixels(clearColor, 0, (int) w, (int) x, (int) y, (int) w, (int) h);
}
private void createTextPaintIfNeeded() {
if (mTextPaint == null) {
mTextPaint = newPaint(mFontName, (int) mFontSize, mIsBoldFont, mIsItalicFont, mIsObliqueFont, mIsSmallCapsFontVariant);
}
}
private void fillRect(float x, float y, float w, float h) {
// Log.d(TAG, "fillRect: " + x + ", " + y + ", " + ", " + w + ", " + h);
int pixelValue = (mFillStyleA & 0xff) << 24 | (mFillStyleR & 0xff) << 16 | (mFillStyleG & 0xff) << 8 | (mFillStyleB & 0xff);
int fillSize = (int)(w * h);
int[] fillColors = new int[fillSize];
for (int i = 0; i < fillSize; ++i) {
fillColors[i] = pixelValue;
}
mBitmap.setPixels(fillColors, 0, (int) w, (int)x, (int)y, (int)w, (int)h);
}
private void scaleX(TextPaint textPaint, String text, float maxWidth) {
if(maxWidth < Float.MIN_VALUE) return;
float measureWidth = this.measureText(text);
if((measureWidth - maxWidth) < Float.MIN_VALUE) return;
float scaleX = maxWidth/measureWidth;
textPaint.setTextScaleX(scaleX);
}
private void fillText(String text, float x, float y, float maxWidth) {
// Log.d(TAG, "this: " + this + ", fillText: " + text + ", " + x + ", " + y + ", " + ", " + maxWidth);
createTextPaintIfNeeded();
mTextPaint.setARGB(mFillStyleA, mFillStyleR, mFillStyleG, mFillStyleB);
mTextPaint.setStyle(Paint.Style.FILL);
scaleX(mTextPaint, text, maxWidth);
Point pt = convertDrawPoint(new Point(x, y), text);
mCanvas.drawText(text, pt.x, pt.y, mTextPaint);
}
private void strokeText(String text, float x, float y, float maxWidth) {
// Log.d(TAG, "strokeText: " + text + ", " + x + ", " + y + ", " + ", " + maxWidth);
createTextPaintIfNeeded();
mTextPaint.setARGB(mStrokeStyleA, mStrokeStyleR, mStrokeStyleG, mStrokeStyleB);
mTextPaint.setStyle(Paint.Style.STROKE);
mTextPaint.setStrokeWidth(mLineWidth);
scaleX(mTextPaint, text, maxWidth);
Point pt = convertDrawPoint(new Point(x, y), text);
mCanvas.drawText(text, pt.x, pt.y, mTextPaint);
}
private float measureText(String text) {
createTextPaintIfNeeded();
float ret = mTextPaint.measureText(text);
// Log.d(TAG, "measureText: " + text + ", return: " + ret);
return ret;
}
private void updateFont(String fontName, float fontSize, boolean bold, boolean italic, boolean oblique, boolean smallCaps) {
// Log.d(TAG, "updateFont: " + fontName + ", " + fontSize);
mFontName = fontName;
mFontSize = fontSize;
mIsBoldFont = bold;
mIsItalicFont = italic;
mIsObliqueFont = oblique;
mIsSmallCapsFontVariant = smallCaps;
mTextPaint = null; // Reset paint to re-create paint object in createTextPaintIfNeeded
}
private void setTextAlign(int align) {
// Log.d(TAG, "setTextAlign: " + align);
mTextAlign = align;
}
private void setTextBaseline(int baseline) {
// Log.d(TAG, "setTextBaseline: " + baseline);
mTextBaseline = baseline;
}
private void setFillStyle(float r, float g, float b, float a) {
// Log.d(TAG, "setFillStyle: " + r + ", " + g + ", " + b + ", " + a);
mFillStyleR = (int)(r * 255.0f);
mFillStyleG = (int)(g * 255.0f);
mFillStyleB = (int)(b * 255.0f);
mFillStyleA = (int)(a * 255.0f);
}
private void setStrokeStyle(float r, float g, float b, float a) {
// Log.d(TAG, "setStrokeStyle: " + r + ", " + g + ", " + b + ", " + a);
mStrokeStyleR = (int)(r * 255.0f);
mStrokeStyleG = (int)(g * 255.0f);
mStrokeStyleB = (int)(b * 255.0f);
mStrokeStyleA = (int)(a * 255.0f);
}
private void setLineWidth(float lineWidth) {
mLineWidth = lineWidth;
}
private void _fillImageData(byte[] imageData, float imageWidth, float imageHeight, float offsetX, float offsetY) {
Log.d(TAG, "_fillImageData: ");
int fillSize = (int) (imageWidth * imageHeight);
int[] fillColors = new int[fillSize];
int r, g, b, a;
for (int i = 0; i < fillSize; ++i) {
// imageData Pixel (RGBA) -> fillColors int (ARGB)
r = ((int)imageData[4 * i + 0]) & 0xff;
g = ((int)imageData[4 * i + 1]) & 0xff;
b = ((int)imageData[4 * i + 2]) & 0xff;
a = ((int)imageData[4 * i + 3]) & 0xff;
fillColors[i] = (a & 0xff) << 24 | (r & 0xff) << 16 | (g & 0xff) << 8 | (b & 0xff);
}
mBitmap.setPixels(fillColors, 0, (int) imageWidth, (int) offsetX, (int) offsetY, (int) imageWidth, (int) imageHeight);
}
private Point convertDrawPoint(final Point point, String text) {
// The parameter 'point' is located at left-bottom position.
// Need to adjust 'point' according 'text align' & 'text base line'.
Point ret = new Point(point);
createTextPaintIfNeeded();
Paint.FontMetrics fm = mTextPaint.getFontMetrics();
float width = measureText(text);
if (mTextAlign == TEXT_ALIGN_CENTER)
{
ret.x -= width / 2;
}
else if (mTextAlign == TEXT_ALIGN_RIGHT)
{
ret.x -= width;
}
// Canvas.drawText accepts the y parameter as the baseline position, not the most bottom
if (mTextBaseline == TEXT_BASELINE_TOP)
{
ret.y += -fm.ascent;
}
else if (mTextBaseline == TEXT_BASELINE_MIDDLE)
{
ret.y += (fm.descent - fm.ascent) / 2 - fm.descent;
}
else if (mTextBaseline == TEXT_BASELINE_BOTTOM)
{
ret.y += -fm.descent;
}
return ret;
}
private byte[] getDataRef() {
// Log.d(TAG, "this: " + this + ", getDataRef ...");
if (mBitmap != null) {
final int len = mBitmap.getWidth() * mBitmap.getHeight() * 4;
final byte[] pixels = new byte[len];
final ByteBuffer buf = ByteBuffer.wrap(pixels);
buf.order(ByteOrder.nativeOrder());
mBitmap.copyPixelsToBuffer(buf);
return pixels;
}
Log.e(TAG, "getDataRef return null");
return null;
}
}

View File

@ -0,0 +1,331 @@
/****************************************************************************
* Copyright (c) 2020 Xiamen Yaji Software Co., Ltd.
*
* http://www.cocos.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
****************************************************************************/
package com.cocos.lib;
import android.app.Activity;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.graphics.Color;
import android.media.AudioManager;
import android.os.Build;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
import java.io.File;
import java.lang.reflect.Field;
public class CocosActivity extends Activity implements SurfaceHolder.Callback
{
private boolean mDestroyed;
private SurfaceHolder mSurfaceHolder;
protected FrameLayout mFrameLayout;
private CocosSurfaceView mSurfaceView;
private CocosWebViewHelper mWebViewHelper = null;
private CocosVideoHelper mVideoHelper = null;
private CocosOrientationHelper mOrientationHelper = null;
private boolean engineInit = false;
private CocosKeyCodeHandler mKeyCodeHandler;
private CocosSensorHandler mSensorHandler;
private native void onCreateNative(Activity activity, AssetManager assetManager, String obbPath, int sdkVersion);
private native void onSurfaceCreatedNative(Surface surface);
private native void onSurfaceChangedNative(int width, int height);
private native void onSurfaceDestroyNative();
private native void onPauseNative();
private native void onResumeNative();
private native void onStopNative();
private native void onStartNative();
private native void onLowMemoryNative();
private native void onWindowFocusChangedNative(boolean hasFocus);
////blank
public static CocosActivity app;
public FrameLayout getFrameLayout()
{
return mFrameLayout;
}
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
////blank 显示启动图
app = this;
ViewGroup.LayoutParams frameLayoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
mFrameLayout = new FrameLayout(this);
mFrameLayout.setLayoutParams(frameLayoutParams);
setContentView(mFrameLayout);
ImageView imageView = new ImageView(this);
imageView.setBackgroundColor(Color.WHITE);
imageView.setTag("launchImage");
mFrameLayout.addView(imageView, frameLayoutParams);
imageView.setImageResource(R.drawable.launch_image);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
GlobalObject.setActivity(this);
CocosHelper.registerBatteryLevelReceiver(this);
CocosHelper.init(this);
CanvasRenderingContext2DImpl.init(this);
onLoadNativeLibraries();
this.setVolumeControlStream(AudioManager.STREAM_MUSIC);
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
initView();
onCreateNative(this, getAssets(), getAbsolutePath(getObbDir()), Build.VERSION.SDK_INT);
mKeyCodeHandler = new CocosKeyCodeHandler(this);
mSensorHandler = new CocosSensorHandler(this);
setImmersiveMode();
Utils.hideVirtualButton();
mOrientationHelper = new CocosOrientationHelper(this);
}
private void setImmersiveMode()
{
WindowManager.LayoutParams lp = getWindow().getAttributes();
try
{
Field field = lp.getClass().getField("layoutInDisplayCutoutMode");
//Field constValue = lp.getClass().getDeclaredField("LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER");
Field constValue = lp.getClass().getDeclaredField("LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES");
field.setInt(lp, constValue.getInt(null));
// https://developer.android.com/training/system-ui/immersive
int flag = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
flag |= View.class.getDeclaredField("SYSTEM_UI_FLAG_IMMERSIVE_STICKY").getInt(null);
View view = getWindow().getDecorView();
view.setSystemUiVisibility(flag);
} catch (NoSuchFieldException e)
{
e.printStackTrace();
} catch (IllegalAccessException e)
{
e.printStackTrace();
}
}
private static String getAbsolutePath(File file)
{
return (file != null) ? file.getAbsolutePath() : null;
}
protected void initView()
{
////blank 改在create中初始化以显示splash启动图
/*
ViewGroup.LayoutParams frameLayoutParams = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
mFrameLayout = new FrameLayout(this);
mFrameLayout.setLayoutParams(frameLayoutParams);
setContentView(mFrameLayout);
*/
mSurfaceView = new CocosSurfaceView(this);
mSurfaceView.getHolder().addCallback(this);
////blank 加到最底层去这样才能显示启动屏
// mFrameLayout.addView(mSurfaceView);
mFrameLayout.addView(mSurfaceView, 0);
if (mWebViewHelper == null)
{
mWebViewHelper = new CocosWebViewHelper(mFrameLayout);
}
if (mVideoHelper == null)
{
mVideoHelper = new CocosVideoHelper(this, mFrameLayout);
}
}
public CocosSurfaceView getSurfaceView()
{
return this.mSurfaceView;
}
@Override
protected void onDestroy()
{
mDestroyed = true;
if (mSurfaceHolder != null)
{
onSurfaceDestroyNative();
mSurfaceHolder = null;
}
super.onDestroy();
}
@Override
protected void onPause()
{
super.onPause();
mSensorHandler.onPause();
mOrientationHelper.onPause();
onPauseNative();
}
@Override
protected void onResume()
{
super.onResume();
mSensorHandler.onResume();
mOrientationHelper.onResume();
onResumeNative();
}
@Override
protected void onStop()
{
super.onStop();
onStopNative();
}
@Override
protected void onStart()
{
super.onStart();
onStartNative();
}
@Override
public void onLowMemory()
{
super.onLowMemory();
if (!mDestroyed)
{
onLowMemoryNative();
}
}
@Override
public void onWindowFocusChanged(boolean hasFocus)
{
super.onWindowFocusChanged(hasFocus);
if (!mDestroyed)
{
onWindowFocusChangedNative(hasFocus);
}
}
@Override
public void surfaceCreated(SurfaceHolder holder)
{
if (!mDestroyed)
{
mSurfaceHolder = holder;
onSurfaceCreatedNative(holder.getSurface());
engineInit = true;
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
if (!mDestroyed)
{
mSurfaceHolder = holder;
onSurfaceChangedNative(width, height);
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder)
{
mSurfaceHolder = null;
if (!mDestroyed)
{
onSurfaceDestroyNative();
engineInit = false;
}
}
private void onLoadNativeLibraries()
{
try
{
ApplicationInfo ai = getPackageManager().getApplicationInfo(getPackageName(), PackageManager.GET_META_DATA);
Bundle bundle = ai.metaData;
String libName = bundle.getString("android.app.lib_name");
System.loadLibrary(libName);
} catch (Exception e)
{
e.printStackTrace();
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
return mKeyCodeHandler.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event);
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event)
{
return mKeyCodeHandler.onKeyUp(keyCode, event) || super.onKeyUp(keyCode, event);
}
////blank
@Override
public void onBackPressed()
{
CocosHelper.runOnGameThread(new Runnable()
{
@Override
public void run()
{
CocosJavascriptJavaBridge.evalString("cx.rootNode.onBackPressed()");
}
});
}
}

View File

@ -0,0 +1,370 @@
/****************************************************************************
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package com.cocos.lib;
import android.util.Log;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
// Rename package okhttp3 to org.cocos2dx.okhttp3
// Github repo: https://github.com/PatriceJiang/okhttp/tree/cocos2dx-rename-3.12.x
// and https://github.com/PatriceJiang/okio/tree/cocos2dx-rename-1.15.0
import org.cocos2dx.okhttp3.Call;
import org.cocos2dx.okhttp3.Callback;
import org.cocos2dx.okhttp3.OkHttpClient;
import org.cocos2dx.okhttp3.Request;
import org.cocos2dx.okhttp3.Response;
public class CocosDownloader {
private int _id;
private OkHttpClient _httpClient = null;
private String _tempFileNameSuffix;
private int _countOfMaxProcessingTasks;
private ConcurrentHashMap<Integer,Call> _taskMap = new ConcurrentHashMap<>();
private Queue<Runnable> _taskQueue = new LinkedList<>();
private int _runningTaskCount = 0;
private static ConcurrentHashMap<String, Boolean> _resumingSupport = new ConcurrentHashMap<>();
private void onProgress(final int id, final long downloadBytes, final long downloadNow, final long downloadTotal) {
CocosHelper.runOnGameThread(new Runnable() {
@Override
public void run() {
nativeOnProgress(_id, id, downloadBytes, downloadNow, downloadTotal);
}
});
}
private void onFinish(final int id, final int errCode, final String errStr, final byte[] data) {
Call task =_taskMap.get(id);
if (null == task) return;
_taskMap.remove(id);
_runningTaskCount -= 1;
CocosHelper.runOnGameThread(new Runnable() {
@Override
public void run() {
nativeOnFinish(_id, id, errCode, errStr, data);
}
});
runNextTaskIfExists();
}
public static CocosDownloader createDownloader(int id, int timeoutInSeconds, String tempFileSuffix, int maxProcessingTasks) {
CocosDownloader downloader = new CocosDownloader();
downloader._id = id;
if (timeoutInSeconds > 0) {
downloader._httpClient = new OkHttpClient().newBuilder()
.followRedirects(true)
.followSslRedirects(true)
.callTimeout(timeoutInSeconds, TimeUnit.SECONDS)
.build();
} else {
downloader._httpClient = new OkHttpClient().newBuilder()
.followRedirects(true)
.followSslRedirects(true)
.build();
}
downloader._tempFileNameSuffix = tempFileSuffix;
downloader._countOfMaxProcessingTasks = maxProcessingTasks;
return downloader;
}
public static void createTask(final CocosDownloader downloader, int id_, String url_, String path_, String []header_) {
final int id = id_;
final String url = url_;
final String path = path_;
final String[] header = header_;
Runnable taskRunnable = new Runnable() {
String domain = null;
String host = null;
File tempFile = null;
File finalFile = null;
long downloadStart = 0;
@Override
public void run() {
Call task = null;
do {
if (path.length() > 0) {
try {
URI uri = new URI(url);
domain = uri.getHost();
} catch (URISyntaxException e) {
e.printStackTrace();
break;
} catch (NullPointerException e) {
e.printStackTrace();
break;
}
// file task
tempFile = new File(path + downloader._tempFileNameSuffix);
if (tempFile.isDirectory()) break;
File parent = tempFile.getParentFile();
if (!parent.isDirectory() && !parent.mkdirs()) break;
finalFile = new File(path);
if (finalFile.isDirectory()) break;
long fileLen = tempFile.length();
host = domain.startsWith("www.") ? domain.substring(4) : domain;
if (fileLen > 0) {
if (_resumingSupport.containsKey(host) && _resumingSupport.get(host)) {
downloadStart = fileLen;
} else {
// Remove previous downloaded context
try {
PrintWriter writer = new PrintWriter(tempFile);
writer.print("");
writer.close();
}
// Not found then nothing to do
catch (FileNotFoundException e) {
}
}
}
}
final Request.Builder builder = new Request.Builder().url(url);
for (int i = 0; i < header.length / 2; i++) {
builder.addHeader(header[i * 2], header[(i * 2) + 1]);
}
if (downloadStart > 0) {
builder.addHeader("RANGE", "bytes=" + downloadStart + "-");
}
final Request request = builder.build();
task = downloader._httpClient.newCall(request);
task.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
downloader.onFinish(id, 0, e.toString(), null);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
InputStream is = null;
byte[] buf = new byte[4096];
FileOutputStream fos = null;
try {
if(!(response.code() >= 200 && response.code() <= 206)) {
// it is encourage to delete the tmp file when requested range not satisfiable.
if (response.code() == 416) {
File file = new File(path + downloader._tempFileNameSuffix);
if (file.exists() && file.isFile()) {
file.delete();
}
}
downloader.onFinish(id, -2, response.message(), null);
return;
}
long total = response.body().contentLength();
if (path.length() > 0 && !_resumingSupport.containsKey(host)) {
if (total > 0) {
_resumingSupport.put(host, true);
} else {
_resumingSupport.put(host, false);
}
}
long current = downloadStart;
is = response.body().byteStream();
if (path.length() > 0) {
if (downloadStart > 0) {
fos = new FileOutputStream(tempFile, true);
} else {
fos = new FileOutputStream(tempFile, false);
}
int len;
while ((len = is.read(buf)) != -1) {
current += len;
fos.write(buf, 0, len);
downloader.onProgress(id, len, current, total);
}
fos.flush();
String errStr = null;
do {
// rename temp file to final file, if final file exist, remove it
if (finalFile.exists()) {
if (finalFile.isDirectory()) {
break;
}
if (!finalFile.delete()) {
errStr = "Can't remove old file:" + finalFile.getAbsolutePath();
break;
}
}
tempFile.renameTo(finalFile);
} while (false);
if (errStr == null) {
downloader.onFinish(id, 0, null, null);
downloader.runNextTaskIfExists();
}
else
downloader.onFinish(id, 0, errStr, null);
} else {
// 非文件
ByteArrayOutputStream buffer;
if(total > 0) {
buffer = new ByteArrayOutputStream((int) total);
} else {
buffer = new ByteArrayOutputStream(4096);
}
int len;
while ((len = is.read(buf)) != -1) {
current += len;
buffer.write(buf, 0, len);
downloader.onProgress(id, len, current, total);
}
downloader.onFinish(id, 0, null, buffer.toByteArray());
downloader.runNextTaskIfExists();
}
} catch (IOException e) {
e.printStackTrace();
downloader.onFinish(id, 0, e.toString(), null);
} finally {
try {
if (is != null) {
is.close();
}
if (fos != null) {
fos.close();
}
} catch (IOException e) {
Log.e("CocosDownloader", e.toString());
}
}
}
});
} while (false);
if (null == task) {
final String errStr = "Can't create DownloadTask for " + url;
CocosHelper.runOnGameThread(new Runnable() {
@Override
public void run() {
downloader.nativeOnFinish(downloader._id, id, 0, errStr, null);
}
});
} else {
downloader._taskMap.put(id, task);
}
}
};
downloader.enqueueTask(taskRunnable);
}
public static void abort(final CocosDownloader downloader, final int id) {
GlobalObject.getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
Iterator iter = downloader._taskMap.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
Object key = entry.getKey();
Call task = (Call) entry.getValue();
if (null != task && Integer.parseInt(key.toString()) == id) {
task.cancel();
downloader._taskMap.remove(id);
downloader.runNextTaskIfExists();
break;
}
}
}
});
}
public static void cancelAllRequests(final CocosDownloader downloader) {
GlobalObject.getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
for (Object o : downloader._taskMap.entrySet()) {
Map.Entry entry = (Map.Entry) o;
Call task = (Call) entry.getValue();
if (null != task) {
task.cancel();
}
}
}
});
}
private void enqueueTask(Runnable taskRunnable) {
synchronized (_taskQueue) {
if (_runningTaskCount < _countOfMaxProcessingTasks) {
GlobalObject.getActivity().runOnUiThread(taskRunnable);
_runningTaskCount++;
} else {
_taskQueue.add(taskRunnable);
}
}
}
private void runNextTaskIfExists() {
synchronized (_taskQueue) {
while (_runningTaskCount < _countOfMaxProcessingTasks &&
CocosDownloader.this._taskQueue.size() > 0) {
Runnable taskRunnable = CocosDownloader.this._taskQueue.poll();
GlobalObject.getActivity().runOnUiThread(taskRunnable);
_runningTaskCount += 1;
}
}
}
native void nativeOnProgress(int id, int taskId, long dl, long dlnow, long dltotal);
native void nativeOnFinish(int id, int taskId, int errCode, String errStr, final byte[] data);
}

View File

@ -0,0 +1,466 @@
/****************************************************************************
Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package com.cocos.lib;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.StateListDrawable;
import android.graphics.drawable.shapes.RoundRectShape;
import android.os.Bundle;
import android.text.Editable;
import android.text.InputFilter;
import android.text.InputType;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.app.Activity;
import android.content.Intent;
public class CocosEditBoxActivity extends Activity {
// a color of dark green, was used for confirm button background
private static final int DARK_GREEN = Color.parseColor("#1fa014");
private static final int DARK_GREEN_PRESS = Color.parseColor("#008e26");
private static CocosEditBoxActivity sThis = null;
private Cocos2dxEditText mEditText = null;
private Button mButton = null;
private String mButtonTitle = null;
private boolean mConfirmHold = true;
private RelativeLayout mButtonLayout = null;
private RelativeLayout.LayoutParams mButtonParams;
private int mEditTextID = 1;
private int mButtonLayoutID = 2;
/***************************************************************************************
Inner class.
**************************************************************************************/
class Cocos2dxEditText extends EditText {
private final String TAG = "Cocos2dxEditBox";
private boolean mIsMultiLine = false;
private TextWatcher mTextWatcher = null;
private Paint mPaint;
private int mLineColor = DARK_GREEN;
private float mLineWidth = 2f;
private boolean keyboardVisible = false;
private int mScreenHeight;
public Cocos2dxEditText(Activity context){
super(context);
//remove focus border
this.setBackground(null);
this.setTextColor(Color.BLACK);
mScreenHeight = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).
getDefaultDisplay().getHeight();
mPaint = new Paint();
mPaint.setStrokeWidth(mLineWidth);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(mLineColor);
mTextWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
// Pass text to c++.
CocosEditBoxActivity.this.onKeyboardInput(s.toString());
}
};
registKeyboardVisible();
}
/***************************************************************************************
Override functions.
**************************************************************************************/
@Override
protected void onDraw(Canvas canvas) {
// draw the underline
int padB = this.getPaddingBottom();
canvas.drawLine(getScrollX(), this.getHeight() - padB / 2 - mLineWidth,
getScrollX() + this.getWidth(),
this.getHeight() - padB / 2 - mLineWidth, mPaint);
super.onDraw(canvas);
}
/***************************************************************************************
Public functions.
**************************************************************************************/
public void show(String defaultValue, int maxLength, boolean isMultiline, boolean confirmHold, String confirmType, String inputType) {
mIsMultiLine = isMultiline;
this.setFilters(new InputFilter[]{new InputFilter.LengthFilter(maxLength) });
this.setText(defaultValue);
if (this.getText().length() >= defaultValue.length()) {
this.setSelection(defaultValue.length());
} else {
this.setSelection(this.getText().length());
}
this.setConfirmType(confirmType);
this.setInputType(inputType, mIsMultiLine);
this.setVisibility(View.VISIBLE);
// Open soft keyboard manually. Should request focus to open soft keyboard.
this.requestFocus();
this.addListeners();
}
public void hide() {
mEditText.setVisibility(View.INVISIBLE);
this.removeListeners();
}
/***************************************************************************************
Private functions.
**************************************************************************************/
private void setConfirmType(final String confirmType) {
if (confirmType.contentEquals("done")) {
this.setImeOptions(EditorInfo.IME_ACTION_DONE | EditorInfo.IME_FLAG_NO_EXTRACT_UI);
mButtonTitle = getResources().getString(R.string.done);
} else if (confirmType.contentEquals("next")) {
this.setImeOptions(EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NO_EXTRACT_UI);
mButtonTitle = getResources().getString(R.string.next);
} else if (confirmType.contentEquals("search")) {
this.setImeOptions(EditorInfo.IME_ACTION_SEARCH | EditorInfo.IME_FLAG_NO_EXTRACT_UI);
mButtonTitle = getResources().getString(R.string.search);
} else if (confirmType.contentEquals("go")) {
this.setImeOptions(EditorInfo.IME_ACTION_GO | EditorInfo.IME_FLAG_NO_EXTRACT_UI);
mButtonTitle = getResources().getString(R.string.go);
} else if (confirmType.contentEquals("send")) {
this.setImeOptions(EditorInfo.IME_ACTION_SEND | EditorInfo.IME_FLAG_NO_EXTRACT_UI);
mButtonTitle = getResources().getString(R.string.send);
} else{
mButtonTitle = null;
Log.e(TAG, "unknown confirm type " + confirmType);
}
}
private void setInputType(final String inputType, boolean isMultiLine){
if (inputType.contentEquals("text")) {
if (isMultiLine)
this.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE);
else
this.setInputType(InputType.TYPE_CLASS_TEXT);
}
else if (inputType.contentEquals("email"))
this.setInputType(InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
else if (inputType.contentEquals("number"))
this.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL | InputType.TYPE_NUMBER_FLAG_SIGNED);
else if (inputType.contentEquals("phone"))
this.setInputType(InputType.TYPE_CLASS_PHONE);
else if (inputType.contentEquals("password"))
this.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
else
Log.e(TAG, "unknown input type " + inputType);
}
private void addListeners() {
this.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (! mIsMultiLine) {
CocosEditBoxActivity.this.hide();
}
return false; // pass on to other listeners.
}
});
this.addTextChangedListener(mTextWatcher);
}
private void removeListeners() {
this.setOnEditorActionListener(null);
this.removeTextChangedListener(mTextWatcher);
}
private void registKeyboardVisible() {
getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
Rect r = new Rect();
getWindowVisibleDisplayFrame(r);
int heightDiff = getRootView().getHeight() - (r.bottom - r.top);
// if more than a quarter of the screen, its probably a keyboard
if (heightDiff > mScreenHeight/4) {
if (!keyboardVisible) {
keyboardVisible = true;
}
} else {
if (keyboardVisible) {
keyboardVisible = false;
CocosEditBoxActivity.this.hide();
}
}
}
});
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
CocosEditBoxActivity.sThis = this;
ViewGroup.LayoutParams frameLayoutParams =
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
RelativeLayout frameLayout = new RelativeLayout(this);
frameLayout.setLayoutParams(frameLayoutParams);
setContentView(frameLayout);
this.addItems(frameLayout);
Bundle extras = getIntent().getExtras();
show(extras.getString("defaultValue"),
extras.getInt("maxLength"),
extras.getBoolean("isMultiline"),
extras.getBoolean("confirmHold"),
extras.getString("confirmType"),
extras.getString("inputType"));
}
/***************************************************************************************
Public functions.
**************************************************************************************/
/***************************************************************************************
Private functions.
**************************************************************************************/
private void addItems(RelativeLayout layout) {
RelativeLayout myLayout = new RelativeLayout(this);
this.addEditText(myLayout);
this.addButton(myLayout);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
layout.addView(myLayout, layoutParams);
//FXI ME: Is it needed?
// When touch area outside EditText and soft keyboard, then hide.
// layout.setOnTouchListener(new View.OnTouchListener() {
// @Override
// public boolean onTouch(View v, MotionEvent event) {
// Cocos2dxEditBox.this.hide();
// return true;
// }
//
// });
}
private void addEditText(RelativeLayout layout) {
mEditText = new Cocos2dxEditText(this);
mEditText.setVisibility(View.INVISIBLE);
mEditText.setBackgroundColor(Color.WHITE);
mEditText.setId(mEditTextID);
RelativeLayout.LayoutParams editParams = new RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
editParams.addRule(RelativeLayout.LEFT_OF, mButtonLayoutID);
layout.addView(mEditText, editParams);
}
private void addButton(RelativeLayout layout) {
mButton = new Button(this);
mButtonParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
mButton.setTextColor(Color.WHITE);
mButton.setBackground(getRoundRectShape());
mButtonLayout = new RelativeLayout(GlobalObject.getActivity());
mButtonLayout.setBackgroundColor(Color.WHITE);
RelativeLayout.LayoutParams buttonLayoutParams = new RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
buttonLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
buttonLayoutParams.addRule(RelativeLayout.ALIGN_BOTTOM, mEditTextID);
buttonLayoutParams.addRule(RelativeLayout.ALIGN_TOP, mEditTextID);
mButtonLayout.addView(mButton, mButtonParams);
mButtonLayout.setId(mButtonLayoutID);
layout.addView(mButtonLayout, buttonLayoutParams);
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
CocosEditBoxActivity.this.onKeyboardConfirm(mEditText.getText().toString());
if (!CocosEditBoxActivity.this.mConfirmHold)
CocosEditBoxActivity.this.hide();
}
});
}
private Drawable getRoundRectShape() {
int radius = 7;
float[] outerRadii = new float[]{radius, radius, radius, radius, radius, radius, radius, radius};
RoundRectShape roundRectShape = new RoundRectShape(outerRadii, null, null);
ShapeDrawable shapeDrawableNormal = new ShapeDrawable();
shapeDrawableNormal.setShape(roundRectShape);
shapeDrawableNormal.getPaint().setStyle(Paint.Style.FILL);
shapeDrawableNormal.getPaint().setColor(DARK_GREEN);
ShapeDrawable shapeDrawablePress = new ShapeDrawable();
shapeDrawablePress.setShape(roundRectShape);
shapeDrawablePress.getPaint().setStyle(Paint.Style.FILL);
shapeDrawablePress.getPaint().setColor(DARK_GREEN_PRESS);
StateListDrawable drawable = new StateListDrawable();
drawable.addState(new int[]{android.R.attr.state_pressed}, shapeDrawablePress);
drawable.addState(new int[]{}, shapeDrawableNormal);
return drawable;
}
private void hide() {
Utils.hideVirtualButton();
this.closeKeyboard();
finish();
}
public void show(String defaultValue, int maxLength, boolean isMultiline, boolean confirmHold, String confirmType, String inputType) {
mConfirmHold = confirmHold;
mEditText.show(defaultValue, maxLength, isMultiline, confirmHold, confirmType, inputType);
int editPaddingBottom = mEditText.getPaddingBottom();
int editPadding = mEditText.getPaddingTop();
mEditText.setPadding(editPadding, editPadding, editPadding, editPaddingBottom);
mButton.setText(mButtonTitle);
if (TextUtils.isEmpty(mButtonTitle)) {
mButton.setPadding(0, 0, 0, 0);
mButtonParams.setMargins(0, 0, 0, 0);
mButtonLayout.setVisibility(View.INVISIBLE);
} else {
int buttonTextPadding = mEditText.getPaddingBottom() / 2;
mButton.setPadding(editPadding, buttonTextPadding, editPadding, buttonTextPadding);
mButtonParams.setMargins(0, buttonTextPadding, 2, 0);
mButtonLayout.setVisibility(View.VISIBLE);
}
this.openKeyboard();
}
private void closeKeyboard() {
InputMethodManager imm = (InputMethodManager) getSystemService(this.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
this.onKeyboardComplete(mEditText.getText().toString());
}
private void openKeyboard() {
InputMethodManager imm = (InputMethodManager) getSystemService(this.INPUT_METHOD_SERVICE);
imm.showSoftInput(mEditText, InputMethodManager.SHOW_IMPLICIT);
}
/***************************************************************************************
Functions invoked by CPP.
**************************************************************************************/
private static void showNative(String defaultValue, int maxLength, boolean isMultiline, boolean confirmHold, String confirmType, String inputType) {
GlobalObject.getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
Intent i = new Intent(GlobalObject.getActivity(), CocosEditBoxActivity.class);
i.putExtra("defaultValue", defaultValue);
i.putExtra("maxLength", maxLength);
i.putExtra("isMultiline", isMultiline);
i.putExtra("confirmHold", confirmHold);
i.putExtra("confirmType", confirmType);
i.putExtra("inputType", inputType);
GlobalObject.getActivity().startActivity(i);
}
});
}
private static void hideNative() {
if (null != CocosEditBoxActivity.sThis) {
GlobalObject.getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
CocosEditBoxActivity.sThis.hide();
}
});
}
}
/***************************************************************************************
Native functions invoked by UI.
**************************************************************************************/
private void onKeyboardInput(String text) {
CocosHelper.runOnGameThread(new Runnable() {
@Override
public void run() {
CocosEditBoxActivity.onKeyboardInputNative(text);
}
});
}
private void onKeyboardComplete(String text) {
CocosHelper.runOnGameThread(new Runnable() {
@Override
public void run() {
CocosEditBoxActivity.onKeyboardCompleteNative(text);
}
});
}
private void onKeyboardConfirm(String text) {
CocosHelper.runOnGameThread(new Runnable() {
@Override
public void run() {
CocosEditBoxActivity.onKeyboardConfirmNative(text);
}
});
}
private static native void onKeyboardInputNative(String text);
private static native void onKeyboardCompleteNative(String text);
private static native void onKeyboardConfirmNative(String text);
}

View File

@ -0,0 +1,105 @@
/****************************************************************************
Copyright (c) 2010-2013 cocos2d-x.org
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package com.cocos.lib;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import java.lang.ref.WeakReference;
public class CocosHandler extends Handler {
// ===========================================================
// Constants
// ===========================================================
public final static int HANDLER_SHOW_DIALOG = 1;
// ===========================================================
// Fields
// ===========================================================
private WeakReference<Activity> mActivity;
// ===========================================================
// Constructors
// ===========================================================
public CocosHandler(Activity activity) {
this.mActivity = new WeakReference<Activity>(activity);
}
// ===========================================================
// Getter & Setter
// ===========================================================
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
// ===========================================================
// Methods
// ===========================================================
public void handleMessage(Message msg) {
switch (msg.what) {
case CocosHandler.HANDLER_SHOW_DIALOG:
showDialog(msg);
break;
}
}
private void showDialog(Message msg) {
Activity theActivity = this.mActivity.get();
DialogMessage dialogMessage = (DialogMessage)msg.obj;
new AlertDialog.Builder(theActivity)
.setTitle(dialogMessage.title)
.setMessage(dialogMessage.message)
.setPositiveButton("Ok",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// REFINE: Auto-generated method stub
}
}).create().show();
}
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
public static class DialogMessage {
public String title;
public String message;
public DialogMessage(String title, String message) {
this.title = title;
this.message = message;
}
}
}

View File

@ -0,0 +1,349 @@
/****************************************************************************
Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package com.cocos.lib;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.AssetFileDescriptor;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.BatteryManager;
import android.os.Build;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.os.Vibrator;
import android.util.Log;
import android.view.Display;
import android.view.Surface;
import android.view.WindowInsets;
import android.view.WindowManager;
import com.android.vending.expansion.zipfile.APKExpansionSupport;
import com.android.vending.expansion.zipfile.ZipResourceFile;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
public class CocosHelper {
// ===========================================================
// Constants
// ===========================================================
private static final String TAG = CocosHelper.class.getSimpleName();
// ===========================================================
// Fields
// ===========================================================
private static Activity sActivity;
private static Vibrator sVibrateService;
private static BatteryReceiver sBatteryReceiver = new BatteryReceiver();
public static final int NETWORK_TYPE_NONE = 0;
public static final int NETWORK_TYPE_LAN = 1;
public static final int NETWORK_TYPE_WWAN = 2;
// The absolute path to the OBB if it exists.
private static String sObbFilePath = "";
// The OBB file
private static ZipResourceFile sOBBFile = null;
private static List<Runnable> sTaskOnGameThread = Collections.synchronizedList(new ArrayList<>());
/**
* Battery receiver to getting battery level.
*/
static class BatteryReceiver extends BroadcastReceiver {
public float sBatteryLevel = 0.0f;
@Override
public void onReceive(Context context, Intent intent) {
setBatteryLevelByIntent(intent);
}
public void setBatteryLevelByIntent(Intent intent) {
if (null != intent) {
int current = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
int total = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 1);
float level = current * 1.0f / total;
// clamp to 0~1
sBatteryLevel = Math.min(Math.max(level, 0.0f), 1.0f);
}
}
}
static void registerBatteryLevelReceiver(Context context) {
Intent intent = context.registerReceiver(sBatteryReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
sBatteryReceiver.setBatteryLevelByIntent(intent);
}
static void unregisterBatteryLevelReceiver(Context context) {
context.unregisterReceiver(sBatteryReceiver);
}
public static void runOnGameThread(final Runnable runnable) {
sTaskOnGameThread.add(runnable);
}
static void flushTasksOnGameThread() {
while(sTaskOnGameThread.size() > 0) {
Runnable r = sTaskOnGameThread.remove(0);
if(r != null) {
r.run();
}
}
}
public static int getNetworkType() {
int status = NETWORK_TYPE_NONE;
NetworkInfo networkInfo;
try {
ConnectivityManager connMgr = (ConnectivityManager) sActivity.getSystemService(Context.CONNECTIVITY_SERVICE);
networkInfo = connMgr.getActiveNetworkInfo();
} catch (Exception e) {
e.printStackTrace();
return status;
}
if (networkInfo == null) {
return status;
}
int nType = networkInfo.getType();
if (nType == ConnectivityManager.TYPE_MOBILE) {
status = NETWORK_TYPE_WWAN;
} else if (nType == ConnectivityManager.TYPE_WIFI) {
status = NETWORK_TYPE_LAN;
}
return status;
}
// ===========================================================
// Constructors
// ===========================================================
private static boolean sInited = false;
public static void init(final Activity activity) {
sActivity = activity;
if (!sInited) {
CocosHelper.sVibrateService = (Vibrator)activity.getSystemService(Context.VIBRATOR_SERVICE);
CocosHelper.initObbFilePath();
CocosHelper.initializeOBBFile();
sInited = true;
}
}
public static float getBatteryLevel() { return sBatteryReceiver.sBatteryLevel; }
public static String getObbFilePath() { return CocosHelper.sObbFilePath; }
public static String getWritablePath() {
return sActivity.getFilesDir().getAbsolutePath();
}
public static String getCurrentLanguage() {
return Locale.getDefault().getLanguage();
}
public static String getCurrentLanguageCode() {
return Locale.getDefault().toString();
}
public static String getDeviceModel(){
return Build.MODEL;
}
public static String getSystemVersion() {
return Build.VERSION.RELEASE;
}
public static void vibrate(float duration) {
try {
if (sVibrateService != null && sVibrateService.hasVibrator()) {
if (android.os.Build.VERSION.SDK_INT >= 26) {
Class<?> vibrationEffectClass = Class.forName("android.os.VibrationEffect");
if(vibrationEffectClass != null) {
final int DEFAULT_AMPLITUDE = CocosReflectionHelper.<Integer>getConstantValue(vibrationEffectClass,
"DEFAULT_AMPLITUDE");
//VibrationEffect.createOneShot(long milliseconds, int amplitude)
final Method method = vibrationEffectClass.getMethod("createOneShot",
new Class[]{Long.TYPE, Integer.TYPE});
Class<?> type = method.getReturnType();
Object effect = method.invoke(vibrationEffectClass,
new Object[]{(long) (duration * 1000), DEFAULT_AMPLITUDE});
//sVibrateService.vibrate(VibrationEffect effect);
CocosReflectionHelper.invokeInstanceMethod(sVibrateService,"vibrate",
new Class[]{type}, new Object[]{(effect)});
}
} else {
sVibrateService.vibrate((long) (duration * 1000));
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static boolean openURL(String url) {
boolean ret = false;
try {
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
sActivity.startActivity(i);
ret = true;
} catch (Exception e) {
}
return ret;
}
public static void copyTextToClipboard(final String text){
sActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
ClipboardManager myClipboard = (ClipboardManager)sActivity.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData myClip = ClipData.newPlainText("text", text);
myClipboard.setPrimaryClip(myClip);
}
});
}
public static long[] getObbAssetFileDescriptor(final String path) {
long[] array = new long[3];
if (CocosHelper.sOBBFile != null) {
AssetFileDescriptor descriptor = CocosHelper.sOBBFile.getAssetFileDescriptor(path);
if (descriptor != null) {
try {
ParcelFileDescriptor parcel = descriptor.getParcelFileDescriptor();
Method method = parcel.getClass().getMethod("getFd", new Class[] {});
array[0] = (Integer)method.invoke(parcel);
array[1] = descriptor.getStartOffset();
array[2] = descriptor.getLength();
} catch (NoSuchMethodException e) {
Log.e(CocosHelper.TAG, "Accessing file descriptor directly from the OBB is only supported from Android 3.1 (API level 12) and above.");
} catch (IllegalAccessException e) {
Log.e(CocosHelper.TAG, e.toString());
} catch (InvocationTargetException e) {
Log.e(CocosHelper.TAG, e.toString());
}
}
}
return array;
}
public static int getDeviceRotation() {
try {
Display display = ((WindowManager) sActivity.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
return display.getRotation();
} catch (NullPointerException e) {
e.printStackTrace();
}
return Surface.ROTATION_0;
}
// ===========================================================
// Private functions.
// ===========================================================
// Initialize asset path:
// - absolute path to the OBB if it exists,
// - else empty string.
private static void initObbFilePath() {
int versionCode = 1;
final ApplicationInfo applicationInfo = sActivity.getApplicationInfo();
try {
versionCode = CocosHelper.sActivity.getPackageManager().getPackageInfo(applicationInfo.packageName, 0).versionCode;
} catch (NameNotFoundException e) {
e.printStackTrace();
}
String pathToOBB = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/obb/" + applicationInfo.packageName + "/main." + versionCode + "." + applicationInfo.packageName + ".obb";
File obbFile = new File(pathToOBB);
if (obbFile.exists())
CocosHelper.sObbFilePath = pathToOBB;
}
private static void initializeOBBFile() {
int versionCode = 1;
final ApplicationInfo applicationInfo = sActivity.getApplicationInfo();
try {
versionCode = sActivity.getPackageManager().getPackageInfo(applicationInfo.packageName, 0).versionCode;
} catch (NameNotFoundException e) {
e.printStackTrace();
}
try {
CocosHelper.sOBBFile = APKExpansionSupport.getAPKExpansionZipFile(sActivity, versionCode, 0);
} catch (IOException e) {
e.printStackTrace();
}
}
public static float[] getSafeArea() {
if (android.os.Build.VERSION.SDK_INT >= 28) {
do {
Object windowInsectObj = GlobalObject.getActivity().getWindow().getDecorView().getRootWindowInsets();
if(windowInsectObj == null) break;
Class<?> windowInsets = WindowInsets.class;
try {
Method wiGetDisplayCutout = windowInsets.getMethod("getDisplayCutout");
Object cutout = wiGetDisplayCutout.invoke(windowInsectObj);
if(cutout == null) break;
Class<?> displayCutout = cutout.getClass();
Method dcGetLeft = displayCutout.getMethod("getSafeInsetLeft");
Method dcGetRight = displayCutout.getMethod("getSafeInsetRight");
Method dcGetBottom = displayCutout.getMethod("getSafeInsetBottom");
Method dcGetTop = displayCutout.getMethod("getSafeInsetTop");
if (dcGetLeft != null && dcGetRight != null && dcGetBottom != null && dcGetTop != null) {
int left = (Integer) dcGetLeft.invoke(cutout);
int right = (Integer) dcGetRight.invoke(cutout);
int top = (Integer) dcGetTop.invoke(cutout);
int bottom = (Integer) dcGetBottom.invoke(cutout);
return new float[]{top, left, bottom, right};
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}while(false);
}
return new float[]{0,0,0,0};
}
}

View File

@ -0,0 +1,413 @@
/****************************************************************************
Copyright (c) 2010-2014 cocos2d-x.org
Copyright (c) 2014-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package com.cocos.lib;
import android.util.Log;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.zip.GZIPInputStream;
import java.util.zip.InflaterInputStream;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
public class CocosHttpURLConnection
{
private static String TAG = "CocosHttpURLConnection";
private static final String POST_METHOD = "POST" ;
private static final String PUT_METHOD = "PUT" ;
static HttpURLConnection createHttpURLConnection(String linkURL) {
URL url;
HttpURLConnection urlConnection;
try {
url = new URL(linkURL);
urlConnection = (HttpURLConnection) url.openConnection();
//Accept-Encoding
urlConnection.setRequestProperty("Accept-Encoding", "identity");
urlConnection.setDoInput(true);
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "createHttpURLConnection:" + e.toString());
return null;
}
return urlConnection;
}
static void setReadAndConnectTimeout(HttpURLConnection urlConnection, int readMiliseconds, int connectMiliseconds) {
urlConnection.setReadTimeout(readMiliseconds);
urlConnection.setConnectTimeout(connectMiliseconds);
}
static void setRequestMethod(HttpURLConnection urlConnection, String method){
try {
urlConnection.setRequestMethod(method);
if(method.equalsIgnoreCase(POST_METHOD) || method.equalsIgnoreCase(PUT_METHOD)) {
urlConnection.setDoOutput(true);
}
} catch (ProtocolException e) {
Log.e(TAG, "setRequestMethod:" + e.toString());
}
}
static void setVerifySSL(HttpURLConnection urlConnection, String sslFilename) {
if(!(urlConnection instanceof HttpsURLConnection))
return;
HttpsURLConnection httpsURLConnection = (HttpsURLConnection)urlConnection;
try {
InputStream caInput = null;
if (sslFilename.startsWith("/")) {
caInput = new BufferedInputStream(new FileInputStream(sslFilename));
}else {
String assetString = "assets/";
String assetsfilenameString = sslFilename.substring(assetString.length());
caInput = new BufferedInputStream(GlobalObject.getActivity().getAssets().open(assetsfilenameString));
}
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Certificate ca;
ca = cf.generateCertificate(caInput);
System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
caInput.close();
// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
// Create an SSLContext that uses our TrustManager
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
httpsURLConnection.setSSLSocketFactory(context.getSocketFactory());
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "setVerifySSL:" + e.toString());
}
}
//Add header
static void addRequestHeader(HttpURLConnection urlConnection, String key, String value) {
urlConnection.setRequestProperty(key, value);
}
static int connect(HttpURLConnection http) {
int suc = 0;
try {
http.connect();
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "connect" + e.toString());
suc = 1;
}
return suc;
}
static void disconnect(HttpURLConnection http) {
http.disconnect();
}
static void sendRequest(HttpURLConnection http, byte[] byteArray) {
try {
OutputStream out = http.getOutputStream();
if(null != byteArray) {
out.write(byteArray);
out.flush();
}
out.close();
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "sendRequest:" + e.toString());
}
}
static String getResponseHeaders(HttpURLConnection http) {
Map<String, List<String>> headers = http.getHeaderFields();
if (null == headers) {
return null;
}
String header = "";
for (Entry<String, List<String>> entry: headers.entrySet()) {
String key = entry.getKey();
if (null == key) {
header += listToString(entry.getValue(), ",") + "\n";
} else {
header += key + ":" + listToString(entry.getValue(), ",") + "\n";
}
}
return header;
}
static String getResponseHeaderByIdx(HttpURLConnection http, int idx) {
Map<String, List<String>> headers = http.getHeaderFields();
if (null == headers) {
return null;
}
String header = null;
int counter = 0;
for (Entry<String, List<String>> entry: headers.entrySet()) {
if (counter == idx) {
String key = entry.getKey();
if (null == key) {
header = listToString(entry.getValue(), ",") + "\n";
} else {
header = key + ":" + listToString(entry.getValue(), ",") + "\n";
}
break;
}
counter++;
}
return header;
}
static String getResponseHeaderByKey(HttpURLConnection http, String key) {
if (null == key) {
return null;
}
Map<String, List<String>> headers = http.getHeaderFields();
if (null == headers) {
return null;
}
String header = null;
for (Entry<String, List<String>> entry: headers.entrySet()) {
if (key.equalsIgnoreCase(entry.getKey())) {
if ("set-cookie".equalsIgnoreCase(key)) {
header = combinCookies(entry.getValue(), http.getURL().getHost());
} else {
header = listToString(entry.getValue(), ",");
}
break;
}
}
return header;
}
static int getResponseHeaderByKeyInt(HttpURLConnection http, String key) {
String value = http.getHeaderField(key);
if (null == value) {
return 0;
} else {
return Integer.parseInt(value);
}
}
static byte[] getResponseContent(HttpURLConnection http) {
InputStream in;
try {
in = http.getInputStream();
String contentEncoding = http.getContentEncoding();
if (contentEncoding != null) {
if(contentEncoding.equalsIgnoreCase("gzip")){
in = new GZIPInputStream(http.getInputStream()); //reads 2 bytes to determine GZIP stream!
}
else if(contentEncoding.equalsIgnoreCase("deflate")){
in = new InflaterInputStream(http.getInputStream());
}
}
} catch (IOException e) {
in = http.getErrorStream();
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "1 getResponseContent: " + e.toString());
return null;
}
try {
byte[] buffer = new byte[1024];
int size = 0;
ByteArrayOutputStream bytestream = new ByteArrayOutputStream();
while((size = in.read(buffer, 0 , 1024)) != -1)
{
bytestream.write(buffer, 0, size);
}
byte retbuffer[] = bytestream.toByteArray();
bytestream.close();
return retbuffer;
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "2 getResponseContent:" + e.toString());
}
return null;
}
static int getResponseCode(HttpURLConnection http) {
int code = 0;
try {
code = http.getResponseCode();
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "getResponseCode:" + e.toString());
}
return code;
}
static String getResponseMessage(HttpURLConnection http) {
String msg;
try {
msg = http.getResponseMessage();
} catch (Exception e) {
e.printStackTrace();
msg = e.toString();
Log.e(TAG, "getResponseMessage: " + msg);
}
return msg;
}
public static String listToString(List<String> list, String strInterVal) {
if (list == null) {
return null;
}
StringBuilder result = new StringBuilder();
boolean flag = false;
for (String str : list) {
if (flag) {
result.append(strInterVal);
}
if (null == str) {
str = "";
}
result.append(str);
flag = true;
}
return result.toString();
}
public static String combinCookies(List<String> list, String hostDomain) {
StringBuilder sbCookies = new StringBuilder();
String domain = hostDomain;
String tailmatch = "FALSE";
String path = "/";
String secure = "FALSE";
String key = null;
String value = null;
String expires = null;
for (String str : list) {
String[] parts = str.split(";");
for (String part : parts) {
int firstIndex = part.indexOf("=");
if (-1 == firstIndex)
continue;
String[] item = {part.substring(0, firstIndex), part.substring(firstIndex + 1)};
if ("expires".equalsIgnoreCase(item[0].trim())) {
expires = str2Seconds(item[1].trim());
} else if("path".equalsIgnoreCase(item[0].trim())) {
path = item[1];
} else if("secure".equalsIgnoreCase(item[0].trim())) {
secure = item[1];
} else if("domain".equalsIgnoreCase(item[0].trim())) {
domain = item[1];
} else if("version".equalsIgnoreCase(item[0].trim()) || "max-age".equalsIgnoreCase(item[0].trim())) {
//do nothing
} else {
key = item[0];
value = item[1];
}
}
if (null == domain) {
domain = "none";
}
sbCookies.append(domain);
sbCookies.append('\t');
sbCookies.append(tailmatch); //access
sbCookies.append('\t');
sbCookies.append(path); //path
sbCookies.append('\t');
sbCookies.append(secure); //secure
sbCookies.append('\t');
sbCookies.append(expires); //expires
sbCookies.append("\t");
sbCookies.append(key); //key
sbCookies.append("\t");
sbCookies.append(value); //value
sbCookies.append('\n');
}
return sbCookies.toString();
}
private static String str2Seconds(String strTime) {
Calendar c = Calendar.getInstance();
long milliseconds = 0;
try {
c.setTime(new SimpleDateFormat("EEE, dd-MMM-yy hh:mm:ss zzz", Locale.US).parse(strTime));
milliseconds = c.getTimeInMillis() / 1000;
} catch (ParseException e) {
Log.e(TAG, "str2Seconds: " + e.toString());
}
return Long.toString(milliseconds);
}
}

View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2013-2016 Chukong Technologies Inc.
* Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.cocos.lib;
public class CocosJavascriptJavaBridge {
public static native int evalString(String value);
}

View File

@ -0,0 +1,89 @@
/****************************************************************************
Copyright (c) 2010-2013 cocos2d-x.org
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package com.cocos.lib;
import android.view.KeyEvent;
public class CocosKeyCodeHandler {
private CocosActivity mAct;
public native void handleKeyDown(final int keyCode);
public native void handleKeyUp(final int keyCode);
public CocosKeyCodeHandler(CocosActivity act) {
mAct = act;
}
public boolean onKeyDown(final int keyCode, final KeyEvent event) {
switch (keyCode) {
// blank js响应不到KEYCODE_BACK
// case KeyEvent.KEYCODE_BACK:
// CocosVideoHelper.mVideoHandler.sendEmptyMessage(CocosVideoHelper.KeyEventBack);
case KeyEvent.KEYCODE_MENU:
case KeyEvent.KEYCODE_DPAD_LEFT:
case KeyEvent.KEYCODE_DPAD_RIGHT:
case KeyEvent.KEYCODE_DPAD_UP:
case KeyEvent.KEYCODE_DPAD_DOWN:
case KeyEvent.KEYCODE_ENTER:
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
case KeyEvent.KEYCODE_DPAD_CENTER:
CocosHelper.runOnGameThread(new Runnable() {
@Override
public void run() {
handleKeyDown(keyCode);
}
});
return true;
default:
return false;
}
}
public boolean onKeyUp(final int keyCode, KeyEvent event) {
switch (keyCode) {
// blank js响应不到KEYCODE_BACK
// case KeyEvent.KEYCODE_BACK:
case KeyEvent.KEYCODE_MENU:
case KeyEvent.KEYCODE_DPAD_LEFT:
case KeyEvent.KEYCODE_DPAD_RIGHT:
case KeyEvent.KEYCODE_DPAD_UP:
case KeyEvent.KEYCODE_DPAD_DOWN:
case KeyEvent.KEYCODE_ENTER:
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
case KeyEvent.KEYCODE_DPAD_CENTER:
CocosHelper.runOnGameThread(new Runnable() {
@Override
public void run() {
handleKeyUp(keyCode);
} ////blank cocos bug, 原来写的是handleKeyDown(keyCode)
});
return true;
default:
return false;
}
}
}

View File

@ -0,0 +1,170 @@
/****************************************************************************
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package com.cocos.lib;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class CocosLocalStorage {
private static final String TAG = "CocosLocalStorage";
private static String DATABASE_NAME = "jsb.sqlite";
private static String TABLE_NAME = "data";
private static final int DATABASE_VERSION = 1;
private static DBOpenHelper mDatabaseOpenHelper = null;
private static SQLiteDatabase mDatabase = null;
public static boolean init(String dbName, String tableName) {
if (GlobalObject.getActivity() != null) {
DATABASE_NAME = dbName;
TABLE_NAME = tableName;
mDatabaseOpenHelper = new DBOpenHelper(GlobalObject.getActivity());
mDatabase = mDatabaseOpenHelper.getWritableDatabase();
return true;
}
return false;
}
public static void destroy() {
if (mDatabase != null) {
mDatabase.close();
}
}
public static void setItem(String key, String value) {
try {
String sql = "replace into "+TABLE_NAME+"(key,value)values(?,?)";
mDatabase.execSQL(sql, new Object[] { key, value });
} catch (Exception e) {
e.printStackTrace();
}
}
public static String getItem(String key) {
String ret = null;
try {
String sql = "select value from "+TABLE_NAME+" where key=?";
Cursor c = mDatabase.rawQuery(sql, new String[]{key});
while (c.moveToNext()) {
// only return the first value
if (ret != null)
{
Log.e(TAG, "The key contains more than one value.");
break;
}
ret = c.getString(c.getColumnIndex("value"));
}
c.close();
} catch (Exception e) {
e.printStackTrace();
}
return ret;
}
public static void removeItem(String key) {
try {
String sql = "delete from "+TABLE_NAME+" where key=?";
mDatabase.execSQL(sql, new Object[] {key});
} catch (Exception e) {
e.printStackTrace();
}
}
public static void clear() {
try {
String sql = "delete from "+TABLE_NAME;
mDatabase.execSQL(sql);
} catch (Exception e) {
e.printStackTrace();
}
}
public static String getKey(int nIndex) {
String ret = null;
try {
int nCount = 0;
String sql = "select key from "+TABLE_NAME + " order by rowid asc";
Cursor c = mDatabase.rawQuery(sql, null);
if(nIndex < 0 || nIndex >= c.getCount()) {
return null;
}
while (c.moveToNext()) {
if(nCount == nIndex) {
ret = c.getString(c.getColumnIndex("key"));
break;
}
nCount++;
}
c.close();
} catch (Exception e) {
e.printStackTrace();
}
return ret;
}
public static int getLength() {
int res = 0;
try {
String sql = "select count(*) as nums from "+TABLE_NAME;
Cursor c = mDatabase.rawQuery(sql, null);
if (c.moveToNext()){
res = c.getInt(c.getColumnIndex("nums"));
}
c.close();
} catch (Exception e) {
e.printStackTrace();
}
return res;
}
/**
* This creates/opens the database.
*/
private static class DBOpenHelper extends SQLiteOpenHelper {
DBOpenHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE IF NOT EXISTS "+TABLE_NAME+"(key TEXT PRIMARY KEY,value TEXT);");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
+ newVersion + ", which will destroy all old data");
//db.execSQL("DROP TABLE IF EXISTS " + VIRTUAL_TABLE);
//onCreate(db);
}
}
}

View File

@ -0,0 +1,164 @@
/****************************************************************************
Copyright (c) 2010-2013 cocos2d-x.org
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package com.cocos.lib;
import android.app.NativeActivity;
import android.media.AudioManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.FrameLayout;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.content.pm.PackageManager;
import android.content.pm.ApplicationInfo;
public abstract class CocosNativeActivity extends NativeActivity {
// ===========================================================
// Constants
// ===========================================================
private final static String TAG = CocosNativeActivity.class.getSimpleName();
// ===========================================================
// Fields
// ===========================================================
private boolean hasFocus = false;
private boolean paused = true;
protected FrameLayout mFrameLayout = null;
private CocosVideoHelper mVideoHelper = null;
private CocosWebViewHelper mWebViewHelper = null;
// ===========================================================
// Override functions
// ===========================================================
@Override
protected void onCreate(final Bundle savedInstanceState) {
Log.d(TAG, "CocosNativeActivity onCreate: " + this + ", savedInstanceState: " + savedInstanceState);
super.onCreate(savedInstanceState);
// Workaround in https://stackoverflow.com/questions/16283079/re-launch-of-activity-on-home-button-but-only-the-first-time/16447508
if (!isTaskRoot()) {
// Android launched another instance of the root activity into an existing task
// so just quietly finish and go away, dropping the user back into the activity
// at the top of the stack (ie: the last state of this task)
finish();
Log.w(TAG, "[Workaround] Ignore the activity started from icon!");
return;
}
GlobalObject.setActivity(this);
Utils.hideVirtualButton();
CocosHelper.registerBatteryLevelReceiver(this);
// Load native library to enable invoke native API.
onLoadNativeLibraries();
CocosHelper.init(this);
CanvasRenderingContext2DImpl.init(this);
if (mFrameLayout == null) {
ViewGroup.LayoutParams frameLayoutParams = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
mFrameLayout = new FrameLayout(this);
mFrameLayout.setLayoutParams(frameLayoutParams);
//
setContentView(mFrameLayout);
}
if (mVideoHelper == null) {
mVideoHelper = new CocosVideoHelper(this, mFrameLayout);
}
if (mWebViewHelper == null) {
mWebViewHelper = new CocosWebViewHelper(mFrameLayout);
}
this.setVolumeControlStream(AudioManager.STREAM_MUSIC);
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
}
@Override
protected void onResume() {
Log.d(TAG, "onResume()");
paused = false;
super.onResume();
Utils.hideVirtualButton();
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
Log.d(TAG, "onWindowFocusChanged() hasFocus=" + hasFocus);
super.onWindowFocusChanged(hasFocus);
this.hasFocus = hasFocus;
resumeIfHasFocus();
}
@Override
protected void onPause() {
Log.d(TAG, "onPause()");
paused = true;
super.onPause();
}
@Override
protected void onDestroy() {
super.onDestroy();
// Workaround in https://stackoverflow.com/questions/16283079/re-launch-of-activity-on-home-button-but-only-the-first-time/16447508
if (!isTaskRoot()) {
return;
}
CocosHelper.unregisterBatteryLevelReceiver(this);;
CanvasRenderingContext2DImpl.destroy();
}
// ===========================================================
// Protected and private methods
// ===========================================================
protected void onLoadNativeLibraries() {
try {
ApplicationInfo ai = getPackageManager().getApplicationInfo(getPackageName(), PackageManager.GET_META_DATA);
Bundle bundle = ai.metaData;
String libName = bundle.getString("android.app.lib_name");
System.loadLibrary(libName);
} catch (Exception e) {
e.printStackTrace();
}
}
private void resumeIfHasFocus() {
if(hasFocus && !paused) {
Utils.hideVirtualButton();
}
}
}

View File

@ -0,0 +1,62 @@
/****************************************************************************
* Copyright (c) 2020 Xiamen Yaji Software Co., Ltd.
*
* http://www.cocos.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
****************************************************************************/
package com.cocos.lib;
import android.content.Context;
import android.view.OrientationEventListener;
public class CocosOrientationHelper extends OrientationEventListener {
private int mCurrentOrientation;
public CocosOrientationHelper(Context context) {
super(context);
mCurrentOrientation = CocosHelper.getDeviceRotation();
}
public void onPause() {
this.disable();
}
public void onResume() {
this.enable();
}
@Override
public void onOrientationChanged(int orientation) {
int curOrientation = CocosHelper.getDeviceRotation();
if (curOrientation != mCurrentOrientation) {
mCurrentOrientation = CocosHelper.getDeviceRotation();
CocosHelper.runOnGameThread(new Runnable() {
@Override
public void run() {
nativeOnOrientationChanged(mCurrentOrientation);
}
});
}
}
private static native void nativeOnOrientationChanged(int rotation);
}

View File

@ -0,0 +1,75 @@
/****************************************************************************
Copyright (c) 2016 cocos2d-x.org
Copyright (c) 2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package com.cocos.lib;
import android.util.Log;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class CocosReflectionHelper {
public static <T> T getConstantValue(final Class aClass, final String constantName) {
try {
return (T)aClass.getDeclaredField(constantName).get(null);
} catch (NoSuchFieldException e) {
Log.e("error", "can not find " + constantName + " in " + aClass.getName());
}
catch (IllegalAccessException e) {
Log.e("error", constantName + " is not accessable");
}
catch (IllegalArgumentException e) {
Log.e("error", "arguments error when get " + constantName);
}
catch (Exception e) {
Log.e("error", "can not get constant" + constantName);
}
return null;
}
public static <T> T invokeInstanceMethod(final Object instance, final String methodName,
final Class[] parameterTypes, final Object[] parameters) {
final Class aClass = instance.getClass();
try {
final Method method = aClass.getMethod(methodName, parameterTypes);
return (T)method.invoke(instance, parameters);
} catch (NoSuchMethodException e) {
Log.e("error", "can not find " + methodName + " in " + aClass.getName());
}
catch (IllegalAccessException e) {
Log.e("error", methodName + " is not accessible");
}
catch (IllegalArgumentException e) {
Log.e("error", "arguments are error when invoking " + methodName);
}
catch (InvocationTargetException e) {
Log.e("error", "an exception was thrown by the invoked method when invoking " + methodName);
}
return null;
}
}

View File

@ -0,0 +1,139 @@
/****************************************************************************
Copyright (c) 2010-2013 cocos2d-x.org
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package com.cocos.lib;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
public class CocosSensorHandler implements SensorEventListener {
// ===========================================================
// Constants
// ===========================================================
private static final String TAG = "CocosSensorHandler";
private static CocosSensorHandler mSensorHandler;
private final Context mContext;
private final SensorManager mSensorManager;
private final Sensor mAcceleration;
private final Sensor mAccelerationIncludingGravity;
private final Sensor mGyroscope;
private int mSamplingPeriodUs = SensorManager.SENSOR_DELAY_GAME;
private static float[] sDeviceMotionValues = new float[9];
// ===========================================================
// Constructors
// ===========================================================
public CocosSensorHandler(final Context context) {
mContext = context;
mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
mAcceleration = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mAccelerationIncludingGravity = mSensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
mGyroscope = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
mSensorHandler = this;
}
// ===========================================================
// Getter & Setter
// ===========================================================
public void enable() {
mSensorManager.registerListener(this, mAcceleration, mSamplingPeriodUs);
mSensorManager.registerListener(this, mAccelerationIncludingGravity, mSamplingPeriodUs);
mSensorManager.registerListener(this, mGyroscope, mSamplingPeriodUs);
}
public void disable() {
this.mSensorManager.unregisterListener(this);
}
public void setInterval(float interval) {
if (android.os.Build.VERSION.SDK_INT >= 11) {
mSamplingPeriodUs = (int) (interval * 1000000);
}
disable();
enable();
}
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
@Override
public void onSensorChanged(final SensorEvent sensorEvent) {
int type = sensorEvent.sensor.getType();
if (type == Sensor.TYPE_ACCELEROMETER) {
sDeviceMotionValues[0] = sensorEvent.values[0];
sDeviceMotionValues[1] = sensorEvent.values[1];
// Issue https://github.com/cocos-creator/2d-tasks/issues/2532
// use negative event.acceleration.z to match iOS value
sDeviceMotionValues[2] = -sensorEvent.values[2];
} else if (type == Sensor.TYPE_LINEAR_ACCELERATION) {
sDeviceMotionValues[3] = sensorEvent.values[0];
sDeviceMotionValues[4] = sensorEvent.values[1];
sDeviceMotionValues[5] = sensorEvent.values[2];
} else if (type == Sensor.TYPE_GYROSCOPE) {
// The unit is rad/s, need to be converted to deg/s
sDeviceMotionValues[6] = (float) Math.toDegrees(sensorEvent.values[0]);
sDeviceMotionValues[7] = (float) Math.toDegrees(sensorEvent.values[1]);
sDeviceMotionValues[8] = (float) Math.toDegrees(sensorEvent.values[2]);
}
}
@Override
public void onAccuracyChanged(final Sensor sensor, final int accuracy) {
}
public void onPause() {
disable();
}
public void onResume() {
enable();
}
public static void setAccelerometerInterval(float interval) {
mSensorHandler.setInterval(interval);
}
public static void setAccelerometerEnabled(boolean enabled) {
if (enabled) {
mSensorHandler.enable();
} else {
mSensorHandler.disable();
}
mSensorHandler.enable();
}
public static float[] getDeviceMotionValue() {
return sDeviceMotionValues;
}
}

View File

@ -0,0 +1,56 @@
/****************************************************************************
* Copyright (c) 2020 Xiamen Yaji Software Co., Ltd.
*
* http://www.cocos.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
****************************************************************************/
package com.cocos.lib;
import android.content.Context;
import android.view.MotionEvent;
import android.view.SurfaceView;
public class CocosSurfaceView extends SurfaceView {
private CocosTouchHandler mTouchHandler;
public CocosSurfaceView(Context context) {
super(context);
mTouchHandler = new CocosTouchHandler();
}
private native void nativeOnSizeChanged(final int width, final int height);
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
CocosHelper.runOnGameThread(new Runnable() {
@Override
public void run() {
nativeOnSizeChanged(w, h);
}
});
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return mTouchHandler.onTouchEvent(event);
}
}

View File

@ -0,0 +1,181 @@
/****************************************************************************
Copyright (c) 2010-2013 cocos2d-x.org
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package com.cocos.lib;
import android.util.Log;
import android.view.MotionEvent;
public class CocosTouchHandler {
public final static String TAG = "CocosTouchHandler";
private boolean mStopHandleTouchAndKeyEvents = false;
public CocosTouchHandler() {
}
boolean onTouchEvent(MotionEvent pMotionEvent) {
// these data are used in ACTION_MOVE and ACTION_CANCEL
final int pointerNumber = pMotionEvent.getPointerCount();
final int[] ids = new int[pointerNumber];
final float[] xs = new float[pointerNumber];
final float[] ys = new float[pointerNumber];
for (int i = 0; i < pointerNumber; i++) {
ids[i] = pMotionEvent.getPointerId(i);
xs[i] = pMotionEvent.getX(i);
ys[i] = pMotionEvent.getY(i);
}
switch (pMotionEvent.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_POINTER_DOWN:
if (mStopHandleTouchAndKeyEvents) {
// Cocos2dxEditBox.complete();
return true;
}
final int indexPointerDown = pMotionEvent.getAction() >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int idPointerDown = pMotionEvent.getPointerId(indexPointerDown);
final float xPointerDown = pMotionEvent.getX(indexPointerDown);
final float yPointerDown = pMotionEvent.getY(indexPointerDown);
CocosHelper.runOnGameThread(new Runnable() {
@Override
public void run() {
handleActionDown(idPointerDown, xPointerDown, yPointerDown);
}
});
break;
case MotionEvent.ACTION_DOWN:
if (mStopHandleTouchAndKeyEvents) {
// Cocos2dxEditBox.complete();
return true;
}
// there are only one finger on the screen
final int idDown = pMotionEvent.getPointerId(0);
final float xDown = xs[0];
final float yDown = ys[0];
CocosHelper.runOnGameThread(new Runnable() {
@Override
public void run() {
handleActionDown(idDown, xDown, yDown);
}
});
break;
case MotionEvent.ACTION_MOVE:
CocosHelper.runOnGameThread(new Runnable() {
@Override
public void run() {
handleActionMove(ids, xs, ys);
}
});
break;
case MotionEvent.ACTION_POINTER_UP:
final int indexPointUp = pMotionEvent.getAction() >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int idPointerUp = pMotionEvent.getPointerId(indexPointUp);
final float xPointerUp = pMotionEvent.getX(indexPointUp);
final float yPointerUp = pMotionEvent.getY(indexPointUp);
CocosHelper.runOnGameThread(new Runnable() {
@Override
public void run() {
handleActionUp(idPointerUp, xPointerUp, yPointerUp);
}
});
break;
case MotionEvent.ACTION_UP:
// there are only one finger on the screen
final int idUp = pMotionEvent.getPointerId(0);
final float xUp = xs[0];
final float yUp = ys[0];
CocosHelper.runOnGameThread(new Runnable() {
@Override
public void run() {
handleActionUp(idUp, xUp, yUp);
}
});
break;
case MotionEvent.ACTION_CANCEL:
CocosHelper.runOnGameThread(new Runnable() {
@Override
public void run() {
handleActionCancel(ids, xs, ys);
}
});
break;
}
if (BuildConfig.DEBUG) {
// CocosTouchHandler.dumpMotionEvent(pMotionEvent);
}
return true;
}
public void setStopHandleTouchAndKeyEvents(boolean value) {
mStopHandleTouchAndKeyEvents = value;
}
private static void dumpMotionEvent(final MotionEvent event) {
final String names[] = {"DOWN", "UP", "MOVE", "CANCEL", "OUTSIDE", "POINTER_DOWN", "POINTER_UP", "7?", "8?", "9?"};
final StringBuilder sb = new StringBuilder();
final int action = event.getAction();
final int actionCode = action & MotionEvent.ACTION_MASK;
sb.append("event ACTION_").append(names[actionCode]);
if (actionCode == MotionEvent.ACTION_POINTER_DOWN || actionCode == MotionEvent.ACTION_POINTER_UP) {
sb.append("(pid ").append(action >> MotionEvent.ACTION_POINTER_INDEX_SHIFT);
sb.append(")");
}
sb.append("[");
for (int i = 0; i < event.getPointerCount(); i++) {
sb.append("#").append(i);
sb.append("(pid ").append(event.getPointerId(i));
sb.append(")=").append((int) event.getX(i));
sb.append(",").append((int) event.getY(i));
if (i + 1 < event.getPointerCount()) {
sb.append(";");
}
}
sb.append("]");
Log.d(TAG, sb.toString());
}
native void handleActionDown(final int id, final float x, final float y);
native void handleActionMove(final int[] ids, final float[] xPointerList, final float[] yPointerList);
native void handleActionUp(final int id, final float x, final float y);
native void handleActionCancel(final int[] ids, final float[] xPointerList, final float[] yPointerList);
}

View File

@ -0,0 +1,431 @@
/****************************************************************************
Copyright (c) 2014-2016 Chukong Technologies Inc.
Copyright (c) 2017-2020 Xiamen Yaji Software Co., Ltd.
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package com.cocos.lib;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.util.SparseArray;
import android.view.View;
import android.widget.FrameLayout;
import android.app.Activity;
import com.cocos.lib.CocosVideoView.OnVideoEventListener;
import java.lang.ref.WeakReference;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class CocosVideoHelper {
private FrameLayout mLayout = null;
private Activity mActivity = null;
private static SparseArray<CocosVideoView> sVideoViews = null;
static VideoHandler mVideoHandler = null;
private static Handler sHandler = null;
CocosVideoHelper(Activity activity, FrameLayout layout)
{
mActivity = activity;
mLayout = layout;
mVideoHandler = new VideoHandler(this);
sVideoViews = new SparseArray<CocosVideoView>();
sHandler = new Handler(Looper.myLooper());
}
private static int videoTag = 0;
private final static int VideoTaskCreate = 0;
private final static int VideoTaskRemove = 1;
private final static int VideoTaskSetSource = 2;
private final static int VideoTaskSetRect = 3;
private final static int VideoTaskStart = 4;
private final static int VideoTaskPause = 5;
private final static int VideoTaskResume = 6;
private final static int VideoTaskStop = 7;
private final static int VideoTaskSeek = 8;
private final static int VideoTaskSetVisible = 9;
private final static int VideoTaskRestart = 10;
private final static int VideoTaskKeepRatio = 11;
private final static int VideoTaskFullScreen = 12;
private final static int VideoTaskSetVolume = 13;
final static int KeyEventBack = 1000;
static class VideoHandler extends Handler{
WeakReference<CocosVideoHelper> mReference;
VideoHandler(CocosVideoHelper helper){
mReference = new WeakReference<CocosVideoHelper>(helper);
}
@Override
public void handleMessage(Message msg) {
CocosVideoHelper helper = mReference.get();
switch (msg.what) {
case VideoTaskCreate: {
helper._createVideoView(msg.arg1);
break;
}
case VideoTaskRemove: {
helper._removeVideoView(msg.arg1);
break;
}
case VideoTaskSetSource: {
helper._setVideoURL(msg.arg1, msg.arg2, (String)msg.obj);
break;
}
case VideoTaskStart: {
helper._startVideo(msg.arg1);
break;
}
case VideoTaskSetRect: {
Rect rect = (Rect)msg.obj;
helper._setVideoRect(msg.arg1, rect.left, rect.top, rect.right, rect.bottom);
break;
}
case VideoTaskFullScreen:{
if (msg.arg2 == 1) {
helper._setFullScreenEnabled(msg.arg1, true);
} else {
helper._setFullScreenEnabled(msg.arg1, false);
}
break;
}
case VideoTaskPause: {
helper._pauseVideo(msg.arg1);
break;
}
case VideoTaskStop: {
helper._stopVideo(msg.arg1);
break;
}
case VideoTaskSeek: {
helper._seekVideoTo(msg.arg1, msg.arg2);
break;
}
case VideoTaskSetVisible: {
if (msg.arg2 == 1) {
helper._setVideoVisible(msg.arg1, true);
} else {
helper._setVideoVisible(msg.arg1, false);
}
break;
}
case VideoTaskKeepRatio: {
if (msg.arg2 == 1) {
helper._setVideoKeepRatio(msg.arg1, true);
} else {
helper._setVideoKeepRatio(msg.arg1, false);
}
break;
}
case KeyEventBack: {
helper.onBackKeyEvent();
break;
}
case VideoTaskSetVolume: {
float volume = (float) msg.arg2 / 10;
helper._setVolume(msg.arg1, volume);
break;
}
default:
break;
}
super.handleMessage(msg);
}
}
public static native void nativeExecuteVideoCallback(int index,int event);
OnVideoEventListener videoEventListener = new OnVideoEventListener() {
@Override
public void onVideoEvent(int tag,int event) {
CocosHelper.runOnGameThread(new Runnable() {
@Override
public void run() {
nativeExecuteVideoCallback(tag, event);
}
});
}
};
public static int createVideoWidget() {
Message msg = new Message();
msg.what = VideoTaskCreate;
msg.arg1 = videoTag;
mVideoHandler.sendMessage(msg);
return videoTag++;
}
private void _createVideoView(int index) {
CocosVideoView videoView = new CocosVideoView(mActivity,index);
sVideoViews.put(index, videoView);
FrameLayout.LayoutParams lParams = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT);
mLayout.addView(videoView, lParams);
videoView.setZOrderOnTop(true);
videoView.setVideoViewEventListener(videoEventListener);
}
public static void removeVideoWidget(int index){
Message msg = new Message();
msg.what = VideoTaskRemove;
msg.arg1 = index;
mVideoHandler.sendMessage(msg);
}
private void _removeVideoView(int index) {
CocosVideoView view = sVideoViews.get(index);
if (view != null) {
view.stopPlayback();
sVideoViews.remove(index);
mLayout.removeView(view);
}
}
public static void setVideoUrl(int index, int videoSource, String videoUrl) {
Message msg = new Message();
msg.what = VideoTaskSetSource;
msg.arg1 = index;
msg.arg2 = videoSource;
msg.obj = videoUrl;
mVideoHandler.sendMessage(msg);
}
private void _setVideoURL(int index, int videoSource, String videoUrl) {
CocosVideoView videoView = sVideoViews.get(index);
if (videoView != null) {
switch (videoSource) {
case 0:
videoView.setVideoFileName(videoUrl);
break;
case 1:
videoView.setVideoURL(videoUrl);
break;
default:
break;
}
}
}
public static void setVideoRect(int index, int left, int top, int maxWidth, int maxHeight) {
Message msg = new Message();
msg.what = VideoTaskSetRect;
msg.arg1 = index;
msg.obj = new Rect(left, top, maxWidth, maxHeight);
mVideoHandler.sendMessage(msg);
}
private void _setVideoRect(int index, int left, int top, int maxWidth, int maxHeight) {
CocosVideoView videoView = sVideoViews.get(index);
if (videoView != null) {
videoView.setVideoRect(left, top, maxWidth, maxHeight);
}
}
public static void setFullScreenEnabled(int index, boolean enabled) {
Message msg = new Message();
msg.what = VideoTaskFullScreen;
msg.arg1 = index;
if (enabled) {
msg.arg2 = 1;
} else {
msg.arg2 = 0;
}
mVideoHandler.sendMessage(msg);
}
private void _setFullScreenEnabled(int index, boolean enabled) {
CocosVideoView videoView = sVideoViews.get(index);
if (videoView != null) {
videoView.setFullScreenEnabled(enabled);
}
}
private void onBackKeyEvent() {
int viewCount = sVideoViews.size();
for (int i = 0; i < viewCount; i++) {
int key = sVideoViews.keyAt(i);
CocosVideoView videoView = sVideoViews.get(key);
if (videoView != null) {
videoView.setFullScreenEnabled(false);
CocosHelper.runOnGameThread(new Runnable() {
@Override
public void run() {
nativeExecuteVideoCallback(key, KeyEventBack);
}
});
}
}
}
public static void startVideo(int index) {
Message msg = new Message();
msg.what = VideoTaskStart;
msg.arg1 = index;
mVideoHandler.sendMessage(msg);
}
private void _startVideo(int index) {
CocosVideoView videoView = sVideoViews.get(index);
if (videoView != null) {
videoView.start();
}
}
public static void pauseVideo(int index) {
Message msg = new Message();
msg.what = VideoTaskPause;
msg.arg1 = index;
mVideoHandler.sendMessage(msg);
}
private void _pauseVideo(int index) {
CocosVideoView videoView = sVideoViews.get(index);
if (videoView != null) {
videoView.pause();
}
}
public static void stopVideo(int index) {
Message msg = new Message();
msg.what = VideoTaskStop;
msg.arg1 = index;
mVideoHandler.sendMessage(msg);
}
private void _stopVideo(int index) {
CocosVideoView videoView = sVideoViews.get(index);
if (videoView != null) {
videoView.stop();
}
}
public static void seekVideoTo(int index,int msec) {
Message msg = new Message();
msg.what = VideoTaskSeek;
msg.arg1 = index;
msg.arg2 = msec;
mVideoHandler.sendMessage(msg);
}
private void _seekVideoTo(int index,int msec) {
CocosVideoView videoView = sVideoViews.get(index);
if (videoView != null) {
videoView.seekTo(msec);
}
}
public static float getCurrentTime(final int index) {
CocosVideoView video = sVideoViews.get(index);
float currentPosition = -1;
if (video != null) {
currentPosition = video.getCurrentPosition() / 1000.0f;
}
return currentPosition;
}
public static float getDuration(final int index) {
CocosVideoView video = sVideoViews.get(index);
float duration = -1;
if (video != null) {
duration = video.getDuration() / 1000.0f;
}
if (duration <= 0) {
Log.w("CocosVideoHelper", "Video player's duration is not ready to get now!");
}
return duration;
}
public static void setVideoVisible(int index, boolean visible) {
Message msg = new Message();
msg.what = VideoTaskSetVisible;
msg.arg1 = index;
if (visible) {
msg.arg2 = 1;
} else {
msg.arg2 = 0;
}
mVideoHandler.sendMessage(msg);
}
private void _setVideoVisible(int index, boolean visible) {
CocosVideoView videoView = sVideoViews.get(index);
if (videoView != null) {
if (visible) {
videoView.fixSize();
videoView.setVisibility(View.VISIBLE);
} else {
videoView.setVisibility(View.INVISIBLE);
}
}
}
public static void setVideoKeepRatioEnabled(int index, boolean enable) {
Message msg = new Message();
msg.what = VideoTaskKeepRatio;
msg.arg1 = index;
if (enable) {
msg.arg2 = 1;
} else {
msg.arg2 = 0;
}
mVideoHandler.sendMessage(msg);
}
private void _setVideoKeepRatio(int index, boolean enable) {
CocosVideoView videoView = sVideoViews.get(index);
if (videoView != null) {
videoView.setKeepRatio(enable);
}
}
private void _setVolume(final int index, final float volume) {
CocosVideoView videoView = sVideoViews.get(index);
if (videoView != null) {
videoView.setVolume(volume);
}
}
public static void setVolume(final int index, final float volume) {
Message msg = new Message();
msg.what = VideoTaskSetVolume;
msg.arg1 = index;
msg.arg2 = (int) (volume * 10);
mVideoHandler.sendMessage(msg);
}
}

View File

@ -0,0 +1,595 @@
/*
* Copyright (C) 2006 The Android Open Source Project
* Copyright (c) 2014-2016 Chukong Technologies Inc.
* Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.cocos.lib;
import android.annotation.TargetApi;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Build;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.FrameLayout;
import android.app.Activity;
import android.graphics.Point;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Map;
public class CocosVideoView extends SurfaceView {
// ===========================================================
// Internal classes and interfaces.
// ===========================================================
public interface OnVideoEventListener {
void onVideoEvent(int tag,int event);
}
private enum State {
IDLE,
ERROR,
INITIALIZED,
PREPARING,
PREPARED,
STARTED,
PAUSED,
STOPPED,
PLAYBACK_COMPLETED,
}
// ===========================================================
// Constants
// ===========================================================
private static final String AssetResourceRoot = "@assets/";
// ===========================================================
// Fields
// ===========================================================
private String TAG = "CocosVideoView";
private Uri mVideoUri;
private int mDuration;
private int mPosition;
private State mCurrentState = State.IDLE;
// All the stuff we need for playing and showing a video
private SurfaceHolder mSurfaceHolder = null;
private MediaPlayer mMediaPlayer = null;
private int mVideoWidth = 0;
private int mVideoHeight = 0;
private OnVideoEventListener mOnVideoEventListener;
// recording the seek position while preparing
private int mSeekWhenPrepared = 0;
protected Activity mActivity = null;
protected int mViewLeft = 0;
protected int mViewTop = 0;
protected int mViewWidth = 0;
protected int mViewHeight = 0;
protected int mVisibleLeft = 0;
protected int mVisibleTop = 0;
protected int mVisibleWidth = 0;
protected int mVisibleHeight = 0;
protected boolean mFullScreenEnabled = false;
private boolean mIsAssetRouse = false;
private String mVideoFilePath = null;
private int mViewTag = 0;
private boolean mKeepRatio = false;
private boolean mMetaUpdated = false;
// MediaPlayer will be released when surface view is destroyed, so should record the position,
// and use it to play after MedialPlayer is created again.
private int mPositionBeforeRelease = 0;
// ===========================================================
// Constructors
// ===========================================================
public CocosVideoView(Activity activity, int tag) {
super(activity);
mViewTag = tag;
mActivity = activity;
initVideoView();
}
// ===========================================================
// Getter & Setter
// ===========================================================
public void setVideoRect(int left, int top, int maxWidth, int maxHeight) {
if (mViewLeft == left && mViewTop == top && mViewWidth == maxWidth && mViewHeight == maxHeight)
return;
mViewLeft = left;
mViewTop = top;
mViewWidth = maxWidth;
mViewHeight = maxHeight;
fixSize(mViewLeft, mViewTop, mViewWidth, mViewHeight);
}
public void setFullScreenEnabled(boolean enabled) {
if (mFullScreenEnabled != enabled) {
mFullScreenEnabled = enabled;
fixSize();
}
}
public void setVolume (float volume) {
if (mMediaPlayer != null) {
mMediaPlayer.setVolume(volume, volume);
}
}
public void setKeepRatio(boolean enabled) {
mKeepRatio = enabled;
fixSize();
}
public void setVideoURL(String url) {
mIsAssetRouse = false;
setVideoURI(Uri.parse(url), null);
}
public void setVideoFileName(String path) {
if (path.startsWith(AssetResourceRoot)) {
path = path.substring(AssetResourceRoot.length());
}
if (path.startsWith("/")) {
mIsAssetRouse = false;
setVideoURI(Uri.parse(path),null);
}
else {
mVideoFilePath = path;
mIsAssetRouse = true;
setVideoURI(Uri.parse(path), null);
}
}
public int getCurrentPosition() {
if (! (mCurrentState == State.IDLE ||
mCurrentState == State.ERROR ||
mCurrentState == State.INITIALIZED ||
mCurrentState == State.STOPPED ||
mMediaPlayer == null) ) {
mPosition = mMediaPlayer.getCurrentPosition();
}
return mPosition;
}
public int getDuration() {
if (! (mCurrentState == State.IDLE ||
mCurrentState == State.ERROR ||
mCurrentState == State.INITIALIZED ||
mCurrentState == State.STOPPED ||
mMediaPlayer == null) ) {
mDuration = mMediaPlayer.getDuration();
}
return mDuration;
}
/**
* Register a callback to be invoked when some video event triggered.
*
* @param l The callback that will be run
*/
public void setVideoViewEventListener(OnVideoEventListener l)
{
mOnVideoEventListener = l;
}
// ===========================================================
// Overrides
// ===========================================================
@Override
public void setVisibility(int visibility) {
super.setVisibility(visibility);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(mVisibleWidth, mVisibleHeight);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_UP) {
this.sendEvent(EVENT_CLICKED);
}
return true;
}
// ===========================================================
// Public functions
// ===========================================================
public void stop() {
if (!(mCurrentState == State.IDLE || mCurrentState == State.INITIALIZED || mCurrentState == State.ERROR || mCurrentState == State.STOPPED)
&& mMediaPlayer != null) {
mCurrentState = State.STOPPED;
mMediaPlayer.stop();
this.sendEvent(EVENT_STOPPED);
// after the video is stop, it shall prepare to be playable again
try {
mMediaPlayer.prepare();
this.showFirstFrame();
} catch (Exception ex) {}
}
}
public void stopPlayback() {
this.release();
}
public void start() {
if ((mCurrentState == State.PREPARED ||
mCurrentState == State.PAUSED ||
mCurrentState == State.PLAYBACK_COMPLETED) &&
mMediaPlayer != null) {
mCurrentState = State.STARTED;
mMediaPlayer.start();
this.sendEvent(EVENT_PLAYING);
}
}
public void pause() {
if ((mCurrentState == State.STARTED || mCurrentState == State.PLAYBACK_COMPLETED) &&
mMediaPlayer != null) {
mCurrentState = State.PAUSED;
mMediaPlayer.pause();
this.sendEvent(EVENT_PAUSED);
}
}
public void seekTo(int ms) {
if (mCurrentState == State.IDLE || mCurrentState == State.INITIALIZED ||
mCurrentState == State.STOPPED || mCurrentState == State.ERROR ||
mMediaPlayer == null) {
return;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
try {
Method seekTo = mMediaPlayer.getClass().getMethod("seekTo", long.class, int.class);
// The mode argument added in API level 26, 3 = MediaPlayer.SEEK_CLOSEST
// https://developer.android.com/reference/android/media/MediaPlayer#seekTo(int)
seekTo.invoke(mMediaPlayer, ms, 3);
} catch (Exception e) {
mMediaPlayer.seekTo(ms);
}
}
else {
mMediaPlayer.seekTo(ms);
}
}
public void fixSize() {
if (mFullScreenEnabled) {
Point screenSize = new Point();
mActivity.getWindowManager().getDefaultDisplay().getSize(screenSize);
fixSize(0, 0, screenSize.x, screenSize.y);
} else {
fixSize(mViewLeft, mViewTop, mViewWidth, mViewHeight);
}
}
public void fixSize(int left, int top, int width, int height) {
if (mVideoWidth == 0 || mVideoHeight == 0) {
mVisibleLeft = left;
mVisibleTop = top;
mVisibleWidth = width;
mVisibleHeight = height;
}
else if (width != 0 && height != 0) {
if (mKeepRatio && !mFullScreenEnabled) {
if ( mVideoWidth * height > width * mVideoHeight ) {
mVisibleWidth = width;
mVisibleHeight = width * mVideoHeight / mVideoWidth;
} else if ( mVideoWidth * height < width * mVideoHeight ) {
mVisibleWidth = height * mVideoWidth / mVideoHeight;
mVisibleHeight = height;
}
mVisibleLeft = left + (width - mVisibleWidth) / 2;
mVisibleTop = top + (height - mVisibleHeight) / 2;
} else {
mVisibleLeft = left;
mVisibleTop = top;
mVisibleWidth = width;
mVisibleHeight = height;
}
}
else {
mVisibleLeft = left;
mVisibleTop = top;
mVisibleWidth = mVideoWidth;
mVisibleHeight = mVideoHeight;
}
getHolder().setFixedSize(mVisibleWidth, mVisibleHeight);
FrameLayout.LayoutParams lParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.MATCH_PARENT);
lParams.leftMargin = mVisibleLeft;
lParams.topMargin = mVisibleTop;
setLayoutParams(lParams);
}
public int resolveAdjustedSize(int desiredSize, int measureSpec) {
int result = desiredSize;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
switch (specMode) {
case MeasureSpec.UNSPECIFIED:
/* Parent says we can be as big as we want. Just don't be larger
* than max size imposed on ourselves.
*/
result = desiredSize;
break;
case MeasureSpec.AT_MOST:
/* Parent says we can be as big as we want, up to specSize.
* Don't be larger than specSize, and don't be larger than
* the max size imposed on ourselves.
*/
result = Math.min(desiredSize, specSize);
break;
case MeasureSpec.EXACTLY:
// No choice. Do what we are told.
result = specSize;
break;
}
return result;
}
// ===========================================================
// Private functions
// ===========================================================
private void initVideoView() {
mVideoWidth = 0;
mVideoHeight = 0;
getHolder().addCallback(mSHCallback);
//Fix issue#11516:Can't play video on Android 2.3.x
getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
setFocusable(true);
setFocusableInTouchMode(true);
mCurrentState = State.IDLE;
}
/**
* @hide
*/
private void setVideoURI(Uri uri, Map<String, String> headers) {
mVideoUri = uri;
mVideoWidth = 0;
mVideoHeight = 0;
}
private void openVideo() {
if (mSurfaceHolder == null) {
// not ready for playback just yet, will try again later
return;
}
if (mIsAssetRouse) {
if(mVideoFilePath == null)
return;
} else if(mVideoUri == null) {
return;
}
this.pausePlaybackService();
try {
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setOnPreparedListener(mPreparedListener);
mMediaPlayer.setOnCompletionListener(mCompletionListener);
mMediaPlayer.setOnErrorListener(mErrorListener);
mMediaPlayer.setDisplay(mSurfaceHolder);
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setScreenOnWhilePlaying(true);
if (mIsAssetRouse) {
AssetFileDescriptor afd = mActivity.getAssets().openFd(mVideoFilePath);
mMediaPlayer.setDataSource(afd.getFileDescriptor(),afd.getStartOffset(),afd.getLength());
} else {
mMediaPlayer.setDataSource(mVideoUri.toString());
}
mCurrentState = State.INITIALIZED;
// Use Prepare() instead of PrepareAsync to make things easy.
mMediaPlayer.prepare();
this.showFirstFrame();
// mMediaPlayer.prepareAsync();
} catch (IOException ex) {
Log.w(TAG, "Unable to open content: " + mVideoUri, ex);
mCurrentState = State.ERROR;
mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
return;
} catch (IllegalArgumentException ex) {
Log.w(TAG, "Unable to open content: " + mVideoUri, ex);
mCurrentState = State.ERROR;
mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
return;
}
}
MediaPlayer.OnPreparedListener mPreparedListener = new MediaPlayer.OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
mVideoWidth = mp.getVideoWidth();
mVideoHeight = mp.getVideoHeight();
if (mVideoWidth != 0 && mVideoHeight != 0) {
fixSize();
}
if(!mMetaUpdated) {
CocosVideoView.this.sendEvent(EVENT_META_LOADED);
CocosVideoView.this.sendEvent(EVENT_READY_TO_PLAY);
mMetaUpdated = true;
}
mCurrentState = State.PREPARED;
if (mPositionBeforeRelease > 0) {
CocosVideoView.this.start();
CocosVideoView.this.seekTo(mPositionBeforeRelease);
mPositionBeforeRelease = 0;
}
}
};
private MediaPlayer.OnCompletionListener mCompletionListener =
new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
mCurrentState = State.PLAYBACK_COMPLETED;
CocosVideoView.this.sendEvent(EVENT_COMPLETED);
}
};
private static final int EVENT_PLAYING = 0;
private static final int EVENT_PAUSED = 1;
private static final int EVENT_STOPPED = 2;
private static final int EVENT_COMPLETED = 3;
private static final int EVENT_META_LOADED = 4;
private static final int EVENT_CLICKED = 5;
private static final int EVENT_READY_TO_PLAY = 6;
private MediaPlayer.OnErrorListener mErrorListener =
new MediaPlayer.OnErrorListener() {
public boolean onError(MediaPlayer mp, int framework_err, int impl_err) {
Log.d(TAG, "Error: " + framework_err + "," + impl_err);
mCurrentState = State.ERROR;
/* Otherwise, pop up an error dialog so the user knows that
* something bad has happened. Only try and pop up the dialog
* if we're attached to a window. When we're going away and no
* longer have a window, don't bother showing the user an error.
*/
if (getWindowToken() != null) {
Resources r = mActivity.getResources();
int messageId;
if (framework_err == MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK) {
// messageId = com.android.internal.R.string.VideoView_error_text_invalid_progressive_playback;
messageId = r.getIdentifier("VideoView_error_text_invalid_progressive_playback", "string", "android");
} else {
// messageId = com.android.internal.R.string.VideoView_error_text_unknown;
messageId = r.getIdentifier("VideoView_error_text_unknown", "string", "android");
}
int titleId = r.getIdentifier("VideoView_error_title", "string", "android");
int buttonStringId = r.getIdentifier("VideoView_error_button", "string", "android");
new AlertDialog.Builder(mActivity)
.setTitle(r.getString(titleId))
.setMessage(messageId)
.setPositiveButton(r.getString(buttonStringId),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
/* If we get here, there is no onError listener, so
* at least inform them that the video is over.
*/
CocosVideoView.this.sendEvent(EVENT_COMPLETED);
}
})
.setCancelable(false)
.show();
}
return true;
}
};
SurfaceHolder.Callback mSHCallback = new SurfaceHolder.Callback()
{
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
}
public void surfaceCreated(SurfaceHolder holder) {
mSurfaceHolder = holder;
CocosVideoView.this.openVideo();
}
public void surfaceDestroyed(SurfaceHolder holder) {
// after we return from this we can't use the surface any more
mSurfaceHolder = null;
mPositionBeforeRelease = getCurrentPosition();
CocosVideoView.this.release();
}
};
/*
* release the media player in any state
*/
private void release() {
if (mMediaPlayer != null) {
mMediaPlayer.release();
mMediaPlayer = null;
mCurrentState = State.IDLE;
}
}
private void showFirstFrame() {
mMediaPlayer.seekTo(1);
}
private void sendEvent(int event) {
if (this.mOnVideoEventListener != null) {
this.mOnVideoEventListener.onVideoEvent(this.mViewTag, event);
}
}
// Tell the music playback service to pause
// REFINE: these constants need to be published somewhere in the framework.
private void pausePlaybackService() {
Intent i = new Intent("com.android.music.musicservicecommand");
i.putExtra("command", "pause");
mActivity.sendBroadcast(i);
}
}

View File

@ -0,0 +1,175 @@
/****************************************************************************
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package com.cocos.lib;
import android.annotation.SuppressLint;
import android.content.Context;
import android.util.Log;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.FrameLayout;
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] = CocosWebViewHelper._shouldStartLoading(mViewTag, mUrlString);
this.mLatch.countDown(); // notify that result is ready
}
}
public class CocosWebView extends WebView {
private static final String TAG = CocosWebViewHelper.class.getSimpleName();
private int mViewTag;
private String mJSScheme;
public CocosWebView(Context context) {
this(context, -1);
}
@SuppressLint("SetJavaScriptEnabled")
public CocosWebView(Context context, int viewTag) {
super(context);
this.mViewTag = viewTag;
this.mJSScheme = "";
this.setFocusable(true);
this.setFocusableInTouchMode(true);
this.getSettings().setSupportZoom(false);
this.getSettings().setDomStorageEnabled(true);
this.getSettings().setJavaScriptEnabled(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());
}
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) {
CocosActivity activity = (CocosActivity)GlobalObject.getActivity();
try {
URI uri = URI.create(urlString);
if (uri != null && uri.getScheme().equals(mJSScheme)) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
CocosWebViewHelper._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.runOnUiThread(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);
CocosHelper.runOnGameThread(new Runnable() {
@Override
public void run() {
CocosWebViewHelper._didFinishLoading(mViewTag, url);
}
});
}
@Override
public void onReceivedError(WebView view, int errorCode, String description, final String failingUrl) {
super.onReceivedError(view, errorCode, description, failingUrl);
CocosHelper.runOnGameThread(new Runnable() {
@Override
public void run() {
CocosWebViewHelper._didFailLoading(mViewTag, failingUrl);
}
});
}
}
public void setWebViewRect(int left, int top, int maxWidth, int maxHeight) {
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.MATCH_PARENT);
layoutParams.leftMargin = left;
layoutParams.topMargin = top;
layoutParams.width = maxWidth;
layoutParams.height = maxHeight;
this.setLayoutParams(layoutParams);
}
}

View File

@ -0,0 +1,312 @@
/****************************************************************************
Copyright (c) 2010-2011 cocos2d-x.org
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package com.cocos.lib;
import android.graphics.Color;
import android.os.Handler;
import android.os.Looper;
import android.util.SparseArray;
import android.view.View;
import android.webkit.WebView;
import android.widget.FrameLayout;
import android.widget.PopupWindow;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class CocosWebViewHelper {
private static final String TAG = CocosWebViewHelper.class.getSimpleName();
private static Handler sHandler;
private static CocosActivity sCocos2Activity;
private static PopupWindow sPopUp;
private static FrameLayout sLayout;
private static SparseArray<CocosWebView> webViews;
private static int viewTag = 0;
public CocosWebViewHelper(FrameLayout layout) {
CocosWebViewHelper.sLayout = layout;
CocosWebViewHelper.sHandler = new Handler(Looper.myLooper());
CocosWebViewHelper.sCocos2Activity = (CocosActivity) GlobalObject.getActivity();
CocosWebViewHelper.webViews = new SparseArray<CocosWebView>();
}
private static native boolean shouldStartLoading(int index, String message);
private static native void didFinishLoading(int index, String message);
private static native void didFailLoading(int index, String message);
private static native void onJsCallback(int index, String message);
public static boolean _shouldStartLoading(int index, String message) { return !shouldStartLoading(index, message); }
public static void _didFinishLoading(int index, String message) { didFinishLoading(index, message); }
public static void _didFailLoading(int index, String message) { didFailLoading(index, message); }
public static void _onJsCallback(int index, String message) { onJsCallback(index, message); }
public static int createWebView() {
final int index = viewTag;
sCocos2Activity.runOnUiThread(new Runnable() {
@Override
public void run() {
CocosWebView webView = new CocosWebView(sCocos2Activity, index);
FrameLayout.LayoutParams lParams = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT);
sLayout.addView(webView, lParams);
webViews.put(index, webView);
}
});
return viewTag++;
}
public static void removeWebView(final int index) {
sCocos2Activity.runOnUiThread(new Runnable() {
@Override
public void run() {
CocosWebView webView = webViews.get(index);
if (webView != null) {
webViews.remove(index);
sLayout.removeView(webView);
webView.destroy();
webView = null;
}
}
});
}
public static void setVisible(final int index, final boolean visible) {
sCocos2Activity.runOnUiThread(new Runnable() {
@Override
public void run() {
CocosWebView webView = webViews.get(index);
if (webView != null) {
webView.setVisibility(visible ? View.VISIBLE : View.GONE);
}
}
});
}
public static void setWebViewRect(final int index, final int left, final int top, final int maxWidth, final int maxHeight) {
sCocos2Activity.runOnUiThread(new Runnable() {
@Override
public void run() {
CocosWebView webView = webViews.get(index);
if (webView != null) {
webView.setWebViewRect(left, top, maxWidth, maxHeight);
}
}
});
}
public static void setBackgroundTransparent(final int index, final boolean isTransparent) {
sCocos2Activity.runOnUiThread(new Runnable() {
@Override
public void run() {
CocosWebView webView = webViews.get(index);
if (webView != null) {
webView.setBackgroundColor(isTransparent ? Color.TRANSPARENT : Color.WHITE);
webView.setLayerType(WebView.LAYER_TYPE_SOFTWARE, null);
}
}
});
}
public static void setJavascriptInterfaceScheme(final int index, final String scheme) {
sCocos2Activity.runOnUiThread(new Runnable() {
@Override
public void run() {
CocosWebView webView = webViews.get(index);
if (webView != null) {
webView.setJavascriptInterfaceScheme(scheme);
}
}
});
}
public static void loadData(final int index, final String data, final String mimeType, final String encoding, final String baseURL) {
sCocos2Activity.runOnUiThread(new Runnable() {
@Override
public void run() {
CocosWebView webView = webViews.get(index);
if (webView != null) {
webView.loadDataWithBaseURL(baseURL, data, mimeType, encoding, null);
}
}
});
}
public static void loadHTMLString(final int index, final String data, final String baseUrl) {
sCocos2Activity.runOnUiThread(new Runnable() {
@Override
public void run() {
CocosWebView webView = webViews.get(index);
if (webView != null) {
webView.loadDataWithBaseURL(baseUrl, data, null, null, null);
}
}
});
}
public static void loadUrl(final int index, final String url) {
sCocos2Activity.runOnUiThread(new Runnable() {
@Override
public void run() {
CocosWebView webView = webViews.get(index);
if (webView != null) {
webView.loadUrl(url);
}
}
});
}
public static void loadFile(final int index, final String filePath) {
sCocos2Activity.runOnUiThread(new Runnable() {
@Override
public void run() {
CocosWebView webView = webViews.get(index);
if (webView != null) {
webView.loadUrl(filePath);
}
}
});
}
public static void stopLoading(final int index) {
sCocos2Activity.runOnUiThread(new Runnable() {
@Override
public void run() {
CocosWebView webView = webViews.get(index);
if (webView != null) {
webView.stopLoading();
}
}
});
}
public static void reload(final int index) {
sCocos2Activity.runOnUiThread(new Runnable() {
@Override
public void run() {
CocosWebView webView = webViews.get(index);
if (webView != null) {
webView.reload();
}
}
});
}
public static <T> T callInMainThread(Callable<T> call) throws ExecutionException, InterruptedException {
FutureTask<T> task = new FutureTask<T>(call);
sHandler.post(task);
return task.get();
}
public static boolean canGoBack(final int index) {
Callable<Boolean> callable = new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
CocosWebView webView = webViews.get(index);
return webView != null && webView.canGoBack();
}
};
try {
return callInMainThread(callable);
} catch (ExecutionException e) {
return false;
} catch (InterruptedException e) {
return false;
}
}
public static boolean canGoForward(final int index) {
Callable<Boolean> callable = new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
CocosWebView webView = webViews.get(index);
return webView != null && webView.canGoForward();
}
};
try {
return callInMainThread(callable);
} catch (ExecutionException e) {
return false;
} catch (InterruptedException e) {
return false;
}
}
public static void goBack(final int index) {
sCocos2Activity.runOnUiThread(new Runnable() {
@Override
public void run() {
CocosWebView webView = webViews.get(index);
if (webView != null) {
webView.goBack();
}
}
});
}
public static void goForward(final int index) {
sCocos2Activity.runOnUiThread(new Runnable() {
@Override
public void run() {
CocosWebView webView = webViews.get(index);
if (webView != null) {
webView.goForward();
}
}
});
}
public static void evaluateJS(final int index, final String js) {
sCocos2Activity.runOnUiThread(new Runnable() {
@Override
public void run() {
CocosWebView webView = webViews.get(index);
if (webView != null) {
webView.loadUrl("javascript:" + js);
}
}
});
}
public static void setScalesPageToFit(final int index, final boolean scalesPageToFit) {
sCocos2Activity.runOnUiThread(new Runnable() {
@Override
public void run() {
CocosWebView webView = webViews.get(index);
if (webView != null) {
webView.setScalesPageToFit(scalesPageToFit);
}
}
});
}
}

View File

@ -0,0 +1,38 @@
/****************************************************************************
Copyright (c) 2020 Xiamen Yaji Software Co., Ltd.
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package com.cocos.lib;
import android.app.Activity;
public class GlobalObject {
private static Activity sActivity = null;
public static void setActivity(Activity activity) {
GlobalObject.sActivity = activity;
}
public static Activity getActivity() {
return GlobalObject.sActivity;
}
}

View File

@ -0,0 +1,61 @@
/****************************************************************************
Copyright (c) 2018 Xiamen Yaji Software Co., Ltd.
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package com.cocos.lib;
import android.os.Build;
import android.view.View;
public class Utils {
public static void hideVirtualButton() {
if (Build.VERSION.SDK_INT >= 19 &&
null != GlobalObject.getActivity()) {
// use reflection to remove dependence of API level
Class viewClass = View.class;
final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = CocosReflectionHelper.<Integer>getConstantValue(viewClass, "SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION");
final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = CocosReflectionHelper.<Integer>getConstantValue(viewClass, "SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN");
final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = CocosReflectionHelper.<Integer>getConstantValue(viewClass, "SYSTEM_UI_FLAG_HIDE_NAVIGATION");
final int SYSTEM_UI_FLAG_FULLSCREEN = CocosReflectionHelper.<Integer>getConstantValue(viewClass, "SYSTEM_UI_FLAG_FULLSCREEN");
final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = CocosReflectionHelper.<Integer>getConstantValue(viewClass, "SYSTEM_UI_FLAG_IMMERSIVE_STICKY");
final int SYSTEM_UI_FLAG_LAYOUT_STABLE = CocosReflectionHelper.<Integer>getConstantValue(viewClass, "SYSTEM_UI_FLAG_LAYOUT_STABLE");
// getWindow().getDecorView().setSystemUiVisibility();
final Object[] parameters = new Object[]{SYSTEM_UI_FLAG_LAYOUT_STABLE
| SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
| SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
| SYSTEM_UI_FLAG_IMMERSIVE_STICKY};
////blank 注释掉才可以全屏显示到状态栏
/*
CocosReflectionHelper.<Void>invokeInstanceMethod(GlobalObject.getActivity().getWindow().getDecorView(),
"setSystemUiVisibility",
new Class[]{Integer.TYPE},
parameters);
*/
}
}
}

View File

@ -0,0 +1,57 @@
package cx;
import com.cocos.lib.CocosHelper;
import com.cocos.lib.CocosJavascriptJavaBridge;
import cx.mask.MaskIntf;
import cx.sys.SysIntf;
public class NativeIntf
{
public interface JsInterface
{
String call(NativeParams params);
}
private static JsInterface jsInterface = null;
public static void setJsIntf(JsInterface jsInterface)
{
NativeIntf.jsInterface = jsInterface;
}
public static String call(String classname, String fname, String params)
{
NativeParams nativeParams = new NativeParams(classname, fname, params.split("#@#"));
if (classname.equals("cx.sys"))
return SysIntf.ins().call(nativeParams);
if (classname.equals("cx.mask"))
return MaskIntf.ins().call(nativeParams);
if (jsInterface != null)
return jsInterface.call(nativeParams);
return "";
}
public static void callJs(final String classname, final int v1, final String v2)
{
CocosHelper.runOnGameThread(new Runnable()
{
@Override
public void run()
{
CocosJavascriptJavaBridge.evalString("cx.native.androidCallback('" + classname + "'," + v1 + ",'" + v2 + "')");
}
});
}
// CocosActivity.app.runOnUiThread(new Runnable()
// {
// @Override
// public void run()
// {
//
// }
// });
}

View File

@ -0,0 +1,58 @@
package cx;
public class NativeParams
{
public class NativeParam
{
private String param;
public NativeParam(String param)
{
this.param = param;
}
public String asString()
{
return param;
}
public int asInt()
{
return Integer.parseInt(param);
}
public float asFloat()
{
return Float.parseFloat(param);
}
public boolean asBool()
{
return Boolean.parseBoolean(param);
}
}
public String classname;
public String fname;
private String[] params;
public NativeParams(String classname, String fname, String[] params)
{
this.classname = classname;
this.fname = fname;
this.params = params;
}
public NativeParam at(int index)
{
return new NativeParam(params[index]);
}
@Override
public String toString()
{
String s = "";
for (int i=0; i<params.length; i++)
s += "," + params[i];
return s.isEmpty() ? s : s.substring(1);
}
}

View File

@ -0,0 +1,160 @@
package cx.mask;
import android.view.View;
import android.widget.FrameLayout;
import com.cocos.lib.CocosActivity;
import java.util.HashMap;
import cx.NativeParams;
public class MaskIntf
{
private static MaskIntf s_sharedMaskIntf = null;
public static MaskIntf ins()
{
if (s_sharedMaskIntf == null)
s_sharedMaskIntf = new MaskIntf();
return s_sharedMaskIntf;
}
public String call(NativeParams params)
{
CocosActivity.app.runOnUiThread(new Runnable()
{
@Override
public void run()
{
callInternal(params);
}
});
return "";
}
public String callInternal(NativeParams params)
{
String fname = params.fname;
String maskName = params.at(0).asString();
if (fname.equals("createMask"))
{
float rectX = params.at(1).asFloat();
float rectY = params.at(2).asFloat();
float rectW = params.at(3).asFloat();
float rectH = params.at(4).asFloat();
this.createMask(maskName, rectX, rectY, rectW, rectH);
}
else if (fname.equals("setMaskVisible"))
{
boolean visible = params.at(1).asBool();
this.setMaskVisible(maskName, visible);
}
else if (fname.equals("setMaskSize"))
{
float rectW = params.at(1).asFloat();
float rectH = params.at(2).asFloat();
this.setMaskSize(maskName, rectW, rectH);
}
else if (fname.equals("setMaskMask"))
{
float maskX = params.at(1).asFloat();
float maskY = params.at(2).asFloat();
float maskW = params.at(3).asFloat();
float maskH = params.at(4).asFloat();
float radius = params.at(5).asFloat();
this.setMaskMask(maskName, maskX, maskY, maskW, maskH, radius);
}
else if (fname.equals("clearMaskMask"))
{
this.clearMaskMask(maskName);
}
else if (fname.equals("removeMask"))
{
this.removeMask(maskName);
}
return "";
}
private HashMap<String, MaskView> maskMap = new HashMap<>();
public void createMask(String maskName, float rectX, float rectY, float rectW, float rectH)
{
if (!maskMap.containsKey(maskName))
{
MaskView maskView = new MaskView();
maskView.initFrame(Math.round(rectX), Math.round(rectY), Math.round(rectW), Math.round(rectH));
maskMap.put(maskName, maskView);
}
}
public void addNativeView(String maskName, View view, String viewTag, FrameLayout.LayoutParams params)
{
MaskView maskView = maskMap.get(maskName);
if (maskView != null)
{
view.setTag(viewTag);
maskView.contentView.addView(view, params);
}
}
public boolean hasNativeView(String maskName, String viewTag)
{
MaskView maskView = maskMap.get(maskName);
if (maskView != null)
{
int count = maskView.contentView.getChildCount();
for (int i=0; i<count; i++)
if (viewTag.equals(maskView.contentView.getChildAt(i).getTag()))
return true;
}
return false;
}
public void setMaskVisible(String maskName, boolean value)
{
MaskView maskView = maskMap.get(maskName);
if (maskView != null)
maskView.setMaskVisible(value);
}
public void setMaskSize(String maskName, float width, float height)
{
MaskView maskView = maskMap.get(maskName);
if (maskView != null)
maskView.setMaskSize(Math.round(width), Math.round(height));
}
public void removeMask(String maskName)
{
MaskView maskView = maskMap.get(maskName);
if (maskView != null)
{
maskView.remove();
maskMap.remove(maskView);
}
}
public void setMaskMask(String maskName, float maskX, float maskY, float maskW, float maskH, float radius)
{
MaskView maskView = maskMap.get(maskName);
if (maskView != null)
{
}
}
public void clearMaskMask(String maskName)
{
MaskView maskView = maskMap.get(maskName);
if (maskView != null)
{
}
}
}

View File

@ -0,0 +1,65 @@
package cx.mask;
import android.graphics.Point;
import android.view.View;
import android.widget.FrameLayout;
import com.cocos.lib.CocosActivity;
import cx.sys.SysIntf;
public class MaskView
{
public FrameLayout view;
public FrameLayout contentView;
private int viewWidth;
private int viewHeight;
public MaskView()
{
}
public void initFrame(final int rectX, final int rectY, final int rectW, final int rectH)
{
FrameLayout.LayoutParams lParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
lParams.leftMargin = rectX;
lParams.topMargin = rectY;
lParams.width = rectW;
lParams.height = rectH;
view = new FrameLayout(CocosActivity.app);
CocosActivity.app.getFrameLayout().addView(view, lParams);
// view.setBackgroundColor(Color.parseColor("#500000ff"));
Point screenSize = SysIntf.getScreenSize();
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
params.leftMargin = -rectX;
params.topMargin = -rectY;
params.width = screenSize.x;
params.height = screenSize.y;
contentView = new FrameLayout(CocosActivity.app);
view.addView(contentView, params);
// contentView.setBackgroundColor(Color.parseColor("#50ff0000"));
}
public void setMaskSize(int width, int height)
{
this.viewWidth = width;
this.viewHeight = height;
FrameLayout.LayoutParams lParams = (FrameLayout.LayoutParams) view.getLayoutParams();
lParams.width = viewWidth;
lParams.height = viewHeight;
view.setLayoutParams(lParams);
}
public void setMaskVisible(final boolean value)
{
view.setVisibility(value ? View.VISIBLE : View.INVISIBLE);
}
public void remove()
{
CocosActivity.app.getFrameLayout().removeView(view);
}
}

View File

@ -0,0 +1,112 @@
package cx.sys;
import android.graphics.Point;
import android.view.Display;
import android.view.View;
import com.cocos.lib.CocosActivity;
import cx.NativeParams;
public class SysIntf
{
private static SysIntf s_sharedSysIntf = null;
public static SysIntf ins()
{
if (s_sharedSysIntf == null)
s_sharedSysIntf = new SysIntf();
return s_sharedSysIntf;
}
private static Point screenSize = null;
public static Point getScreenSize()
{
if (screenSize != null)
return screenSize;
Display display = CocosActivity.app.getWindowManager().getDefaultDisplay();
screenSize = new Point();
display.getRealSize(screenSize);
return screenSize;
}
public String call(NativeParams params)
{
String fname = params.fname;
if (fname.equals("moveTaskToBack"))
this.moveTaskToBack();
else if (fname.equals("getPackageName"))
return this.getPackageName();
else if (fname.equals("getVersionCode"))
return this.getVersionCode();
else if (fname.equals("getVersionName"))
return this.getVersionName();
else if (fname.equals("removeLaunchImage"))
this.removeLaunchImage();
return "";
}
public void moveTaskToBack()
{
CocosActivity.app.moveTaskToBack(false);
}
public String getPackageName()
{
try
{
String packName = CocosActivity.app.getPackageName();
return String.valueOf(CocosActivity.app.getPackageManager().getPackageInfo(packName, 0).packageName);
}
catch (Exception e)
{
return "";
}
}
public String getVersionCode()
{
try
{
String packName = CocosActivity.app.getPackageName();
return String.valueOf(CocosActivity.app.getPackageManager().getPackageInfo(packName, 0).versionCode);
}
catch (Exception e)
{
return "";
}
}
public String getVersionName()
{
try
{
String packName = CocosActivity.app.getPackageName();
return CocosActivity.app.getPackageManager().getPackageInfo(packName, 0).versionName;
}
catch (Exception e)
{
return "";
}
}
public void removeLaunchImage()
{
View view = CocosActivity.app.getFrameLayout().findViewWithTag("launchImage");
if (view != null)
{
CocosActivity.app.runOnUiThread(new Runnable()
{
@Override
public void run()
{
CocosActivity.app.getFrameLayout().removeView(view);
}
});
}
}
}

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cx3.blank.so"
android:installLocation="auto">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.CALL_PHONE"/>
<uses-permission android:name="android.permission.CAMERA"/>
<application
android:allowBackup="true"
android:usesCleartextTraffic="true">
<meta-data android:name="android.app.lib_name"
android:value="cocos" />
<meta-data android:name="com.amap.api.v2.apikey" android:value="94f84f93c7305329b9ebe12f761dbbac"/>
<activity
android:name=".AppActivity"
android:screenOrientation="portrait"
android:configChanges="orientation|keyboardHidden|screenSize|screenLayout"
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>
</application>
</manifest>

View File

@ -0,0 +1,81 @@
apply plugin: 'com.android.application'
RES_PATH = RES_PATH.replace("\\", "/")
COCOS_ENGINE_PATH = COCOS_ENGINE_PATH.replace("\\", "/")
buildDir = "${RES_PATH}/build/$project.name"
android {
compileSdkVersion PROP_COMPILE_SDK_VERSION.toInteger()
buildToolsVersion PROP_BUILD_TOOLS_VERSION
// ndkPath PROP_NDK_PATH
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
applicationId APPLICATION_ID
minSdkVersion PROP_MIN_SDK_VERSION
targetSdkVersion PROP_TARGET_SDK_VERSION
versionCode 1
versionName "1.0"
externalNativeBuild {
cmake {
targets "cocos"
arguments "-DRES_DIR=${RES_PATH}", "-DCOCOS_X_PATH=${COCOS_ENGINE_PATH}", "-DANDROID_STL=c++_static", "-DANDROID_TOOLCHAIN=clang", "-DANDROID_ARM_NEON=TRUE", "-DANDROID_LD=gold"
cppFlags "-frtti -fexceptions -fsigned-char"
}
ndk { abiFilters PROP_APP_ABI.split(':') }
}
}
externalNativeBuild {
cmake {
path "../engine/CMakeLists.txt"
buildStagingDirectory "${RES_PATH}/build"
}
}
sourceSets.main {
manifest.srcFile "AndroidManifest.xml"
java.srcDirs "src"
jniLibs.srcDirs = ["libs"]
}
signingConfigs {
release {
if (project.hasProperty("RELEASE_STORE_FILE")) {
storeFile file(RELEASE_STORE_FILE)
storePassword RELEASE_STORE_PASSWORD
keyAlias RELEASE_KEY_ALIAS
keyPassword RELEASE_KEY_PASSWORD
}
}
}
buildTypes {
release {
debuggable false
jniDebuggable false
renderscriptDebuggable false
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
if (project.hasProperty("RELEASE_STORE_FILE")) {
signingConfig signingConfigs.release
}
}
debug {
debuggable true
jniDebuggable true
renderscriptDebuggable true
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar','*.aar'])
}

View File

@ -0,0 +1,40 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in E:\developSoftware\Android\SDK/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Proguard Cocos2d-x-lite for release
-keep public class com.cocos.** { *; }
-dontwarn com.cocos.**
# Proguard Apache HTTP for release
-keep class org.apache.http.** { *; }
-dontwarn org.apache.http.**
# Proguard okhttp for release
-keep class okhttp3.** { *; }
-dontwarn okhttp3.**
-keep class okio.** { *; }
-dontwarn okio.**
# Proguard Android Webivew for release. you can comment if you are not using a webview
-keep public class android.net.http.SslError
-keep public class android.webkit.WebViewClient
-dontwarn android.webkit.WebView
-dontwarn android.net.http.SslError
-dontwarn android.webkit.WebViewClient

View File

@ -0,0 +1,9 @@
package cx3.blank.so;
import android.app.Activity;
public class AppActivity extends Activity
{
}

View File

@ -0,0 +1,28 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}

View File

@ -0,0 +1,53 @@
cmake_minimum_required(VERSION 3.8)
option(APP_NAME "Project Name" "cx3-so")
project(${APP_NAME} CXX)
include(${CMAKE_CURRENT_LIST_DIR}/common/CMakeLists.txt)
set(LIB_NAME cocos)
set(PROJ_SOURCES
${CMAKE_CURRENT_LIST_DIR}/../../../cx-native/cxCreator.h
${CMAKE_CURRENT_LIST_DIR}/../../../cx-native/cxCreator.cpp
${CMAKE_CURRENT_LIST_DIR}/../../../cx-native/cxDefine.h
${CMAKE_CURRENT_LIST_DIR}/../../../cx-native/cxIntf.h
${CMAKE_CURRENT_LIST_DIR}/../../../cx-native/cxIntf.cpp
${CMAKE_CURRENT_LIST_DIR}/../../../cx-native/cxJsb.hpp
${CMAKE_CURRENT_LIST_DIR}/../../../cx-native/cxJsb.cpp
${CMAKE_CURRENT_LIST_DIR}/../../../cx-native/Game.h
${CMAKE_CURRENT_LIST_DIR}/../../../cx-native/Game.cpp
${CMAKE_CURRENT_LIST_DIR}/../../../cx-native/jsb_module_register.cpp
${CMAKE_CURRENT_LIST_DIR}/jni/main.cpp
)
# -------------- SRART ---------------
# USED BY COCOS SERVICE, DON'T REMOVE!
if(EXISTS ${RES_DIR}/service.cmake)
set(SERVICE_NATIVE_DIR ${CMAKE_CURRENT_LIST_DIR})
include(${RES_DIR}/service.cmake)
endif()
# -------------- END ----------------
#list(APPEND PROJ_SOURCES
# ${CMAKE_CURRENT_LIST_DIR}/../../../cx-native/jsb_module_register.cpp
#)
add_library(${LIB_NAME} SHARED ${PROJ_SOURCES})
# -------------- SRART ---------------
# USED BY COCOS SERVICE, DON'T REMOVE!
if(COMMAND service_insert_library)
service_insert_library()
endif()
# -------------- END ----------------
target_link_libraries(${LIB_NAME}
"-Wl,--whole-archive" cocos2d_jni "-Wl,--no-whole-archive"
cocos2d
)
target_include_directories(${LIB_NAME} PRIVATE
${CMAKE_CURRENT_LIST_DIR}/../../../cx-native
)

View File

@ -0,0 +1,8 @@
{
"ndk_module_path" :[
"${COCOS_ROOT}",
"${COCOS_ROOT}/cocos",
"${COCOS_ROOT}/external"
],
"copy_resources": []
}

View File

@ -0,0 +1,13 @@
set(CC_USE_GLES3 ON)
set(CC_USE_GLES2 ON)
set(APP_NAME cx3-so)
set(COCOS_X_PATH "/Applications/CocosCreator/Creator/3.1.1/CocosCreator.app/Contents/Resources/resources/3d/engine-native")
set(CC_USE_VULKAN OFF)
set(USE_PHYSICS_PHYSX OFF)
set(USE_AUDIO ON)
set(USE_VIDEO ON)
set(USE_WEBVIEW ON)
set(USE_SPINE OFF)
set(USE_DRAGONBONES ON)
set(USE_JOB_SYSTEM_TBB ON)

View File

@ -0,0 +1,64 @@
enable_language(C ASM)
set(DEVELOPMENT_TEAM "" CACHE STRING "APPLE Developtment Team")
set(RES_DIR "" CACHE STRING "Resource path")
set(COCOS_X_PATH "" CACHE STRING "Path to cocos2d-x-lite/")
set(TARGET_OSX_VERSION "10.14" CACHE STRING "Target MacOSX version" FORCE)
set(TARGET_IOS_VERSION "12.0" CACHE STRING "Target iOS version" FORCE)
set(CMAKE_CXX_STANDARD 14)
option(USE_SE_V8 "Use V8 JavaScript Engine" ON)
option(USE_V8_DEBUGGER "Enable Chrome Remote inspector" OFF)
option(USE_SOCKET "Enable WebSocket & SocketIO" OFF)
option(USE_AUDIO "Enable Audio" ON) #Enable AudioEngine
option(USE_EDIT_BOX "Enable EditBox" ON)
option(USE_SE_JSC "Use JavaScriptCore on MacOSX/iOS" OFF)
option(USE_VIDEO "Enable VideoPlayer Component" ON)
option(USE_WEBVIEW "Enable WebView Component" ON)
option(USE_MIDDLEWARE "Enable Middleware" ON)
option(USE_DRAGONBONES "Enable Dragonbones" ON)
option(USE_SPINE "Enable Spine" OFF)
option(USE_WEBSOCKET_SERVER "Enable WebSocket Server" OFF)
option(USE_JOB_SYSTEM_TASKFLOW "Use taskflow as job system backend" OFF)
option(USE_JOB_SYSTEM_TBB "Use tbb as job system backend" OFF)
option(USE_PHYSICS_PHYSX "USE PhysX Physics" OFF)
if(NOT RES_DIR)
message(FATAL_ERROR "RES_DIR is not set!")
endif()
include(${RES_DIR}/engine/cfg.cmake)
if(NOT COCOS_X_PATH)
message(FATAL_ERROR "COCOS_X_PATH is not set!")
endif()
include(${COCOS_X_PATH}/CMakeLists.txt)
set(ASSET_FILES)
macro(include_resources ARG_RES_ROOT)
foreach(res ${ARG_RES_ROOT})
set(res_list)
if(NOT EXISTS ${res})
continue()
endif()
if(IS_DIRECTORY ${res})
file(GLOB_RECURSE res_list "${res}/*")
else()
set(res_list ${res})
endif()
foreach(res ${res_list})
get_filename_component(res_abs ${res} ABSOLUTE)
file(RELATIVE_PATH res_rel ${ARG_RES_ROOT} ${res_abs})
get_filename_component(res_dir ${res_rel} PATH)
set_source_files_properties(${res_abs} PROPERTIES
MACOSX_PACKAGE_LOCATION "Resources/${res_dir}/"
HEADER_FILE_ONLY 1
)
list(APPEND ASSET_FILES ${res_abs})
endforeach()
endforeach()
endmacro()

View File

@ -0,0 +1,29 @@
/****************************************************************************
Copyright (c) 2017-2020 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "Game.h"
cc::Application *cocos_main(int width, int height) {
return new Game(width, height);
}

View File

@ -0,0 +1,38 @@
# Project-wide Gradle settings.
android.injected.testOnly=false
# Android SDK version that will be used as the compile project
PROP_COMPILE_SDK_VERSION=28
# Android SDK version that will be used as the earliest version of android this application can run on
PROP_MIN_SDK_VERSION=21
# Android SDK version that will be used as the latest version of android this application has been tested on
PROP_TARGET_SDK_VERSION=27
# Android Build Tools version that will be used as the compile project
PROP_BUILD_TOOLS_VERSION=28.0.2
PROP_NDK_PATH=/Users/blank/Library/Android/sdk/ndk-bundle
# Cocos Engine Path
COCOS_ENGINE_PATH=/Applications/CocosCreator/Creator/3.1.1/CocosCreator.app/Contents/Resources/resources/3d/engine-native
# Res path
RES_PATH=/Users/blank/ccapp3/cx-framework3.1/cocos3-libs/cocos3-libso
# Application ID
APPLICATION_ID=cx3.blank.so
# List of CPU Archtexture to build that application with
# Available architextures (armeabi-v7a | arm64-v8a | x86)
# To build for multiple architexture, use the `:` between them
# Example - PROP_APP_ABI=armeabi-v7a
#PROP_APP_ABI=armeabi-v7a:x86_64
PROP_APP_ABI=armeabi-v7a
RELEASE_STORE_FILE=/Applications/CocosCreator/Creator/3.1.1/CocosCreator.app/Contents/Resources/tools/keystore/debug.keystore
RELEASE_STORE_PASSWORD=123456
RELEASE_KEY_ALIAS=debug_keystore
RELEASE_KEY_PASSWORD=123456

View File

@ -0,0 +1,6 @@
#Wed May 05 22:20:29 CST 2021
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-all.zip

View File

@ -0,0 +1,164 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

View File

@ -0,0 +1,90 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@ -0,0 +1,9 @@
## This file must *NOT* be checked into Version Control Systems,
# as it contains information specific to your local configuration.
#
# Location of the SDK. This is only used by Gradle.
# For customization when using a Version Control System, please read the
# header note.
#Wed May 05 22:19:02 CST 2021
ndk.dir=/Users/blank/Library/Android/sdk/ndk-bundle
sdk.dir=/Users/blank/Library/Android/sdk

View File

@ -0,0 +1 @@
include ':app'

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:/Users/blank/ccapp3/cx-framework3.1/cocos3-libs/cocos3-mac.xcodeproj">
</FileRef>
</Workspace>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BuildSystemType</key>
<string>Latest</string>
<key>DisableBuildSystemDeprecationWarning</key>
<true/>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BuildLocationStyle</key>
<string>UseAppPreferences</string>
<key>CustomBuildIntermediatesPath</key>
<string>Build/Intermediates.noindex</string>
<key>CustomBuildLocationType</key>
<string>RelativeToDerivedData</string>
<key>CustomBuildProductsPath</key>
<string>Build/Products</string>
<key>DerivedDataLocationStyle</key>
<string>Default</string>
<key>IssueFilterStyle</key>
<string>ShowActiveSchemeOnly</string>
<key>LiveSourceIssuesEnabled</key>
<true/>
<key>ShowSharedSchemesAutomaticallyEnabled</key>
<true/>
</dict>
</plist>

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1240"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "46916FCB264D6D28000C7B53"
BuildableName = "libcocos3 Mac.a"
BlueprintName = "cocos3 Mac"
ReferencedContainer = "container:cocos3-mac.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "46916FCB264D6D28000C7B53"
BuildableName = "libcocos3 Mac.a"
BlueprintName = "cocos3 Mac"
ReferencedContainer = "container:cocos3-mac.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Bucket
uuid = "ABE5CDBB-B2EC-4486-A952-379CAA2C5C0A"
type = "1"
version = "2.0">
</Bucket>

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>ALL_BUILD.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>1</integer>
</dict>
<key>ZERO_CHECK.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>2</integer>
</dict>
<key>cocos3 Mac.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>1</integer>
</dict>
<key>cx3-demo-desktop.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>0</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
<dict>
<key>46916FCB264D6D28000C7B53</key>
<dict>
<key>primary</key>
<true/>
</dict>
<key>E77C5DADC6FB43A28EC868C1</key>
<dict>
<key>primary</key>
<true/>
</dict>
</dict>
</dict>
</plist>

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,101 @@
/****************************************************************************
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "Game.h"
#include "cocos/bindings/event/CustomEventTypes.h"
#include "cocos/bindings/event/EventDispatcher.h"
#include "cocos/bindings/jswrapper/SeApi.h"
#include "cocos/bindings/manual/jsb_classtype.h"
#include "cocos/bindings/manual/jsb_global.h"
#include "cocos/bindings/manual/jsb_module_register.h"
#if (CC_PLATFORM == CC_PLATFORM_MAC_IOS)
#include "platform/Device.h"
#endif
////blank
#include "cxJsb.hpp"
Game::Game(int width, int height) : cc::Application(width, height) {}
bool Game::init()
{
cc::Application::init();
se::ScriptEngine *se = se::ScriptEngine::getInstance();
jsb_set_xxtea_key("");
jsb_init_file_operation_delegate();
#if defined(CC_DEBUG) && (CC_DEBUG > 0)
// Enable debugger here
jsb_enable_debugger("0.0.0.0", 6086, false);
#endif
se->setExceptionCallback([](const char *location, const char *message, const char *stack) {
// Send exception information to server like Tencent Bugly.
CC_LOG_ERROR("\nUncaught Exception:\n - location : %s\n - msg : %s\n - detail : \n %s\n", location, message, stack);
});
se->addRegisterCallback(register_all_cx);
jsb_register_all_modules();
se->start();
se::AutoHandleScope hs;
jsb_run_script("jsb-adapter/jsb-builtin.js");
jsb_run_script("boot.js");
se->addAfterCleanupHook([]() {
JSBClassType::destroy();
});
#if (CC_PLATFORM == CC_PLATFORM_MAC_IOS)
cc::Vec2 logicSize = getViewLogicalSize();
float pixelRatio = cc::Device::getDevicePixelRatio();
cc::EventDispatcher::dispatchResizeEvent(logicSize.x * pixelRatio, logicSize.y * pixelRatio);
#endif
return true;
}
void Game::onPause()
{
cc::Application::onPause();
cc::CustomEvent event;
event.name = EVENT_COME_TO_BACKGROUND;
cc::EventDispatcher::dispatchCustomEvent(event);
cc::EventDispatcher::dispatchEnterBackgroundEvent();
}
void Game::onResume()
{
cc::Application::onResume();
cc::CustomEvent event;
event.name = EVENT_COME_TO_FOREGROUND;
cc::EventDispatcher::dispatchCustomEvent(event);
cc::EventDispatcher::dispatchEnterForegroundEvent();
}

View File

@ -0,0 +1,43 @@
/****************************************************************************
Copyright (c) 2018 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "platform/Application.h"
/**
@brief The cocos2d Application.
The reason for implement as private inheritance is to hide some interface call by Director.
*/
class Game : public cc::Application
{
public:
/**
* width and height in logical pixel unit
*/
Game(int width, int height);
virtual bool init() override;
virtual void onPause() override;
virtual void onResume() override;
};

View File

@ -0,0 +1,36 @@
#include "cxCreator.h"
#include "cxIntf.h"
#if CC_PLATFORM == CC_PLATFORM_MAC_IOS
#include "cxMask/cxMaskIntf.h"
#endif
#if CC_PLATFORM != CC_PLATFORM_ANDROID
#include "cxSys/cxSysIntf.h"
#endif
NativeIntfClass* NativeCreator::createNativeClass(std::string classname)
{
if (classname == "cx")
return CxIntf::ins();
#if CC_PLATFORM == CC_PLATFORM_MAC_IOS
if (classname == "cx.mask")
return CxMaskIntf::ins();
#endif
#if CC_PLATFORM != CC_PLATFORM_ANDROID
if (classname == "cx.sys")
return CxSysIntf::ins();
return createAppNativeClass(classname);
#endif
return nullptr;
}

View File

@ -0,0 +1,15 @@
#pragma once
#include "cxDefine.h"
#if CC_PLATFORM != CC_PLATFORM_ANDROID
extern NativeIntfClass* createAppNativeClass(std::string classname);
#endif
class NativeCreator
{
public:
static NativeIntfClass* createNativeClass(std::string classname);
};

View File

@ -0,0 +1,13 @@
#pragma once
#include "cocos/base/Value.h"
typedef std::function<void(int v1, std::string v2)> DataCallback;
class NativeIntfClass
{
public:
virtual std::string call(std::string fname, cc::ValueVector params, const DataCallback& callback){ return nullptr; };
};

View File

@ -0,0 +1,23 @@
#include "cxIntf.h"
DataCallback CxIntf::m_cxCallback = NULL;
static CxIntf* s_sharedCxIntf = nullptr;
CxIntf* CxIntf::ins()
{
if (!s_sharedCxIntf)
s_sharedCxIntf = new CxIntf();
return s_sharedCxIntf;
}
std::string CxIntf::call(std::string fname, cc::ValueVector params, const DataCallback& callback)
{
if (fname == "encode" || fname == "decode" || fname == "md5")
return params.at(0).asString();
return "";
}

View File

@ -0,0 +1,20 @@
#pragma once
#include "cocos/base/Value.h"
#include "cxDefine.h"
class CxIntf : public NativeIntfClass
{
public:
static CxIntf* ins();
virtual std::string call(std::string fname, cc::ValueVector params, const DataCallback& callback) override;
static DataCallback m_cxCallback;
private:
};

View File

@ -0,0 +1,228 @@
#include "cxJsb.hpp"
#include "cocos/bindings/manual/jsb_conversions.h"
#include "cocos/bindings/manual/jsb_global.h"
#include "platform/FileUtils.h"
#include "cxCreator.h"
se::Object* __jsb_NativeCreator_proto = nullptr;
se::Class* __jsb_NativeCreator_class = nullptr;
//***********************************
//NativeCreator
//***********************************
static bool js_cx_NativeCreator_createNativeClass(se::State& s)
{
const auto& args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc == 1) {
std::string arg0;
ok &= seval_to_std_string(args[0], &arg0);
SE_PRECONDITION2(ok, false, "js_cx_NativeCreator_createNativeClass : Error processing arguments");
NativeIntfClass* result = NativeCreator::createNativeClass(arg0);
ok &= native_ptr_to_seval<NativeIntfClass>((NativeIntfClass*)result, &s.rval());
SE_PRECONDITION2(ok, false, "js_cx_NativeCreator_createNativeClass : Error processing arguments");
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(js_cx_NativeCreator_createNativeClass)
static bool js_NativeCreator_finalize(se::State& s)
{
// SE_LOGD("jsbindings: finalizing JS object %p (NativeCreator)", s.nativeThisObject());
auto iter = se::NonRefNativePtrCreatedByCtorMap::find(s.nativeThisObject());
if (iter != se::NonRefNativePtrCreatedByCtorMap::end())
{
se::NonRefNativePtrCreatedByCtorMap::erase(iter);
NativeCreator* cobj = (NativeCreator*)s.nativeThisObject();
delete cobj;
}
return true;
}
SE_BIND_FINALIZE_FUNC(js_NativeCreator_finalize)
bool js_register_cx_NativeCreator(se::Object* obj)
{
auto cls = se::Class::create("NativeCreator", obj, nullptr, nullptr);
cls->defineStaticFunction("createNativeClass", _SE(js_cx_NativeCreator_createNativeClass));
cls->defineFinalizeFunction(_SE(js_NativeCreator_finalize));
cls->install();
JSBClassType::registerClass<NativeCreator>(cls);
__jsb_NativeCreator_proto = cls->getProto();
__jsb_NativeCreator_class = cls;
se::ScriptEngine::getInstance()->clearException();
return true;
}
//***********************************
//NativeIntfClass
//***********************************
se::Object* __jsb_NativeIntfClass_proto = nullptr;
se::Class* __jsb_NativeIntfClass_class = nullptr;
static bool js_cx_NativeIntfClass_call(se::State& s)
{
const auto& args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
std::string arg0;
cc::ValueVector arg1;
std::function<void (int, std::string)> arg2 = nullptr;
if (argc >= 1)
{
ok &= seval_to_std_string(args[0], &arg0);
}
if (argc >= 2)
{
ok &= seval_to_std_string(args[0], &arg0);
ok &= seval_to_ccvaluevector(args[1], &arg1);
}
if (ok && argc == 3)
{
if (args[2].isObject() && args[2].toObject()->isFunction())
{
se::Value jsThis(s.thisObject());
se::Value jsFunc(args[2]);
//https://docs.cocos.com/creator/manual/zh/advanced-topics/JSB2.0-learning.html
//如果当前类是一个单例类,或者永远只有一个实例的类,我们不能用 se::Object::attachObject 去关联, 必须使用 se::Object::root
//jsThis.toObject()->attachObject(jsFunc.toObject());
jsFunc.toObject()->root();
jsThis.toObject()->root();
auto lambda = [=](int larg0, std::string larg1) -> void
{
se::ScriptEngine::getInstance()->clearException();
se::AutoHandleScope hs;
CC_UNUSED bool ok = true;
se::ValueArray args;
args.resize(2);
ok &= int32_to_seval(larg0, &args[0]);
ok &= std_string_to_seval(larg1, &args[1]);
se::Value rval;
se::Object* thisObj = jsThis.isObject() ? jsThis.toObject() : nullptr;
se::Object* funcObj = jsFunc.toObject();
bool succeed = funcObj->call(args, thisObj, &rval);
if (!succeed)
{
se::ScriptEngine::getInstance()->clearException();
}
};
arg2 = lambda;
}
}
SE_PRECONDITION2(ok, false, "js_cx_NativeIntfClass_func : Error processing arguments");
if (ok)
{
NativeIntfClass* cobj = (NativeIntfClass*)s.nativeThisObject();
std::string result = cobj->call(arg0, arg1, arg2);
std_string_to_seval(result, &s.rval());
return true;
}
return false;
}
SE_BIND_FUNC(js_cx_NativeIntfClass_call)
static bool js_NativeIntfClass_finalize(se::State& s)
{
// SE_LOGD("jsbindings: finalizing JS object %p (NativeCreator)", s.nativeThisObject());
auto iter = se::NonRefNativePtrCreatedByCtorMap::find(s.nativeThisObject());
if (iter != se::NonRefNativePtrCreatedByCtorMap::end())
{
se::NonRefNativePtrCreatedByCtorMap::erase(iter);
NativeIntfClass* cobj = (NativeIntfClass*)s.nativeThisObject();
delete cobj;
}
return true;
}
SE_BIND_FINALIZE_FUNC(js_NativeIntfClass_finalize)
bool js_register_cx_NativeIntfClass(se::Object* obj)
{
auto cls = se::Class::create("NativeIntfClass", obj, nullptr, nullptr);
cls->defineFunction("call", _SE(js_cx_NativeIntfClass_call));
cls->defineFinalizeFunction(_SE(js_NativeIntfClass_finalize));
cls->install();
JSBClassType::registerClass<NativeIntfClass>(cls);
__jsb_NativeIntfClass_proto = cls->getProto();
__jsb_NativeIntfClass_class = cls;
se::ScriptEngine::getInstance()->clearException();
return true;
}
//***********************************
//NativeUtils
//***********************************
se::Object* __jsb_NativeUtils_proto = nullptr;
se::Class* __jsb_NativeUtils_class = nullptr;
static bool js_cx_NativeUtils_writeDataToFile(se::State& s)
{
const auto& args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc == 2) {
cc::Data arg0;
std::string arg1;
ok &= seval_to_Data(args[0], &arg0);
ok &= seval_to_std_string(args[1], &arg1);
SE_PRECONDITION2(ok, false, "js_engine_FileUtils_writeDataToFile : Error processing arguments");
bool result = cc::FileUtils::getInstance()->writeDataToFile(arg0, arg1);
ok &= boolean_to_seval(result, &s.rval());
SE_PRECONDITION2(ok, false, "js_engine_FileUtils_writeDataToFile : Error processing result");
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 2);
return false;
}
SE_BIND_FUNC(js_cx_NativeUtils_writeDataToFile)
bool js_register_cx_NativeUtils(se::Object* obj)
{
auto cls = se::Class::create("NativeUtils", obj, nullptr, nullptr);
cls->defineStaticFunction("writeDataToFile", _SE(js_cx_NativeUtils_writeDataToFile));
cls->install();
__jsb_NativeUtils_proto = cls->getProto();
__jsb_NativeUtils_class = cls;
se::ScriptEngine::getInstance()->clearException();
return true;
}
//***********************************
//register
//***********************************
bool register_all_cx(se::Object* obj)
{
// Get the ns
se::Value nsVal;
if (!obj->getProperty("cxnative", &nsVal))
{
se::HandleObject jsobj(se::Object::createPlainObject());
nsVal.setObject(jsobj);
obj->setProperty("cxnative", nsVal);
}
se::Object* ns = nsVal.toObject();
js_register_cx_NativeCreator(ns);
js_register_cx_NativeIntfClass(ns);
js_register_cx_NativeUtils(ns);
return true;
}

View File

@ -0,0 +1,11 @@
#pragma once
#include "cocos/bindings/jswrapper/SeApi.h"
extern se::Object* __jsb_NativeCreator_proto;
extern se::Class* __jsb_NativeCreator_class;
bool js_register_NativeCreator(se::Object* obj);
bool register_all_cx(se::Object* obj);
SE_DECLARE_FUNC(js_cx_NativeCreator_createNativeClass);

View File

@ -0,0 +1,20 @@
#pragma once
#include "cxDefine.h"
class CxMaskIntf : public NativeIntfClass
{
public:
static CxMaskIntf* ins();
virtual std::string call(std::string fname, cc::ValueVector params, const DataCallback& callback) override;
void addNativeView(std::string maskName, void* view);
bool hasNativeView(std::string maskName, void* view);
private:
};

View File

@ -0,0 +1,127 @@
#include "cxMaskIntf.h"
#include "AppController.h"
#include "cxMaskView.h"
std::unordered_map<std::string, CxMaskView*> m_maskViewList;
CxMaskView* getMaskView(std::string name)
{
auto itr = m_maskViewList.find(name);
if (itr != m_maskViewList.end())
return itr->second;
return nullptr;
}
static CxMaskIntf* s_sharedCxMaskIntf = nullptr;
CxMaskIntf* CxMaskIntf::ins()
{
if (!s_sharedCxMaskIntf)
s_sharedCxMaskIntf = new CxMaskIntf();
return s_sharedCxMaskIntf;
}
std::string CxMaskIntf::call(std::string fname, cc::ValueVector params, const DataCallback& callback)
{
if (fname == "createMask")
{
std::string name = params.at(0).asString();
float rectX = params.at(1).asFloat();
float rectY = params.at(2).asFloat();
float rectW = params.at(3).asFloat();
float rectH = params.at(4).asFloat();
if (getMaskView(name))
return "";
CxMaskView* maskView = [[CxMaskView alloc] initWithFrame:CGRectMake(rectX, rectY, rectW, rectH)];
//maskView.contentView.backgroundColor = [UIColor colorWithRed:100 green:0 blue:0 alpha:0.4];
[[AppController ins] addView:maskView];
m_maskViewList.emplace(name, maskView);
}
else if (fname == "setMaskVisible")
{
std::string name = params.at(0).asString();
bool visible = params.at(1).asBool();
auto maskView = getMaskView(name);
if (maskView)
[maskView setHidden:!visible];
}
else if (fname == "setMaskSize")
{
std::string name = params.at(0).asString();
float rectW = params.at(1).asFloat();
float rectH = params.at(2).asFloat();
auto maskView = getMaskView(name);
if (maskView)
maskView.frame = CGRectMake(maskView.frame.origin.x, maskView.frame.origin.y, rectW, rectH);
}
else if (fname == "setMaskMask")
{
std::string name = params.at(0).asString();
auto maskView = getMaskView(name);
if (maskView)
{
float maskX = params.at(1).asFloat();
float maskY = params.at(2).asFloat();
float maskW = params.at(3).asFloat();
float maskH = params.at(4).asFloat();
float radius = params.at(5).asFloat();
UIBezierPath* path = [UIBezierPath bezierPathWithRect:maskView.contentView.bounds];
UIBezierPath* round = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(maskX, maskY, maskW, maskH) cornerRadius:radius];
CAShapeLayer* maskLayer = [CAShapeLayer layer];
[path appendPath:round];
maskLayer.path = [path CGPath];
maskLayer.fillRule = kCAFillRuleEvenOdd;
maskView.contentView.layer.mask = maskLayer;
}
}
else if (fname == "clearMaskMask")
{
std::string name = params.at(0).asString();
auto maskView = getMaskView(name);
if (maskView)
maskView.contentView.layer.mask = nil;
}
else if (fname == "removeMask")
{
std::string name = params.at(0).asString();
auto maskView = getMaskView(name);
if (maskView)
{
[maskView removeFromSuperview];
m_maskViewList.erase(name);
}
}
return "";
}
void CxMaskIntf::addNativeView(std::string maskName, void* view)
{
auto maskView = getMaskView(maskName);
if (maskView)
[maskView.contentView addSubview:(UIView*)view];
}
bool CxMaskIntf::hasNativeView(std::string maskName, void* view)
{
auto maskView = getMaskView(maskName);
if (maskView)
{
for (UIView* subview in maskView.contentView.subviews)
{
if (subview == view)
return true;
}
}
return false;
}

View File

@ -0,0 +1,9 @@
#import <UIKit/UIKit.h>
@interface CxMaskView : UIView
@property (strong, nonatomic) UIView* contentView;
@end

View File

@ -0,0 +1,25 @@
#import "cxMaskView.h"
#define pop_height 200
#define RGBCOLOR(r,g,b) [UIColor colorWithRed:(r)/255.0f green:(g)/255.0f blue:(b)/255.0f alpha:1]
@implementation CxMaskView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
self.userInteractionEnabled = false;
self.clipsToBounds = true;
CGSize screen = [[UIScreen mainScreen] bounds].size;
self.contentView = [[UIView alloc] initWithFrame:CGRectMake(-frame.origin.x, -frame.origin.y, screen.width, screen.height)];
self.contentView.userInteractionEnabled = false;
[self addSubview:self.contentView];
return self;
}
@end

View File

@ -0,0 +1,23 @@
#pragma once
#include "cxDefine.h"
#include "cocos/bindings/event/EventDispatcher.h"
class CxSysIntf : public NativeIntfClass
{
public:
static CxSysIntf* ins();
virtual std::string call(std::string fname, cc::ValueVector params, const DataCallback& callback) override;
static DataCallback m_cxSysCallback;
private:
void restartForUpdate(cc::CustomEvent evt);
};

View File

@ -0,0 +1,70 @@
#include "cxSysIntf.h"
#include "AppController.h"
#include "platform/Application.h"
#include "cocos/bindings/event/CustomEventTypes.h"
DataCallback CxSysIntf::m_cxSysCallback = NULL;
static CxSysIntf* s_sharedCxSysIntf = nullptr;
CxSysIntf* CxSysIntf::ins()
{
if (!s_sharedCxSysIntf)
s_sharedCxSysIntf = new CxSysIntf();
return s_sharedCxSysIntf;
}
std::string CxSysIntf::call(std::string fname, cc::ValueVector params, const DataCallback& callback)
{
if (fname == "getStoragePath")
{
#if (CC_PLATFORM == CC_PLATFORM_MAC_IOS)
return "";
#endif
return call("getPackageName", params, callback);
}
if (fname == "getPackageName")
{
NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
NSString* packageName = [infoDictionary objectForKey:@"CFBundleIdentifier"];
return [packageName UTF8String];
}
if (fname == "getVersionCode")
{
return [[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"] UTF8String];
}
if (fname == "getVersionName")
{
return [[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"] UTF8String];
}
if (fname == "removeLaunchImage")
{
[[AppController ins] removeLaunchImage];
return "";
}
//只供在main.js中且是ios时调用这个方法
if (fname == "restartForUpdate")
{
//ios弹出网络授权时应用会进入后台点击后回到前台侦听回到前台时重启
cc::EventDispatcher::addCustomEventListener(EVENT_COME_TO_FOREGROUND, CC_CALLBACK_1(CxSysIntf::restartForUpdate, this));
return "";
}
return "";
}
void CxSysIntf::restartForUpdate(cc::CustomEvent evt)
{
if (evt.name == EVENT_COME_TO_FOREGROUND)
{
cc::EventDispatcher::removeAllCustomEventListeners(EVENT_COME_TO_FOREGROUND);
cc::Application::getInstance()->restart();
}
}

View File

@ -0,0 +1,187 @@
/****************************************************************************
Copyright (c) 2017-2021 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "cocos/bindings/jswrapper/SeApi.h"
#include "cocos/bindings/manual/jsb_module_register.h"
#include "cocos/bindings/auto/jsb_cocos_auto.h"
#include "cocos/base/AutoreleasePool.h"
#include "cocos/bindings/dop/jsb_dop.h"
#include "cocos/bindings/auto/jsb_extension_auto.h"
#include "cocos/bindings/auto/jsb_network_auto.h"
#include "cocos/bindings/auto/jsb_gfx_auto.h"
#include "cocos/bindings/auto/jsb_pipeline_auto.h"
#include "cocos/bindings/manual/jsb_pipeline_manual.h"
#include "cocos/bindings/manual/jsb_cocos_manual.h"
#include "cocos/bindings/manual/jsb_network_manual.h"
#include "cocos/bindings/manual/jsb_conversions.h"
#include "cocos/bindings/manual/jsb_gfx_manual.h"
#include "cocos/bindings/manual/jsb_global.h"
#include "cocos/bindings/manual/jsb_platform.h"
#include "cocos/bindings/manual/jsb_xmlhttprequest.h"
#if USE_GFX_RENDERER
#endif
#if USE_SOCKET
#include "cocos/bindings/manual/jsb_socketio.h"
#include "cocos/bindings/manual/jsb_websocket.h"
#endif // USE_SOCKET
#if USE_AUDIO
#include "cocos/bindings/auto/jsb_audio_auto.h"
#endif
#if (CC_PLATFORM == CC_PLATFORM_MAC_IOS || CC_PLATFORM == CC_PLATFORM_MAC_OSX)
#include "cocos/bindings/manual/JavaScriptObjCBridge.h"
#endif
#if (CC_PLATFORM == CC_PLATFORM_ANDROID)
#include "cocos/bindings/manual/JavaScriptJavaBridge.h"
#endif
#if (CC_PLATFORM == CC_PLATFORM_MAC_IOS || CC_PLATFORM == CC_PLATFORM_ANDROID)
#if USE_VIDEO
#include "cocos/bindings/auto/jsb_video_auto.h"
#endif
#if USE_WEBVIEW
#include "cocos/bindings/auto/jsb_webview_auto.h"
#endif
#endif // (CC_PLATFORM == CC_PLATFORM_MAC_IOS || CC_PLATFORM == CC_PLATFORM_ANDROID)
#if USE_SOCKET && USE_WEBSOCKET_SERVER
#include "cocos/bindings/manual/jsb_websocket_server.h"
#endif
#if USE_MIDDLEWARE
#include "cocos/bindings/auto/jsb_editor_support_auto.h"
#if USE_SPINE
#include "cocos/bindings/auto/jsb_spine_auto.h"
#include "cocos/bindings/manual/jsb_spine_manual.h"
#endif
#if USE_DRAGONBONES
#include "cocos/bindings/auto/jsb_dragonbones_auto.h"
#include "cocos/bindings/manual/jsb_dragonbones_manual.h"
#endif
#endif // USE_MIDDLEWARE
#if USE_PHYSICS_PHYSX
#include "cocos/bindings/auto/jsb_physics_auto.h"
#endif
using namespace cc;
bool jsb_register_all_modules() {
se::ScriptEngine *se = se::ScriptEngine::getInstance();
se->addBeforeInitHook([]() {
JSBClassType::init();
});
se->addBeforeCleanupHook([se]() {
se->garbageCollect();
PoolManager::getInstance()->getCurrentPool()->clear();
se->garbageCollect();
PoolManager::getInstance()->getCurrentPool()->clear();
});
se->addRegisterCallback(jsb_register_global_variables);
se->addRegisterCallback(register_all_engine);
se->addRegisterCallback(register_all_cocos_manual);
se->addRegisterCallback(register_platform_bindings);
se->addRegisterCallback(register_all_gfx);
se->addRegisterCallback(register_all_gfx_manual);
se->addRegisterCallback(register_all_network);
se->addRegisterCallback(register_all_network_manual);
se->addRegisterCallback(register_all_xmlhttprequest);
// extension depend on network
se->addRegisterCallback(register_all_extension);
se->addRegisterCallback(register_all_dop_bindings);
se->addRegisterCallback(register_all_pipeline);
se->addRegisterCallback(register_all_pipeline_manual);
#if (CC_PLATFORM == CC_PLATFORM_MAC_IOS || CC_PLATFORM == CC_PLATFORM_MAC_OSX)
se->addRegisterCallback(register_javascript_objc_bridge);
#endif
#if (CC_PLATFORM == CC_PLATFORM_ANDROID)
se->addRegisterCallback(register_javascript_java_bridge);
#endif
#if USE_AUDIO
se->addRegisterCallback(register_all_audio);
#endif
#if USE_SOCKET
se->addRegisterCallback(register_all_websocket);
se->addRegisterCallback(register_all_socketio);
#endif
#if USE_MIDDLEWARE
se->addRegisterCallback(register_all_editor_support);
#if USE_SPINE
se->addRegisterCallback(register_all_spine);
se->addRegisterCallback(register_all_spine_manual);
#endif
#if USE_DRAGONBONES
se->addRegisterCallback(register_all_dragonbones);
se->addRegisterCallback(register_all_dragonbones_manual);
#endif
#endif // USE_MIDDLEWARE
#if USE_PHYSICS_PHYSX
se->addRegisterCallback(register_all_physics);
#endif
#if (CC_PLATFORM == CC_PLATFORM_MAC_IOS || CC_PLATFORM == CC_PLATFORM_ANDROID)
#if USE_VIDEO
se->addRegisterCallback(register_all_video);
#endif
#if USE_WEBVIEW
se->addRegisterCallback(register_all_webview);
#endif
#endif // (CC_PLATFORM == CC_PLATFORM_MAC_IOS || CC_PLATFORM == CC_PLATFORM_ANDROID)
#if USE_SOCKET && USE_WEBSOCKET_SERVER
se->addRegisterCallback(register_all_websocket_server);
#endif
se->addAfterCleanupHook([]() {
PoolManager::getInstance()->getCurrentPool()->clear();
JSBClassType::destroy();
});
return true;
}

Some files were not shown because too many files have changed in this diff Show More