diff --git a/native/cocos/platform/android/java/src/com/cocos/lib/CocosActivity.java b/native/cocos/platform/android/java/src/com/cocos/lib/CocosActivity.java index a20829e1e02..ca7bdbd8397 100644 --- a/native/cocos/platform/android/java/src/com/cocos/lib/CocosActivity.java +++ b/native/cocos/platform/android/java/src/com/cocos/lib/CocosActivity.java @@ -26,61 +26,34 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; -import android.media.AudioManager; import android.os.Bundle; import android.text.TextUtils; import android.util.Log; import android.view.SurfaceView; import android.view.View; -import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; -import android.widget.FrameLayout; import com.google.androidgamesdk.GameActivity; import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.List; public class CocosActivity extends GameActivity { private static final String TAG = "CocosActivity"; - private CocosWebViewHelper mWebViewHelper = null; - private CocosVideoHelper mVideoHelper = null; - - private CocosSensorHandler mSensorHandler; - private List mSurfaceViewArray; - private FrameLayout mRootLayout; - - - - private native void onCreateNative(); + private CocosEngine mCocosEngine; @Override protected void onCreate(Bundle savedInstanceState) { - onLoadNativeLibraries(); - onCreateNative(); + String libName = getLibraryName(); + mCocosEngine = new CocosEngine(this, libName); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); getWindow().requestFeature(Window.FEATURE_NO_TITLE); + getIntent().putExtra(GameActivity.META_DATA_LIB_NAME, libName); super.onCreate(savedInstanceState); - - // GlobalObject.init should be initialized at first. - GlobalObject.init(this, this); - - CocosHelper.registerBatteryLevelReceiver(this); - CocosHelper.init(); - CocosAudioFocusManager.registerAudioFocusListener(this); - CanvasRenderingContext2DImpl.init(this); - this.setVolumeControlStream(AudioManager.STREAM_MUSIC); - getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING); initView(); - - mSensorHandler = new CocosSensorHandler(this); - setImmersiveMode(); - Utils.hideVirtualButton(); mSurfaceView.setOnTouchListener((v, event) -> processMotionEvent(event)); @@ -110,100 +83,53 @@ private void setImmersiveMode() { } } + //Deprecated, for compatibility, keep this interface for now protected void initView() { - mRootLayout = findViewById(contentViewId); - if (mWebViewHelper == null) { - mWebViewHelper = new CocosWebViewHelper(mRootLayout); - } - - if (mVideoHelper == null) { - mVideoHelper = new CocosVideoHelper(this, mRootLayout); - } + mCocosEngine.initView(findViewById(contentViewId)); } - - public SurfaceView getSurfaceView() { - return this.mSurfaceView; + return mSurfaceView; } @Override protected void onDestroy() { super.onDestroy(); - CocosHelper.unregisterBatteryLevelReceiver(this); - CocosAudioFocusManager.unregisterAudioFocusListener(this); - CanvasRenderingContext2DImpl.destroy(); - GlobalObject.destroy(); + mCocosEngine.destroy(); } @Override protected void onPause() { super.onPause(); - mSensorHandler.onPause(); + mCocosEngine.pause(); } @Override protected void onResume() { super.onResume(); - mSensorHandler.onResume(); Utils.hideVirtualButton(); - if (CocosAudioFocusManager.isAudioFocusLoss()) { - CocosAudioFocusManager.registerAudioFocusListener(this); - } + mCocosEngine.resume(); } @Override protected void onStop() { super.onStop(); - mSurfaceView.setVisibility(View.INVISIBLE); - if (null != mSurfaceViewArray) { - for (CocosSurfaceView surfaceView : mSurfaceViewArray) { - surfaceView.setVisibility(View.INVISIBLE); - } - } + mCocosEngine.stop(); } @Override protected void onStart() { super.onStart(); - mSurfaceView.setVisibility(View.VISIBLE); - if (null != mSurfaceViewArray) { - for (CocosSurfaceView surfaceView : mSurfaceViewArray) { - surfaceView.setVisibility(View.VISIBLE); - } - } + mCocosEngine.start(); } @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); - if (hasFocus && CocosAudioFocusManager.isAudioFocusLoss()) { - CocosAudioFocusManager.registerAudioFocusListener(this); - } - } - - // invoke from native code - @SuppressWarnings({"UnusedDeclaration"}) - private void createSurface(int x, int y, int width, int height, int windowId) { - runOnUiThread(new Runnable() { - @Override - public void run() { - CocosSurfaceView view = new CocosSurfaceView(CocosActivity.this, windowId); - view.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); - FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(width, height); - params.leftMargin = x; - params.topMargin = y; - //mSubsurfaceView.setBackgroundColor(Color.BLUE); - mRootLayout.addView(view, params); - if (null == mSurfaceViewArray) { - mSurfaceViewArray = new ArrayList<>(); - } - mSurfaceViewArray.add(view); - } - }); + mCocosEngine.getAudio().setFocus(hasFocus); } - private void onLoadNativeLibraries() { + private String getLibraryName() { try { ApplicationInfo ai = getPackageManager().getApplicationInfo(getPackageName(), PackageManager.GET_META_DATA); @@ -212,11 +138,10 @@ private void onLoadNativeLibraries() { if (TextUtils.isEmpty(libName)) { Log.e(TAG, "can not find library, please config android.app.lib_name at AndroidManifest.xml"); } - assert libName != null; - System.loadLibrary(libName); - getIntent().putExtra(GameActivity.META_DATA_LIB_NAME, libName); + return libName; } catch (Exception e) { e.printStackTrace(); } + return null; } } diff --git a/native/cocos/platform/android/java/src/com/cocos/lib/CocosAudio.java b/native/cocos/platform/android/java/src/com/cocos/lib/CocosAudio.java new file mode 100644 index 00000000000..4022817608c --- /dev/null +++ b/native/cocos/platform/android/java/src/com/cocos/lib/CocosAudio.java @@ -0,0 +1,47 @@ +/**************************************************************************** + Copyright (c) 2023 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.content.Context; + +public class CocosAudio { + Context mApplicationContext; + + CocosAudio(Context context) { + mApplicationContext = context.getApplicationContext(); + } + + public void setFocus(boolean hasFocus) { + if (hasFocus && CocosAudioFocusManager.isAudioFocusLoss()) { + CocosAudioFocusManager.registerAudioFocusListener(mApplicationContext); + } + } + + void destroy() { + CocosAudioFocusManager.unregisterAudioFocusListener(mApplicationContext); + mApplicationContext = null; + } +} diff --git a/native/cocos/platform/android/java/src/com/cocos/lib/CocosEditBoxActivity.java b/native/cocos/platform/android/java/src/com/cocos/lib/CocosEditBoxActivity.java index 388b9fdb27f..87b05cb5328 100644 --- a/native/cocos/platform/android/java/src/com/cocos/lib/CocosEditBoxActivity.java +++ b/native/cocos/platform/android/java/src/com/cocos/lib/CocosEditBoxActivity.java @@ -413,14 +413,14 @@ private static void showNative(String defaultValue, int maxLength, boolean isMul GlobalObject.runOnUiThread(new Runnable() { @Override public void run() { - Intent i = new Intent(GlobalObject.getActivity(), CocosEditBoxActivity.class); + Intent i = new Intent(GlobalObject.getContext(), 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); + GlobalObject.getContext().startActivity(i); } }); } diff --git a/native/cocos/platform/android/java/src/com/cocos/lib/CocosEngine.java b/native/cocos/platform/android/java/src/com/cocos/lib/CocosEngine.java new file mode 100644 index 00000000000..2c957188ecd --- /dev/null +++ b/native/cocos/platform/android/java/src/com/cocos/lib/CocosEngine.java @@ -0,0 +1,172 @@ +/**************************************************************************** + Copyright (c) 2023 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.app.Activity; +import android.content.Context; +import android.media.AudioManager; +import android.os.Handler; +import android.view.SurfaceView; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.List; + + +class CocosEngine { + private static WeakReference mRefCocosEngine; + + private CocosAudio mAudio; + private Context mContext; + + private CocosSensorHandler mSensorHandler; + + private CocosWebViewHelper mWebViewHelper = null; + private CocosVideoHelper mVideoHelper = null; + private FrameLayout mRootLayout; + private Handler mHandler; + + private List mSurfaceViewArray; + private SurfaceView mSurfaceView; + + private native void initEnvNative(Context context); + + CocosEngine(Context context, String libName) { + mRefCocosEngine = new WeakReference<>(this); + mContext = context; + mAudio = new CocosAudio(context); + mAudio.setFocus(true); + mHandler = new Handler(context.getMainLooper()); + System.loadLibrary(libName); + initEnvNative(context); + + Activity activity = null; + if (mContext instanceof Activity) { + activity = (Activity) mContext; + } + + // GlobalObject.init should be initialized at first. + GlobalObject.init(mContext, activity); + CocosHelper.registerBatteryLevelReceiver(mContext); + CocosHelper.init(); + CanvasRenderingContext2DImpl.init(mContext); + if (activity != null) { + activity.setVolumeControlStream(AudioManager.STREAM_MUSIC); + } + mSensorHandler = new CocosSensorHandler(mContext); + } + + void destroy() { + mRefCocosEngine.clear(); + CocosHelper.unregisterBatteryLevelReceiver(mContext); + mAudio.destroy(); + mAudio = null; + mHandler.removeCallbacks(null); + mHandler = null; + CanvasRenderingContext2DImpl.destroy(); + GlobalObject.destroy(); + mContext = null; + } + + void start() { + mSurfaceView.setVisibility(View.VISIBLE); + if (null != mSurfaceViewArray) { + for (CocosSurfaceView surfaceView : mSurfaceViewArray) { + surfaceView.setVisibility(View.VISIBLE); + } + } + } + + void stop() { + mSurfaceView.setVisibility(View.INVISIBLE); + if (null != mSurfaceViewArray) { + for (CocosSurfaceView surfaceView : mSurfaceViewArray) { + surfaceView.setVisibility(View.INVISIBLE); + } + } + } + + void pause() { + mSensorHandler.onPause(); + } + + void resume() { + mSensorHandler.onResume(); + mAudio.setFocus(true); + } + + SurfaceView getRenderView() { + return mSurfaceView; + } + + CocosAudio getAudio() { + return mAudio; + } + + void initView(FrameLayout parentView) { + if (parentView != null) { + mRootLayout = parentView; + CocosActivity cocosActivity = null; + if (mContext instanceof CocosActivity) { + cocosActivity = (CocosActivity) mContext; + mSurfaceView = cocosActivity.getSurfaceView(); + } else { + // todo: create surfaceView + } + + if (mWebViewHelper == null) { + mWebViewHelper = new CocosWebViewHelper(mRootLayout); + } + + if (mVideoHelper == null) { + mVideoHelper = new CocosVideoHelper(cocosActivity, mRootLayout); + } + } + } + + // invoke from native code + @SuppressWarnings({"UnusedDeclaration"}) + private static void createSurface(int x, int y, int width, int height, int windowId) { + CocosEngine cocosEngine = mRefCocosEngine.get(); + if (cocosEngine == null) return; + cocosEngine.mHandler.post(() -> { + CocosSurfaceView view = new CocosSurfaceView(cocosEngine.mContext, windowId); + view.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); + FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(width, height); + params.leftMargin = x; + params.topMargin = y; + //mSubsurfaceView.setBackgroundColor(Color.BLUE); + cocosEngine.mRootLayout.addView(view, params); + if (null == cocosEngine.mSurfaceViewArray) { + cocosEngine.mSurfaceViewArray = new ArrayList<>(); + } + cocosEngine.mSurfaceViewArray.add(view); + }); + } +} diff --git a/native/cocos/platform/android/java/src/com/cocos/lib/CocosHelper.java b/native/cocos/platform/android/java/src/com/cocos/lib/CocosHelper.java index 382b24dfc04..4417da2e5d1 100644 --- a/native/cocos/platform/android/java/src/com/cocos/lib/CocosHelper.java +++ b/native/cocos/platform/android/java/src/com/cocos/lib/CocosHelper.java @@ -262,7 +262,7 @@ public static void vibrate(float duration) { } public static boolean openURL(String url) { - if (GlobalObject.getActivity() == null) { + if (GlobalObject.getContext() == null) { Log.e(TAG, "activity is null"); return false; } @@ -271,7 +271,7 @@ public static boolean openURL(String url) { try { Intent i = new Intent(Intent.ACTION_VIEW); i.setData(Uri.parse(url)); - GlobalObject.getActivity().startActivity(i); + GlobalObject.getContext().startActivity(i); ret = true; } catch (Exception e) { } diff --git a/native/cocos/platform/android/jni/JniCocosEntry.cpp b/native/cocos/platform/android/jni/JniCocosEntry.cpp index 9334f01c263..754c96fbcc2 100644 --- a/native/cocos/platform/android/jni/JniCocosEntry.cpp +++ b/native/cocos/platform/android/jni/JniCocosEntry.cpp @@ -39,7 +39,7 @@ void android_main(struct android_app *app) { } //NOLINTNEXTLINE -JNIEXPORT void JNICALL Java_com_cocos_lib_CocosActivity_onCreateNative(JNIEnv *env, jobject activity) { +JNIEXPORT void JNICALL Java_com_cocos_lib_CocosEngine_initEnvNative(JNIEnv *env, jobject /**/, jobject activity) { cc::JniHelper::init(env, activity); } } diff --git a/native/cocos/platform/java/modules/SystemWindow.cpp b/native/cocos/platform/java/modules/SystemWindow.cpp index b2f37739f80..f506346a4ec 100644 --- a/native/cocos/platform/java/modules/SystemWindow.cpp +++ b/native/cocos/platform/java/modules/SystemWindow.cpp @@ -40,8 +40,8 @@ #include "platform/java/jni/glue/JniNativeGlue.h" namespace { -#ifndef JCLS_COCOSACTIVITY - #define JCLS_COCOSACTIVITY "com/cocos/lib/CocosActivity" +#ifndef JCLS_COCOSENGINE + #define JCLS_COCOSENGINE "com/cocos/lib/CocosEngine" #endif } // namespace @@ -109,7 +109,7 @@ bool SystemWindow::createWindow(const char *title, int x, int y, int w, int h, i CC_UNUSED_PARAM(title); CC_UNUSED_PARAM(flags); #if (CC_PLATFORM == CC_PLATFORM_ANDROID) - cc::JniHelper::callObjectVoidMethod(cc::JniHelper::getActivity(), JCLS_COCOSACTIVITY, "createSurface", x, y, w, h, static_cast(_windowId)); + JniHelper::callStaticVoidMethod(JCLS_COCOSENGINE, "createSurface", x, y, w, h, static_cast(_windowId)); #endif return true; } @@ -118,7 +118,7 @@ bool SystemWindow::createWindow(const char *title, int w, int h, int flags) { CC_UNUSED_PARAM(title); CC_UNUSED_PARAM(flags); #if (CC_PLATFORM == CC_PLATFORM_ANDROID) - cc::JniHelper::callObjectVoidMethod(cc::JniHelper::getActivity(), JCLS_COCOSACTIVITY, "createSurface", 0, 0, w, h, static_cast(_windowId)); + JniHelper::callStaticVoidMethod(JCLS_COCOSENGINE, "createSurface", 0, 0, w, h, static_cast(_windowId)); #endif return true; }