mirror of
https://github.com/godotengine/godot.git
synced 2026-05-12 22:35:35 +00:00
Godot Android re-architecture
Decouples the Godot java entry point from the Android Fragment component. This enables the Godot component to be more easily reused across different types of Android components including Activities and Services.
This commit is contained in:
@@ -30,7 +30,7 @@
|
||||
|
||||
package com.godot.game;
|
||||
|
||||
import org.godotengine.godot.FullScreenGodotApp;
|
||||
import org.godotengine.godot.GodotActivity;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
@@ -38,7 +38,7 @@ import android.os.Bundle;
|
||||
* Template activity for Godot Android builds.
|
||||
* Feel free to extend and modify this class for your custom logic.
|
||||
*/
|
||||
public class GodotApp extends FullScreenGodotApp {
|
||||
public class GodotApp extends GodotActivity {
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
setTheme(R.style.GodotAppMainTheme);
|
||||
|
||||
@@ -39,7 +39,7 @@ import android.os.*
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import androidx.window.layout.WindowMetricsCalculator
|
||||
import org.godotengine.godot.FullScreenGodotApp
|
||||
import org.godotengine.godot.GodotActivity
|
||||
import org.godotengine.godot.GodotLib
|
||||
import org.godotengine.godot.utils.PermissionsUtil
|
||||
import org.godotengine.godot.utils.ProcessPhoenix
|
||||
@@ -55,7 +55,7 @@ import kotlin.math.min
|
||||
*
|
||||
* It also plays the role of the primary editor window.
|
||||
*/
|
||||
open class GodotEditor : FullScreenGodotApp() {
|
||||
open class GodotEditor : GodotActivity() {
|
||||
|
||||
companion object {
|
||||
private val TAG = GodotEditor::class.java.simpleName
|
||||
@@ -115,7 +115,7 @@ open class GodotEditor : FullScreenGodotApp() {
|
||||
|
||||
runOnUiThread {
|
||||
// Enable long press, panning and scaling gestures
|
||||
godotFragment?.renderView?.inputHandler?.apply {
|
||||
godotFragment?.godot?.renderView?.inputHandler?.apply {
|
||||
enableLongPress(longPressEnabled)
|
||||
enablePanningAndScalingGestures(panScaleEnabled)
|
||||
}
|
||||
@@ -318,7 +318,7 @@ open class GodotEditor : FullScreenGodotApp() {
|
||||
|
||||
override fun onRequestPermissionsResult(
|
||||
requestCode: Int,
|
||||
permissions: Array<String?>,
|
||||
permissions: Array<String>,
|
||||
grantResults: IntArray
|
||||
) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
|
||||
@@ -30,156 +30,10 @@
|
||||
|
||||
package org.godotengine.godot;
|
||||
|
||||
import org.godotengine.godot.utils.ProcessPhoenix;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.CallSuper;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
|
||||
/**
|
||||
* Base activity for Android apps intending to use Godot as the primary and only screen.
|
||||
* Base abstract activity for Android apps intending to use Godot as the primary screen.
|
||||
*
|
||||
* It's also a reference implementation for how to setup and use the {@link Godot} fragment
|
||||
* within an Android app.
|
||||
* @deprecated Use {@link GodotActivity}
|
||||
*/
|
||||
public abstract class FullScreenGodotApp extends FragmentActivity implements GodotHost {
|
||||
private static final String TAG = FullScreenGodotApp.class.getSimpleName();
|
||||
|
||||
protected static final String EXTRA_FORCE_QUIT = "force_quit_requested";
|
||||
protected static final String EXTRA_NEW_LAUNCH = "new_launch_requested";
|
||||
|
||||
@Nullable
|
||||
private Godot godotFragment;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.godot_app_layout);
|
||||
|
||||
handleStartIntent(getIntent(), true);
|
||||
|
||||
Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.godot_fragment_container);
|
||||
if (currentFragment instanceof Godot) {
|
||||
Log.v(TAG, "Reusing existing Godot fragment instance.");
|
||||
godotFragment = (Godot)currentFragment;
|
||||
} else {
|
||||
Log.v(TAG, "Creating new Godot fragment instance.");
|
||||
godotFragment = initGodotInstance();
|
||||
getSupportFragmentManager().beginTransaction().replace(R.id.godot_fragment_container, godotFragment).setPrimaryNavigationFragment(godotFragment).commitNowAllowingStateLoss();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
Log.v(TAG, "Destroying Godot app...");
|
||||
super.onDestroy();
|
||||
terminateGodotInstance(godotFragment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onGodotForceQuit(Godot instance) {
|
||||
runOnUiThread(() -> {
|
||||
terminateGodotInstance(instance);
|
||||
});
|
||||
}
|
||||
|
||||
private void terminateGodotInstance(Godot instance) {
|
||||
if (instance == godotFragment) {
|
||||
Log.v(TAG, "Force quitting Godot instance");
|
||||
ProcessPhoenix.forceQuit(FullScreenGodotApp.this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onGodotRestartRequested(Godot instance) {
|
||||
runOnUiThread(() -> {
|
||||
if (instance == godotFragment) {
|
||||
// It's very hard to properly de-initialize Godot on Android to restart the game
|
||||
// from scratch. Therefore, we need to kill the whole app process and relaunch it.
|
||||
//
|
||||
// Restarting only the activity, wouldn't be enough unless it did proper cleanup (including
|
||||
// releasing and reloading native libs or resetting their state somehow and clearing static data).
|
||||
Log.v(TAG, "Restarting Godot instance...");
|
||||
ProcessPhoenix.triggerRebirth(FullScreenGodotApp.this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
setIntent(intent);
|
||||
|
||||
handleStartIntent(intent, false);
|
||||
|
||||
if (godotFragment != null) {
|
||||
godotFragment.onNewIntent(intent);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleStartIntent(Intent intent, boolean newLaunch) {
|
||||
boolean forceQuitRequested = intent.getBooleanExtra(EXTRA_FORCE_QUIT, false);
|
||||
if (forceQuitRequested) {
|
||||
Log.d(TAG, "Force quit requested, terminating..");
|
||||
ProcessPhoenix.forceQuit(this);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!newLaunch) {
|
||||
boolean newLaunchRequested = intent.getBooleanExtra(EXTRA_NEW_LAUNCH, false);
|
||||
if (newLaunchRequested) {
|
||||
Log.d(TAG, "New launch requested, restarting..");
|
||||
|
||||
Intent restartIntent = new Intent(intent).putExtra(EXTRA_NEW_LAUNCH, false);
|
||||
ProcessPhoenix.triggerRebirth(this, restartIntent);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (godotFragment != null) {
|
||||
godotFragment.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
if (godotFragment != null) {
|
||||
godotFragment.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (godotFragment != null) {
|
||||
godotFragment.onBackPressed();
|
||||
} else {
|
||||
super.onBackPressed();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to initialize the Godot fragment instance in {@link FullScreenGodotApp#onCreate(Bundle)}.
|
||||
*/
|
||||
@NonNull
|
||||
protected Godot initGodotInstance() {
|
||||
return new Godot();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected final Godot getGodotFragment() {
|
||||
return godotFragment;
|
||||
}
|
||||
}
|
||||
@Deprecated
|
||||
public abstract class FullScreenGodotApp extends GodotActivity {}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,167 @@
|
||||
/**************************************************************************/
|
||||
/* GodotActivity.kt */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* 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 org.godotengine.godot
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import androidx.annotation.CallSuper
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import org.godotengine.godot.utils.ProcessPhoenix
|
||||
|
||||
/**
|
||||
* Base abstract activity for Android apps intending to use Godot as the primary screen.
|
||||
*
|
||||
* Also a reference implementation for how to setup and use the [GodotFragment] fragment
|
||||
* within an Android app.
|
||||
*/
|
||||
abstract class GodotActivity : FragmentActivity(), GodotHost {
|
||||
|
||||
companion object {
|
||||
private val TAG = GodotActivity::class.java.simpleName
|
||||
|
||||
@JvmStatic
|
||||
protected val EXTRA_FORCE_QUIT = "force_quit_requested"
|
||||
@JvmStatic
|
||||
protected val EXTRA_NEW_LAUNCH = "new_launch_requested"
|
||||
}
|
||||
|
||||
/**
|
||||
* Interaction with the [Godot] object is delegated to the [GodotFragment] class.
|
||||
*/
|
||||
protected var godotFragment: GodotFragment? = null
|
||||
private set
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.godot_app_layout)
|
||||
|
||||
handleStartIntent(intent, true)
|
||||
|
||||
val currentFragment = supportFragmentManager.findFragmentById(R.id.godot_fragment_container)
|
||||
if (currentFragment is GodotFragment) {
|
||||
Log.v(TAG, "Reusing existing Godot fragment instance.")
|
||||
godotFragment = currentFragment
|
||||
} else {
|
||||
Log.v(TAG, "Creating new Godot fragment instance.")
|
||||
godotFragment = initGodotInstance()
|
||||
supportFragmentManager.beginTransaction().replace(R.id.godot_fragment_container, godotFragment!!).setPrimaryNavigationFragment(godotFragment).commitNowAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
Log.v(TAG, "Destroying Godot app...")
|
||||
super.onDestroy()
|
||||
if (godotFragment != null) {
|
||||
terminateGodotInstance(godotFragment!!.godot)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onGodotForceQuit(instance: Godot) {
|
||||
runOnUiThread { terminateGodotInstance(instance) }
|
||||
}
|
||||
|
||||
private fun terminateGodotInstance(instance: Godot) {
|
||||
if (godotFragment != null && instance === godotFragment!!.godot) {
|
||||
Log.v(TAG, "Force quitting Godot instance")
|
||||
ProcessPhoenix.forceQuit(this)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onGodotRestartRequested(instance: Godot) {
|
||||
runOnUiThread {
|
||||
if (godotFragment != null && instance === godotFragment!!.godot) {
|
||||
// It's very hard to properly de-initialize Godot on Android to restart the game
|
||||
// from scratch. Therefore, we need to kill the whole app process and relaunch it.
|
||||
//
|
||||
// Restarting only the activity, wouldn't be enough unless it did proper cleanup (including
|
||||
// releasing and reloading native libs or resetting their state somehow and clearing static data).
|
||||
Log.v(TAG, "Restarting Godot instance...")
|
||||
ProcessPhoenix.triggerRebirth(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onNewIntent(newIntent: Intent) {
|
||||
super.onNewIntent(newIntent)
|
||||
intent = newIntent
|
||||
|
||||
handleStartIntent(newIntent, false)
|
||||
|
||||
godotFragment?.onNewIntent(newIntent)
|
||||
}
|
||||
|
||||
private fun handleStartIntent(intent: Intent, newLaunch: Boolean) {
|
||||
val forceQuitRequested = intent.getBooleanExtra(EXTRA_FORCE_QUIT, false)
|
||||
if (forceQuitRequested) {
|
||||
Log.d(TAG, "Force quit requested, terminating..")
|
||||
ProcessPhoenix.forceQuit(this)
|
||||
return
|
||||
}
|
||||
if (!newLaunch) {
|
||||
val newLaunchRequested = intent.getBooleanExtra(EXTRA_NEW_LAUNCH, false)
|
||||
if (newLaunchRequested) {
|
||||
Log.d(TAG, "New launch requested, restarting..")
|
||||
val restartIntent = Intent(intent).putExtra(EXTRA_NEW_LAUNCH, false)
|
||||
ProcessPhoenix.triggerRebirth(this, restartIntent)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
godotFragment?.onActivityResult(requestCode, resultCode, data)
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
godotFragment?.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
godotFragment?.onBackPressed() ?: super.onBackPressed()
|
||||
}
|
||||
|
||||
override fun getActivity(): Activity? {
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to initialize the Godot fragment instance in [onCreate].
|
||||
*/
|
||||
protected open fun initGodotInstance(): GodotFragment {
|
||||
return GodotFragment()
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -29,10 +29,10 @@
|
||||
/**************************************************************************/
|
||||
|
||||
package org.godotengine.godot;
|
||||
|
||||
import org.godotengine.godot.gl.GLSurfaceView;
|
||||
import org.godotengine.godot.gl.GodotRenderer;
|
||||
import org.godotengine.godot.input.GodotInputHandler;
|
||||
import org.godotengine.godot.utils.GLUtils;
|
||||
import org.godotengine.godot.xr.XRMode;
|
||||
import org.godotengine.godot.xr.ovr.OvrConfigChooser;
|
||||
import org.godotengine.godot.xr.ovr.OvrContextFactory;
|
||||
@@ -78,22 +78,23 @@ import java.io.InputStream;
|
||||
* bit depths). Failure to do so would result in an EGL_BAD_MATCH error.
|
||||
*/
|
||||
public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView {
|
||||
private final GodotHost host;
|
||||
private final Godot godot;
|
||||
private final GodotInputHandler inputHandler;
|
||||
private final GodotRenderer godotRenderer;
|
||||
private final SparseArray<PointerIcon> customPointerIcons = new SparseArray<>();
|
||||
|
||||
public GodotGLRenderView(Context context, Godot godot, XRMode xrMode, boolean p_use_debug_opengl) {
|
||||
super(context);
|
||||
GLUtils.use_debug_opengl = p_use_debug_opengl;
|
||||
public GodotGLRenderView(GodotHost host, Godot godot, XRMode xrMode, boolean useDebugOpengl) {
|
||||
super(host.getActivity());
|
||||
|
||||
this.host = host;
|
||||
this.godot = godot;
|
||||
this.inputHandler = new GodotInputHandler(this);
|
||||
this.godotRenderer = new GodotRenderer();
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
setPointerIcon(PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_DEFAULT));
|
||||
}
|
||||
init(xrMode, false);
|
||||
init(xrMode, false, useDebugOpengl);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -123,7 +124,7 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
godot.onBackPressed();
|
||||
godot.onBackPressed(host);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -233,7 +234,7 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView
|
||||
return super.onResolvePointerIcon(me, pointerIndex);
|
||||
}
|
||||
|
||||
private void init(XRMode xrMode, boolean translucent) {
|
||||
private void init(XRMode xrMode, boolean translucent, boolean useDebugOpengl) {
|
||||
setPreserveEGLContextOnPause(true);
|
||||
setFocusableInTouchMode(true);
|
||||
switch (xrMode) {
|
||||
@@ -262,7 +263,7 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView
|
||||
/* Setup the context factory for 2.0 rendering.
|
||||
* See ContextFactory class definition below
|
||||
*/
|
||||
setEGLContextFactory(new RegularContextFactory());
|
||||
setEGLContextFactory(new RegularContextFactory(useDebugOpengl));
|
||||
|
||||
/* We need to choose an EGLConfig that matches the format of
|
||||
* our surface exactly. This is going to be done in our
|
||||
@@ -275,7 +276,10 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView
|
||||
new RegularConfigChooser(8, 8, 8, 8, 16, 0)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startRenderer() {
|
||||
/* Set the renderer responsible for frame rendering */
|
||||
setRenderer(godotRenderer);
|
||||
}
|
||||
|
||||
@@ -30,11 +30,13 @@
|
||||
|
||||
package org.godotengine.godot;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Denotate a component (e.g: Activity, Fragment) that hosts the {@link Godot} fragment.
|
||||
* Denotate a component (e.g: Activity, Fragment) that hosts the {@link Godot} engine.
|
||||
*/
|
||||
public interface GodotHost {
|
||||
/**
|
||||
@@ -86,4 +88,9 @@ public interface GodotHost {
|
||||
default int onNewGodotInstanceRequested(String[] args) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide access to the Activity hosting the Godot engine.
|
||||
*/
|
||||
Activity getActivity();
|
||||
}
|
||||
|
||||
@@ -39,6 +39,11 @@ public interface GodotRenderView {
|
||||
|
||||
void initInputDevices();
|
||||
|
||||
/**
|
||||
* Starts the thread that will drive Godot's rendering.
|
||||
*/
|
||||
void startRenderer();
|
||||
|
||||
void queueOnRenderThread(Runnable event);
|
||||
|
||||
void onActivityPaused();
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package org.godotengine.godot
|
||||
|
||||
import android.app.Service
|
||||
import android.content.Intent
|
||||
import android.os.Binder
|
||||
import android.os.IBinder
|
||||
import android.util.Log
|
||||
|
||||
/**
|
||||
* Godot service responsible for hosting the Godot engine instance.
|
||||
*/
|
||||
class GodotService : Service() {
|
||||
|
||||
companion object {
|
||||
private val TAG = GodotService::class.java.simpleName
|
||||
}
|
||||
|
||||
private var boundIntent: Intent? = null
|
||||
private val godot by lazy {
|
||||
Godot(applicationContext)
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun onBind(intent: Intent?): IBinder? {
|
||||
if (boundIntent != null) {
|
||||
Log.d(TAG, "GodotService already bound")
|
||||
return null
|
||||
}
|
||||
|
||||
boundIntent = intent
|
||||
return GodotHandle(godot)
|
||||
}
|
||||
|
||||
override fun onRebind(intent: Intent?) {
|
||||
super.onRebind(intent)
|
||||
}
|
||||
|
||||
override fun onUnbind(intent: Intent?): Boolean {
|
||||
return super.onUnbind(intent)
|
||||
}
|
||||
|
||||
override fun onTaskRemoved(rootIntent: Intent?) {
|
||||
super.onTaskRemoved(rootIntent)
|
||||
}
|
||||
|
||||
class GodotHandle(val godot: Godot) : Binder()
|
||||
}
|
||||
@@ -35,7 +35,6 @@ import org.godotengine.godot.vulkan.VkRenderer;
|
||||
import org.godotengine.godot.vulkan.VkSurfaceView;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.res.AssetManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
@@ -52,14 +51,16 @@ import androidx.annotation.Keep;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderView {
|
||||
private final GodotHost host;
|
||||
private final Godot godot;
|
||||
private final GodotInputHandler mInputHandler;
|
||||
private final VkRenderer mRenderer;
|
||||
private final SparseArray<PointerIcon> customPointerIcons = new SparseArray<>();
|
||||
|
||||
public GodotVulkanRenderView(Context context, Godot godot) {
|
||||
super(context);
|
||||
public GodotVulkanRenderView(GodotHost host, Godot godot) {
|
||||
super(host.getActivity());
|
||||
|
||||
this.host = host;
|
||||
this.godot = godot;
|
||||
mInputHandler = new GodotInputHandler(this);
|
||||
mRenderer = new VkRenderer();
|
||||
@@ -67,6 +68,10 @@ public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderV
|
||||
setPointerIcon(PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_DEFAULT));
|
||||
}
|
||||
setFocusableInTouchMode(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startRenderer() {
|
||||
startRenderer(mRenderer);
|
||||
}
|
||||
|
||||
@@ -97,7 +102,7 @@ public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderV
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
godot.onBackPressed();
|
||||
godot.onBackPressed(host);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -33,6 +33,7 @@ package org.godotengine.godot.tts;
|
||||
import org.godotengine.godot.GodotLib;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.speech.tts.TextToSpeech;
|
||||
import android.speech.tts.UtteranceProgressListener;
|
||||
@@ -62,7 +63,7 @@ public class GodotTTS extends UtteranceProgressListener {
|
||||
final private static int EVENT_CANCEL = 2;
|
||||
final private static int EVENT_BOUNDARY = 3;
|
||||
|
||||
final private Activity activity;
|
||||
private final Context context;
|
||||
private TextToSpeech synth;
|
||||
private LinkedList<GodotUtterance> queue;
|
||||
final private Object lock = new Object();
|
||||
@@ -71,8 +72,8 @@ public class GodotTTS extends UtteranceProgressListener {
|
||||
private boolean speaking;
|
||||
private boolean paused;
|
||||
|
||||
public GodotTTS(Activity p_activity) {
|
||||
activity = p_activity;
|
||||
public GodotTTS(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
private void updateTTS() {
|
||||
@@ -188,7 +189,7 @@ public class GodotTTS extends UtteranceProgressListener {
|
||||
* Initialize synth and query.
|
||||
*/
|
||||
public void init() {
|
||||
synth = new TextToSpeech(activity, null);
|
||||
synth = new TextToSpeech(context, null);
|
||||
queue = new LinkedList<GodotUtterance>();
|
||||
|
||||
synth.setOnUtteranceProgressListener(this);
|
||||
|
||||
@@ -44,8 +44,6 @@ public class GLUtils {
|
||||
|
||||
public static final boolean DEBUG = false;
|
||||
|
||||
public static boolean use_debug_opengl = false;
|
||||
|
||||
private static final String[] ATTRIBUTES_NAMES = new String[] {
|
||||
"EGL_BUFFER_SIZE",
|
||||
"EGL_ALPHA_SIZE",
|
||||
|
||||
@@ -36,7 +36,8 @@ import android.net.wifi.WifiManager;
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.StringWriter;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.security.KeyStore;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Enumeration;
|
||||
@@ -50,9 +51,9 @@ public class GodotNetUtils {
|
||||
/* A single, reference counted, multicast lock, or null if permission CHANGE_WIFI_MULTICAST_STATE is missing */
|
||||
private WifiManager.MulticastLock multicastLock;
|
||||
|
||||
public GodotNetUtils(Activity p_activity) {
|
||||
if (PermissionsUtil.hasManifestPermission(p_activity, "android.permission.CHANGE_WIFI_MULTICAST_STATE")) {
|
||||
WifiManager wifi = (WifiManager)p_activity.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
|
||||
public GodotNetUtils(Context context) {
|
||||
if (PermissionsUtil.hasManifestPermission(context, "android.permission.CHANGE_WIFI_MULTICAST_STATE")) {
|
||||
WifiManager wifi = (WifiManager)context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
|
||||
multicastLock = wifi.createMulticastLock("GodotMulticastLock");
|
||||
multicastLock.setReferenceCounted(true);
|
||||
}
|
||||
@@ -91,7 +92,7 @@ public class GodotNetUtils {
|
||||
* @see https://developer.android.com/reference/java/security/KeyStore .
|
||||
* @return A string of concatenated X509 certificates in PEM format.
|
||||
*/
|
||||
public static String getCACertificates() {
|
||||
public static @NonNull String getCACertificates() {
|
||||
try {
|
||||
KeyStore ks = KeyStore.getInstance("AndroidCAStore");
|
||||
StringBuilder writer = new StringBuilder();
|
||||
|
||||
@@ -32,6 +32,7 @@ package org.godotengine.godot.utils;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
@@ -52,7 +53,6 @@ import java.util.Set;
|
||||
/**
|
||||
* This class includes utility functions for Android permissions related operations.
|
||||
*/
|
||||
|
||||
public final class PermissionsUtil {
|
||||
private static final String TAG = PermissionsUtil.class.getSimpleName();
|
||||
|
||||
@@ -193,13 +193,13 @@ public final class PermissionsUtil {
|
||||
|
||||
/**
|
||||
* With this function you can get the list of dangerous permissions that have been granted to the Android application.
|
||||
* @param activity the caller activity for this method.
|
||||
* @param context the caller context for this method.
|
||||
* @return granted permissions list
|
||||
*/
|
||||
public static String[] getGrantedPermissions(Activity activity) {
|
||||
public static String[] getGrantedPermissions(Context context) {
|
||||
String[] manifestPermissions;
|
||||
try {
|
||||
manifestPermissions = getManifestPermissions(activity);
|
||||
manifestPermissions = getManifestPermissions(context);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
return new String[0];
|
||||
@@ -215,9 +215,9 @@ public final class PermissionsUtil {
|
||||
grantedPermissions.add(manifestPermission);
|
||||
}
|
||||
} else {
|
||||
PermissionInfo permissionInfo = getPermissionInfo(activity, manifestPermission);
|
||||
PermissionInfo permissionInfo = getPermissionInfo(context, manifestPermission);
|
||||
int protectionLevel = Build.VERSION.SDK_INT >= Build.VERSION_CODES.P ? permissionInfo.getProtection() : permissionInfo.protectionLevel;
|
||||
if (protectionLevel == PermissionInfo.PROTECTION_DANGEROUS && ContextCompat.checkSelfPermission(activity, manifestPermission) == PackageManager.PERMISSION_GRANTED) {
|
||||
if (protectionLevel == PermissionInfo.PROTECTION_DANGEROUS && ContextCompat.checkSelfPermission(context, manifestPermission) == PackageManager.PERMISSION_GRANTED) {
|
||||
grantedPermissions.add(manifestPermission);
|
||||
}
|
||||
}
|
||||
@@ -232,13 +232,13 @@ public final class PermissionsUtil {
|
||||
|
||||
/**
|
||||
* Check if the given permission is in the AndroidManifest.xml file.
|
||||
* @param activity the caller activity for this method.
|
||||
* @param context the caller context for this method.
|
||||
* @param permission the permession to look for in the manifest file.
|
||||
* @return "true" if the permission is in the manifest file of the activity, "false" otherwise.
|
||||
*/
|
||||
public static boolean hasManifestPermission(Activity activity, String permission) {
|
||||
public static boolean hasManifestPermission(Context context, String permission) {
|
||||
try {
|
||||
for (String p : getManifestPermissions(activity)) {
|
||||
for (String p : getManifestPermissions(context)) {
|
||||
if (permission.equals(p))
|
||||
return true;
|
||||
}
|
||||
@@ -250,13 +250,13 @@ public final class PermissionsUtil {
|
||||
|
||||
/**
|
||||
* Returns the permissions defined in the AndroidManifest.xml file.
|
||||
* @param activity the caller activity for this method.
|
||||
* @param context the caller context for this method.
|
||||
* @return manifest permissions list
|
||||
* @throws PackageManager.NameNotFoundException the exception is thrown when a given package, application, or component name cannot be found.
|
||||
*/
|
||||
private static String[] getManifestPermissions(Activity activity) throws PackageManager.NameNotFoundException {
|
||||
PackageManager packageManager = activity.getPackageManager();
|
||||
PackageInfo packageInfo = packageManager.getPackageInfo(activity.getPackageName(), PackageManager.GET_PERMISSIONS);
|
||||
private static String[] getManifestPermissions(Context context) throws PackageManager.NameNotFoundException {
|
||||
PackageManager packageManager = context.getPackageManager();
|
||||
PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), PackageManager.GET_PERMISSIONS);
|
||||
if (packageInfo.requestedPermissions == null)
|
||||
return new String[0];
|
||||
return packageInfo.requestedPermissions;
|
||||
@@ -264,13 +264,13 @@ public final class PermissionsUtil {
|
||||
|
||||
/**
|
||||
* Returns the information of the desired permission.
|
||||
* @param activity the caller activity for this method.
|
||||
* @param context the caller context for this method.
|
||||
* @param permission the name of the permission.
|
||||
* @return permission info object
|
||||
* @throws PackageManager.NameNotFoundException the exception is thrown when a given package, application, or component name cannot be found.
|
||||
*/
|
||||
private static PermissionInfo getPermissionInfo(Activity activity, String permission) throws PackageManager.NameNotFoundException {
|
||||
PackageManager packageManager = activity.getPackageManager();
|
||||
private static PermissionInfo getPermissionInfo(Context context, String permission) throws PackageManager.NameNotFoundException {
|
||||
PackageManager packageManager = context.getPackageManager();
|
||||
return packageManager.getPermissionInfo(permission, 0);
|
||||
}
|
||||
}
|
||||
|
||||
+11
-1
@@ -51,12 +51,22 @@ public class RegularContextFactory implements GLSurfaceView.EGLContextFactory {
|
||||
|
||||
private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
|
||||
|
||||
private final boolean mUseDebugOpengl;
|
||||
|
||||
public RegularContextFactory() {
|
||||
this(false);
|
||||
}
|
||||
|
||||
public RegularContextFactory(boolean useDebugOpengl) {
|
||||
this.mUseDebugOpengl = useDebugOpengl;
|
||||
}
|
||||
|
||||
public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig) {
|
||||
Log.w(TAG, "creating OpenGL ES 3.0 context :");
|
||||
|
||||
GLUtils.checkEglError(TAG, "Before eglCreateContext", egl);
|
||||
EGLContext context;
|
||||
if (GLUtils.use_debug_opengl) {
|
||||
if (mUseDebugOpengl) {
|
||||
int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, 3, _EGL_CONTEXT_FLAGS_KHR, _EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR, EGL10.EGL_NONE };
|
||||
context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list);
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user