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

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.