Browse Source

Enable the ability to use Godot as a subview within an Android app

(cherry picked from commit 920639511d5e774402c6b4f37ee0550368f5109a)
Fredia Huya-Kouadio 5 years ago
parent
commit
e99dc65b64

+ 2 - 2
platform/android/java/app/src/com/godot/game/GodotApp.java

@@ -30,11 +30,11 @@
 
 package com.godot.game;
 
-import org.godotengine.godot.Godot;
+import org.godotengine.godot.FullScreenGodotApp;
 
 /**
  * Template activity for Godot Android custom builds.
  * Feel free to extend and modify this class for your custom logic.
  */
-public class GodotApp extends Godot {
+public class GodotApp extends FullScreenGodotApp {
 }

+ 5 - 0
platform/android/java/lib/res/layout/godot_app_layout.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+	android:id="@+id/godot_fragment_container"
+	android:layout_width="match_parent"
+	android:layout_height="match_parent" />

+ 80 - 0
platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java

@@ -0,0 +1,80 @@
+/*************************************************************************/
+/*  FullScreenGodotApp.java                                              */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* 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.content.Intent;
+import android.os.Bundle;
+import android.view.KeyEvent;
+
+import androidx.fragment.app.FragmentActivity;
+
+/**
+ * Base activity for Android apps intending to use Godot as the primary and only screen.
+ *
+ * It's also a reference implementation for how to setup and use the {@link Godot} fragment
+ * within an Android app.
+ */
+public abstract class FullScreenGodotApp extends FragmentActivity {
+
+	protected Godot godotFragment;
+
+	@Override
+	public void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+		setContentView(R.layout.godot_app_layout);
+		godotFragment = new Godot();
+		getSupportFragmentManager().beginTransaction().replace(R.id.godot_fragment_container, godotFragment).setPrimaryNavigationFragment(godotFragment).commitNowAllowingStateLoss();
+	}
+
+	@Override
+	public void onNewIntent(Intent intent) {
+		if (godotFragment != null) {
+			godotFragment.onNewIntent(intent);
+		}
+	}
+
+	@Override
+	public void onBackPressed() {
+		if (godotFragment != null) {
+			godotFragment.onBackPressed();
+		} else {
+			super.onBackPressed();
+		}
+	}
+
+	@Override
+	public boolean onKeyMultiple(final int inKeyCode, int repeatCount, KeyEvent event) {
+		if (godotFragment != null && godotFragment.onKeyMultiple(inKeyCode, repeatCount, event)) {
+			return true;
+		}
+		return super.onKeyMultiple(inKeyCode, repeatCount, event);
+	}
+}

+ 171 - 158
platform/android/java/lib/src/org/godotengine/godot/Godot.java

@@ -30,6 +30,9 @@
 
 package org.godotengine.godot;
 
+import static android.content.Context.MODE_PRIVATE;
+import static android.content.Context.WINDOW_SERVICE;
+
 import org.godotengine.godot.input.GodotEditText;
 import org.godotengine.godot.plugin.GodotPlugin;
 import org.godotengine.godot.plugin.GodotPluginRegistry;
@@ -70,6 +73,7 @@ import android.os.Vibrator;
 import android.provider.Settings.Secure;
 import android.view.Display;
 import android.view.KeyEvent;
+import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.Surface;
 import android.view.View;
@@ -87,7 +91,7 @@ import androidx.annotation.CallSuper;
 import androidx.annotation.Keep;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
-import androidx.fragment.app.FragmentActivity;
+import androidx.fragment.app.Fragment;
 
 import com.google.android.vending.expansion.downloader.DownloadProgressInfo;
 import com.google.android.vending.expansion.downloader.DownloaderClientMarshaller;
@@ -109,7 +113,7 @@ import java.util.Locale;
 
 import javax.microedition.khronos.opengles.GL10;
 
-public abstract class Godot extends FragmentActivity implements SensorEventListener, IDownloaderClient {
+public class Godot extends Fragment implements SensorEventListener, IDownloaderClient {
 
 	static final int MAX_SINGLETONS = 64;
 	private IStub mDownloaderClientStub;
@@ -142,7 +146,6 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 
 	static private Intent mCurrentIntent;
 
-	@Override
 	public void onNewIntent(Intent intent) {
 		mCurrentIntent = intent;
 	}
@@ -244,6 +247,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 	private String[] command_line;
 	private boolean use_apk_expansion;
 
+	private ViewGroup containerLayout;
 	public GodotView mView;
 	private boolean godot_initialized = false;
 
@@ -265,7 +269,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 	public ResultCallback result_callback;
 
 	@Override
-	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+	public void onActivityResult(int requestCode, int resultCode, Intent data) {
 		if (result_callback != null) {
 			result_callback.callback(requestCode, resultCode, data);
 			result_callback = null;
@@ -311,19 +315,19 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 	private void onVideoInit() {
 		boolean use_gl3 = getGLESVersionCode() >= 0x00030000;
 
-		final FrameLayout layout = new FrameLayout(this);
-		layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
-		setContentView(layout);
+		final Activity activity = getActivity();
+		containerLayout = new FrameLayout(activity);
+		containerLayout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
 
 		// GodotEditText layout
-		GodotEditText edittext = new GodotEditText(this);
+		GodotEditText edittext = new GodotEditText(activity);
 		edittext.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT,
 				(int)getResources().getDimension(R.dimen.text_edit_height)));
 		// ...add to FrameLayout
-		layout.addView(edittext);
+		containerLayout.addView(edittext);
 
-		mView = new GodotView(this, xrMode, use_gl3, use_32_bits, use_debug_opengl);
-		layout.addView(mView, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
+		mView = new GodotView(activity, this, xrMode, use_gl3, use_32_bits, use_debug_opengl);
+		containerLayout.addView(mView, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
 		edittext.setView(mView);
 		io.setEdit(edittext);
 
@@ -331,7 +335,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 			@Override
 			public void onGlobalLayout() {
 				Point fullSize = new Point();
-				getWindowManager().getDefaultDisplay().getSize(fullSize);
+				activity.getWindowManager().getDefaultDisplay().getSize(fullSize);
 				Rect gameSize = new Rect();
 				mView.getWindowVisibleDisplayFrame(gameSize);
 
@@ -359,9 +363,9 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 					public void run() {
 						// Include the non-null views returned in the Godot view hierarchy.
 						for (int i = 0; i < singleton_count; i++) {
-							View view = singletons[i].onMainCreateView(Godot.this);
+							View view = singletons[i].onMainCreateView(activity);
 							if (view != null) {
-								layout.addView(view);
+								containerLayout.addView(view);
 							}
 						}
 					}
@@ -371,9 +375,9 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 
 		// Include the returned non-null views in the Godot view hierarchy.
 		for (GodotPlugin plugin : pluginRegistry.getAllPlugins()) {
-			View pluginView = plugin.onMainCreate(this);
+			View pluginView = plugin.onMainCreate(activity);
 			if (pluginView != null) {
-				layout.addView(pluginView);
+				containerLayout.addView(pluginView);
 			}
 		}
 	}
@@ -383,9 +387,9 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 			@Override
 			public void run() {
 				if (p_enabled) {
-					getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+					getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
 				} else {
-					getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+					getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
 				}
 			}
 		});
@@ -399,7 +403,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 	@Keep
 	private void vibrate(int durationMs) {
 		if (requestPermission("VIBRATE")) {
-			Vibrator v = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
+			Vibrator v = (Vibrator)getContext().getSystemService(Context.VIBRATOR_SERVICE);
 			if (v != null) {
 				if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
 					v.vibrate(VibrationEffect.createOneShot(durationMs, VibrationEffect.DEFAULT_AMPLITUDE));
@@ -423,13 +427,16 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 		// Using instrumentation is a way of making the whole app process restart, because Android
 		// will kill any process of the same package which was already running.
 		//
-		Bundle args = new Bundle();
-		args.putParcelable("intent", mCurrentIntent);
-		startInstrumentation(new ComponentName(this, GodotInstrumentation.class), null, args);
+		final Activity activity = getActivity();
+		if (activity != null) {
+			Bundle args = new Bundle();
+			args.putParcelable("intent", mCurrentIntent);
+			activity.startInstrumentation(new ComponentName(activity, GodotInstrumentation.class), null, args);
+		}
 	}
 
 	public void alert(final String message, final String title) {
-		final Activity activity = this;
+		final Activity activity = getActivity();
 		runOnUiThread(new Runnable() {
 			@Override
 			public void run() {
@@ -449,7 +456,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 	}
 
 	public int getGLESVersionCode() {
-		ActivityManager am = (ActivityManager)this.getSystemService(Context.ACTIVITY_SERVICE);
+		ActivityManager am = (ActivityManager)getContext().getSystemService(Context.ACTIVITY_SERVICE);
 		ConfigurationInfo deviceInfo = am.getDeviceConfigurationInfo();
 		return deviceInfo.reqGlEsVersion;
 	}
@@ -458,7 +465,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 	protected String[] getCommandLine() {
 		InputStream is;
 		try {
-			is = getAssets().open("_cl_");
+			is = getActivity().getAssets().open("_cl_");
 			byte[] len = new byte[4];
 			int r = is.read(len);
 			if (r < 4) {
@@ -538,11 +545,12 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 			command_line = new_cmdline;
 		}
 
-		io = new GodotIO(this);
-		io.unique_id = Secure.getString(getContentResolver(), Secure.ANDROID_ID);
+		final Activity activity = getActivity();
+		io = new GodotIO(activity);
+		io.unique_id = Secure.getString(activity.getContentResolver(), Secure.ANDROID_ID);
 		GodotLib.io = io;
-		netUtils = new GodotNetUtils(this);
-		mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
+		netUtils = new GodotNetUtils(activity);
+		mSensorManager = (SensorManager)activity.getSystemService(Context.SENSOR_SERVICE);
 		mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
 		mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME);
 		mGravity = mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);
@@ -552,7 +560,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 		mGyroscope = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
 		mSensorManager.registerListener(this, mGyroscope, SensorManager.SENSOR_DELAY_GAME);
 
-		GodotLib.initialize(this, getAssets(), use_apk_expansion);
+		GodotLib.initialize(activity, this, activity.getAssets(), use_apk_expansion);
 
 		result_callback = null;
 
@@ -566,151 +574,151 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 	}
 
 	@Override
-	protected void onCreate(Bundle icicle) {
-
-		super.onCreate(icicle);
-		Window window = getWindow();
+	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle icicle) {
+		final Activity activity = getActivity();
+		Window window = activity.getWindow();
 		window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
-		mClipboard = (ClipboardManager)getSystemService(Context.CLIPBOARD_SERVICE);
+		mClipboard = (ClipboardManager)activity.getSystemService(Context.CLIPBOARD_SERVICE);
 		pluginRegistry = GodotPluginRegistry.initializePluginRegistry(this);
 
 		//check for apk expansion API
-		if (true) {
-			boolean md5mismatch = false;
-			command_line = getCommandLine();
-			String main_pack_md5 = null;
-			String main_pack_key = null;
-
-			List<String> new_args = new LinkedList<String>();
-
-			for (int i = 0; i < command_line.length; i++) {
-
-				boolean has_extra = i < command_line.length - 1;
-				if (command_line[i].equals(XRMode.REGULAR.cmdLineArg)) {
-					xrMode = XRMode.REGULAR;
-				} else if (command_line[i].equals(XRMode.OVR.cmdLineArg)) {
-					xrMode = XRMode.OVR;
-				} else if (command_line[i].equals("--use_depth_32")) {
-					use_32_bits = true;
-				} else if (command_line[i].equals("--debug_opengl")) {
-					use_debug_opengl = true;
-				} else if (command_line[i].equals("--use_immersive")) {
-					use_immersive = true;
-					if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // check if the application runs on an android 4.4+
-						window.getDecorView().setSystemUiVisibility(
-								View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
-								View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
-								View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
-								View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | // hide nav bar
-								View.SYSTEM_UI_FLAG_FULLSCREEN | // hide status bar
-								View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
-
-						UiChangeListener();
-					}
-				} else if (command_line[i].equals("--use_apk_expansion")) {
-					use_apk_expansion = true;
-				} else if (has_extra && command_line[i].equals("--apk_expansion_md5")) {
-					main_pack_md5 = command_line[i + 1];
-					i++;
-				} else if (has_extra && command_line[i].equals("--apk_expansion_key")) {
-					main_pack_key = command_line[i + 1];
-					SharedPreferences prefs = getSharedPreferences("app_data_keys", MODE_PRIVATE);
-					Editor editor = prefs.edit();
-					editor.putString("store_public_key", main_pack_key);
-
-					editor.apply();
-					i++;
-				} else if (command_line[i].trim().length() != 0) {
-					new_args.add(command_line[i]);
+		boolean md5mismatch = false;
+		command_line = getCommandLine();
+		String main_pack_md5 = null;
+		String main_pack_key = null;
+
+		List<String> new_args = new LinkedList<String>();
+
+		for (int i = 0; i < command_line.length; i++) {
+
+			boolean has_extra = i < command_line.length - 1;
+			if (command_line[i].equals(XRMode.REGULAR.cmdLineArg)) {
+				xrMode = XRMode.REGULAR;
+			} else if (command_line[i].equals(XRMode.OVR.cmdLineArg)) {
+				xrMode = XRMode.OVR;
+			} else if (command_line[i].equals("--use_depth_32")) {
+				use_32_bits = true;
+			} else if (command_line[i].equals("--debug_opengl")) {
+				use_debug_opengl = true;
+			} else if (command_line[i].equals("--use_immersive")) {
+				use_immersive = true;
+				if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // check if the application runs on an android 4.4+
+					window.getDecorView().setSystemUiVisibility(
+							View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
+							View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
+							View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
+							View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | // hide nav bar
+							View.SYSTEM_UI_FLAG_FULLSCREEN | // hide status bar
+							View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
+
+					UiChangeListener();
 				}
+			} else if (command_line[i].equals("--use_apk_expansion")) {
+				use_apk_expansion = true;
+			} else if (has_extra && command_line[i].equals("--apk_expansion_md5")) {
+				main_pack_md5 = command_line[i + 1];
+				i++;
+			} else if (has_extra && command_line[i].equals("--apk_expansion_key")) {
+				main_pack_key = command_line[i + 1];
+				SharedPreferences prefs = activity.getSharedPreferences("app_data_keys",
+						MODE_PRIVATE);
+				Editor editor = prefs.edit();
+				editor.putString("store_public_key", main_pack_key);
+
+				editor.apply();
+				i++;
+			} else if (command_line[i].trim().length() != 0) {
+				new_args.add(command_line[i]);
 			}
+		}
 
-			if (new_args.isEmpty()) {
-				command_line = null;
-			} else {
+		if (new_args.isEmpty()) {
+			command_line = null;
+		} else {
 
-				command_line = new_args.toArray(new String[new_args.size()]);
+			command_line = new_args.toArray(new String[new_args.size()]);
+		}
+		if (use_apk_expansion && main_pack_md5 != null && main_pack_key != null) {
+			//check that environment is ok!
+			if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+				//show popup and die
 			}
-			if (use_apk_expansion && main_pack_md5 != null && main_pack_key != null) {
-				//check that environment is ok!
-				if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
-					//show popup and die
-				}
 
-				// Build the full path to the app's expansion files
-				try {
-					expansion_pack_path = Helpers.getSaveFilePath(getApplicationContext());
-					expansion_pack_path += "/main." + getPackageManager().getPackageInfo(getPackageName(), 0).versionCode + "." + this.getPackageName() + ".obb";
-				} catch (Exception e) {
-					e.printStackTrace();
-				}
+			// Build the full path to the app's expansion files
+			try {
+				expansion_pack_path = Helpers.getSaveFilePath(getContext());
+				expansion_pack_path += "/main." + activity.getPackageManager().getPackageInfo(activity.getPackageName(), 0).versionCode + "." + activity.getPackageName() + ".obb";
+			} catch (Exception e) {
+				e.printStackTrace();
+			}
 
-				File f = new File(expansion_pack_path);
+			File f = new File(expansion_pack_path);
 
-				boolean pack_valid = true;
+			boolean pack_valid = true;
 
-				if (!f.exists()) {
+			if (!f.exists()) {
 
-					pack_valid = false;
+				pack_valid = false;
 
-				} else if (obbIsCorrupted(expansion_pack_path, main_pack_md5)) {
-					pack_valid = false;
-					try {
-						f.delete();
-					} catch (Exception e) {
-					}
+			} else if (obbIsCorrupted(expansion_pack_path, main_pack_md5)) {
+				pack_valid = false;
+				try {
+					f.delete();
+				} catch (Exception e) {
 				}
+			}
 
-				if (!pack_valid) {
+			if (!pack_valid) {
 
-					Intent notifierIntent = new Intent(this, this.getClass());
-					notifierIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
-											Intent.FLAG_ACTIVITY_CLEAR_TOP);
+				Intent notifierIntent = new Intent(activity, activity.getClass());
+				notifierIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
+										Intent.FLAG_ACTIVITY_CLEAR_TOP);
 
-					PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
-							notifierIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+				PendingIntent pendingIntent = PendingIntent.getActivity(activity, 0,
+						notifierIntent, PendingIntent.FLAG_UPDATE_CURRENT);
 
-					int startResult;
-					try {
-						startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired(
-								getApplicationContext(),
-								pendingIntent,
+				int startResult;
+				try {
+					startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired(
+							getContext(),
+							pendingIntent,
+							GodotDownloaderService.class);
+
+					if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) {
+						// This is where you do set up to display the download
+						// progress (next step)
+						mDownloaderClientStub = DownloaderClientMarshaller.CreateStub(this,
 								GodotDownloaderService.class);
 
-						if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) {
-							// This is where you do set up to display the download
-							// progress (next step)
-							mDownloaderClientStub = DownloaderClientMarshaller.CreateStub(this,
-									GodotDownloaderService.class);
-
-							setContentView(R.layout.downloading_expansion);
-							mPB = (ProgressBar)findViewById(R.id.progressBar);
-							mStatusText = (TextView)findViewById(R.id.statusText);
-							mProgressFraction = (TextView)findViewById(R.id.progressAsFraction);
-							mProgressPercent = (TextView)findViewById(R.id.progressAsPercentage);
-							mAverageSpeed = (TextView)findViewById(R.id.progressAverageSpeed);
-							mTimeRemaining = (TextView)findViewById(R.id.progressTimeRemaining);
-							mDashboard = findViewById(R.id.downloaderDashboard);
-							mCellMessage = findViewById(R.id.approveCellular);
-							mPauseButton = (Button)findViewById(R.id.pauseButton);
-							mWiFiSettingsButton = (Button)findViewById(R.id.wifiSettingsButton);
-
-							return;
-						}
-					} catch (NameNotFoundException e) {
-						// TODO Auto-generated catch block
+						View downloadingExpansionView =
+								inflater.inflate(R.layout.downloading_expansion, container, false);
+						mPB = (ProgressBar)downloadingExpansionView.findViewById(R.id.progressBar);
+						mStatusText = (TextView)downloadingExpansionView.findViewById(R.id.statusText);
+						mProgressFraction = (TextView)downloadingExpansionView.findViewById(R.id.progressAsFraction);
+						mProgressPercent = (TextView)downloadingExpansionView.findViewById(R.id.progressAsPercentage);
+						mAverageSpeed = (TextView)downloadingExpansionView.findViewById(R.id.progressAverageSpeed);
+						mTimeRemaining = (TextView)downloadingExpansionView.findViewById(R.id.progressTimeRemaining);
+						mDashboard = downloadingExpansionView.findViewById(R.id.downloaderDashboard);
+						mCellMessage = downloadingExpansionView.findViewById(R.id.approveCellular);
+						mPauseButton = (Button)downloadingExpansionView.findViewById(R.id.pauseButton);
+						mWiFiSettingsButton = (Button)downloadingExpansionView.findViewById(R.id.wifiSettingsButton);
+
+						return downloadingExpansionView;
 					}
+				} catch (NameNotFoundException e) {
+					// TODO Auto-generated catch block
 				}
 			}
 		}
 
-		mCurrentIntent = getIntent();
+		mCurrentIntent = activity.getIntent();
 
 		initializeGodot();
+		return containerLayout;
 	}
 
 	@Override
-	protected void onDestroy() {
+	public void onDestroy() {
 
 		for (int i = 0; i < singleton_count; i++) {
 			singletons[i].onMainDestroy();
@@ -719,7 +727,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 			plugin.onMainDestroy();
 		}
 
-		GodotLib.ondestroy(this);
+		GodotLib.ondestroy();
 
 		super.onDestroy();
 
@@ -729,13 +737,13 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 	}
 
 	@Override
-	protected void onPause() {
+	public void onPause() {
 		super.onPause();
 		activityResumed = false;
 
 		if (!godot_initialized) {
 			if (null != mDownloaderClientStub) {
-				mDownloaderClientStub.disconnect(this);
+				mDownloaderClientStub.disconnect(getActivity());
 			}
 			return;
 		}
@@ -770,12 +778,12 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 	}
 
 	@Override
-	protected void onResume() {
+	public void onResume() {
 		super.onResume();
 		activityResumed = true;
 		if (!godot_initialized) {
 			if (null != mDownloaderClientStub) {
-				mDownloaderClientStub.connect(this);
+				mDownloaderClientStub.connect(getActivity());
 			}
 			return;
 		}
@@ -788,7 +796,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 		mSensorManager.registerListener(this, mGyroscope, SensorManager.SENSOR_DELAY_GAME);
 
 		if (use_immersive && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // check if the application runs on an android 4.4+
-			Window window = getWindow();
+			Window window = getActivity().getWindow();
 			window.getDecorView().setSystemUiVisibility(
 					View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
 					View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
@@ -808,7 +816,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 	}
 
 	public void UiChangeListener() {
-		final View decorView = getWindow().getDecorView();
+		final View decorView = getActivity().getWindow().getDecorView();
 		decorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {
 			@Override
 			public void onSystemUiVisibilityChange(int visibility) {
@@ -829,7 +837,8 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 
 	@Override
 	public void onSensorChanged(SensorEvent event) {
-		Display display = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
+		Display display =
+				((WindowManager)getActivity().getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
 		int displayRotation = display.getRotation();
 
 		float[] adjustedValues = new float[3];
@@ -892,7 +901,6 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 	}
 	*/
 
-	@Override
 	public void onBackPressed() {
 		boolean shouldQuit = true;
 
@@ -928,6 +936,12 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 		}
 	}
 
+	public final void runOnUiThread(@NonNull Runnable action) {
+		if (getActivity() != null) {
+			getActivity().runOnUiThread(action);
+		}
+	}
+
 	private void forceQuit() {
 		System.exit(0);
 	}
@@ -1034,17 +1048,16 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 		return true;
 	}
 
-	@Override
 	public boolean onKeyMultiple(final int inKeyCode, int repeatCount, KeyEvent event) {
 		String s = event.getCharacters();
 		if (s == null || s.length() == 0)
-			return super.onKeyMultiple(inKeyCode, repeatCount, event);
+			return false;
 
 		final char[] cc = s.toCharArray();
 		int cnt = 0;
 		for (int i = cc.length; --i >= 0; cnt += cc[i] != 0 ? 1 : 0)
 			;
-		if (cnt == 0) return super.onKeyMultiple(inKeyCode, repeatCount, event);
+		if (cnt == 0) return false;
 		mView.queueEvent(new Runnable() {
 			// This method will be called on the rendering thread:
 			public void run() {
@@ -1062,15 +1075,15 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
 	}
 
 	public boolean requestPermission(String p_name) {
-		return PermissionsUtil.requestPermission(p_name, this);
+		return PermissionsUtil.requestPermission(p_name, getActivity());
 	}
 
 	public boolean requestPermissions() {
-		return PermissionsUtil.requestManifestPermissions(this);
+		return PermissionsUtil.requestManifestPermissions(getActivity());
 	}
 
 	public String[] getGrantedPermissions() {
-		return PermissionsUtil.getGrantedPermissions(this);
+		return PermissionsUtil.getGrantedPermissions(getActivity());
 	}
 
 	/**

+ 3 - 2
platform/android/java/lib/src/org/godotengine/godot/GodotIO.java

@@ -32,6 +32,7 @@ package org.godotengine.godot;
 
 import org.godotengine.godot.input.*;
 
+import android.app.Activity;
 import android.content.*;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
@@ -52,7 +53,7 @@ import java.util.Locale;
 public class GodotIO {
 
 	AssetManager am;
-	Godot activity;
+	final Activity activity;
 	GodotEditText edit;
 
 	MediaPlayer mediaPlayer;
@@ -340,7 +341,7 @@ public class GodotIO {
 		dirs.remove(id);
 	}
 
-	GodotIO(Godot p_activity) {
+	GodotIO(Activity p_activity) {
 
 		am = p_activity.getAssets();
 		activity = p_activity;

+ 7 - 7
platform/android/java/lib/src/org/godotengine/godot/GodotLib.java

@@ -50,13 +50,13 @@ public class GodotLib {
 	/**
 	 * Invoked on the main thread to initialize Godot native layer.
 	 */
-	public static native void initialize(Godot p_instance, Object p_asset_manager, boolean use_apk_expansion);
+	public static native void initialize(Activity activity, Godot p_instance, Object p_asset_manager, boolean use_apk_expansion);
 
 	/**
 	 * Invoked on the main thread to clean up Godot native layer.
-	 * @see Activity#onDestroy()
+	 * @see androidx.fragment.app.Fragment#onDestroy()
 	 */
-	public static native void ondestroy(Godot p_instance);
+	public static native void ondestroy();
 
 	/**
 	 * Invoked on the GL thread to complete setup for the Godot native layer logic.
@@ -160,14 +160,14 @@ public class GodotLib {
 	public static native void joyconnectionchanged(int p_device, boolean p_connected, String p_name);
 
 	/**
-	 * Invoked when the Android activity resumes.
-	 * @see Activity#onResume()
+	 * Invoked when the Android app resumes.
+	 * @see androidx.fragment.app.Fragment#onResume()
 	 */
 	public static native void focusin();
 
 	/**
-	 * Invoked when the Android activity pauses.
-	 * @see Activity#onPause()
+	 * Invoked when the Android app pauses.
+	 * @see androidx.fragment.app.Fragment#onPause()
 	 */
 	public static native void focusout();
 

+ 9 - 7
platform/android/java/lib/src/org/godotengine/godot/GodotView.java

@@ -42,6 +42,7 @@ import org.godotengine.godot.xr.regular.RegularContextFactory;
 import org.godotengine.godot.xr.regular.RegularFallbackConfigChooser;
 
 import android.annotation.SuppressLint;
+import android.content.Context;
 import android.graphics.PixelFormat;
 import android.opengl.GLSurfaceView;
 import android.view.GestureDetector;
@@ -70,20 +71,21 @@ public class GodotView extends GLSurfaceView {
 
 	private static String TAG = GodotView.class.getSimpleName();
 
-	private final Godot activity;
+	private final Godot godot;
 	private final GodotInputHandler inputHandler;
 	private final GestureDetector detector;
 	private final GodotRenderer godotRenderer;
 
-	public GodotView(Godot activity, XRMode xrMode, boolean p_use_gl3, boolean p_use_32_bits, boolean p_use_debug_opengl) {
-		super(activity);
+	public GodotView(Context context, Godot godot, XRMode xrMode, boolean p_use_gl3,
+			boolean p_use_32_bits, boolean p_use_debug_opengl) {
+		super(context);
 		GLUtils.use_gl3 = p_use_gl3;
 		GLUtils.use_32 = p_use_32_bits;
 		GLUtils.use_debug_opengl = p_use_debug_opengl;
 
-		this.activity = activity;
+		this.godot = godot;
 		this.inputHandler = new GodotInputHandler(this);
-		this.detector = new GestureDetector(activity, new GodotGestureHandler(this));
+		this.detector = new GestureDetector(context, new GodotGestureHandler(this));
 		this.godotRenderer = new GodotRenderer();
 		init(xrMode, false, 16, 0);
 	}
@@ -97,7 +99,7 @@ public class GodotView extends GLSurfaceView {
 	public boolean onTouchEvent(MotionEvent event) {
 		super.onTouchEvent(event);
 		this.detector.onTouchEvent(event);
-		return activity.gotTouchEvent(event);
+		return godot.gotTouchEvent(event);
 	}
 
 	@Override
@@ -174,7 +176,7 @@ public class GodotView extends GLSurfaceView {
 	}
 
 	public void onBackPressed() {
-		activity.onBackPressed();
+		godot.onBackPressed();
 	}
 
 	@Override

+ 1 - 1
platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java

@@ -98,7 +98,7 @@ public abstract class GodotPlugin {
 	 */
 	@Nullable
 	protected Activity getActivity() {
-		return godot;
+		return godot.getActivity();
 	}
 
 	/**

+ 5 - 2
platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginRegistry.java

@@ -32,6 +32,7 @@ package org.godotengine.godot.plugin;
 
 import org.godotengine.godot.Godot;
 
+import android.app.Activity;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.os.Bundle;
@@ -122,9 +123,11 @@ public final class GodotPluginRegistry {
 
 	private void loadPlugins(Godot godot) {
 		try {
-			ApplicationInfo appInfo = godot
+			final Activity activity = godot.getActivity();
+			ApplicationInfo appInfo = activity
 											  .getPackageManager()
-											  .getApplicationInfo(godot.getPackageName(), PackageManager.GET_META_DATA);
+											  .getApplicationInfo(activity.getPackageName(),
+													  PackageManager.GET_META_DATA);
 			Bundle metaData = appInfo.metaData;
 			if (metaData == null || metaData.isEmpty()) {
 				return;

+ 2 - 3
platform/android/java/lib/src/org/godotengine/godot/utils/GodotNetUtils.java

@@ -30,8 +30,7 @@
 
 package org.godotengine.godot.utils;
 
-import org.godotengine.godot.Godot;
-
+import android.app.Activity;
 import android.content.Context;
 import android.net.wifi.WifiManager;
 import android.util.Log;
@@ -46,7 +45,7 @@ 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(Godot p_activity) {
+	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);
 			multicastLock = wifi.createMulticastLock("GodotMulticastLock");

+ 7 - 8
platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java

@@ -30,9 +30,8 @@
 
 package org.godotengine.godot.utils;
 
-import org.godotengine.godot.Godot;
-
 import android.Manifest;
+import android.app.Activity;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PermissionInfo;
@@ -66,7 +65,7 @@ public final class PermissionsUtil {
 	 * @param activity the caller activity for this method.
 	 * @return true/false. "true" if permission was granted otherwise returns "false".
 	 */
-	public static boolean requestPermission(String name, Godot activity) {
+	public static boolean requestPermission(String name, Activity activity) {
 		if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
 			// Not necessary, asked on install already
 			return true;
@@ -94,7 +93,7 @@ public final class PermissionsUtil {
 	 * @param activity the caller activity for this method.
 	 * @return true/false. "true" if all permissions were granted otherwise returns "false".
 	 */
-	public static boolean requestManifestPermissions(Godot activity) {
+	public static boolean requestManifestPermissions(Activity activity) {
 		if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
 			return true;
 		}
@@ -139,7 +138,7 @@ public final class PermissionsUtil {
 	 * @param activity the caller activity for this method.
 	 * @return granted permissions list
 	 */
-	public static String[] getGrantedPermissions(Godot activity) {
+	public static String[] getGrantedPermissions(Activity activity) {
 		String[] manifestPermissions;
 		try {
 			manifestPermissions = getManifestPermissions(activity);
@@ -173,7 +172,7 @@ public final class PermissionsUtil {
 	 * @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(Godot activity, String permission) {
+	public static boolean hasManifestPermission(Activity activity, String permission) {
 		try {
 			for (String p : getManifestPermissions(activity)) {
 				if (permission.equals(p))
@@ -191,7 +190,7 @@ public final class PermissionsUtil {
 	 * @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(Godot activity) throws PackageManager.NameNotFoundException {
+	private static String[] getManifestPermissions(Activity activity) throws PackageManager.NameNotFoundException {
 		PackageManager packageManager = activity.getPackageManager();
 		PackageInfo packageInfo = packageManager.getPackageInfo(activity.getPackageName(), PackageManager.GET_PERMISSIONS);
 		if (packageInfo.requestedPermissions == null)
@@ -206,7 +205,7 @@ public final class PermissionsUtil {
 	 * @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(Godot activity, String permission) throws PackageManager.NameNotFoundException {
+	private static PermissionInfo getPermissionInfo(Activity activity, String permission) throws PackageManager.NameNotFoundException {
 		PackageManager packageManager = activity.getPackageManager();
 		return packageManager.getPermissionInfo(permission, 0);
 	}

+ 1 - 1
platform/android/java_class_wrapper.cpp

@@ -1244,7 +1244,7 @@ JavaClassWrapper::JavaClassWrapper(jobject p_activity) {
 
 	JNIEnv *env = ThreadAndroid::get_env();
 
-	jclass activityClass = env->FindClass("org/godotengine/godot/Godot");
+	jclass activityClass = env->FindClass("android/app/Activity");
 	jmethodID getClassLoader = env->GetMethodID(activityClass, "getClassLoader", "()Ljava/lang/ClassLoader;");
 	classLoader = env->CallObjectMethod(p_activity, getClassLoader);
 	classLoader = (jclass)env->NewGlobalRef(classLoader);

+ 3 - 3
platform/android/java_godot_lib_jni.cpp

@@ -120,7 +120,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setVirtualKeyboardHei
 	}
 }
 
-JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jclass clazz, jobject activity, jobject p_asset_manager, jboolean p_use_apk_expansion) {
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jclass clazz, jobject activity, jobject godot_instance, jobject p_asset_manager, jboolean p_use_apk_expansion) {
 
 	initialized = true;
 
@@ -128,7 +128,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *en
 	env->GetJavaVM(&jvm);
 
 	// create our wrapper classes
-	godot_java = new GodotJavaWrapper(env, activity); // our activity is our godot instance is our activity..
+	godot_java = new GodotJavaWrapper(env, activity, godot_instance);
 	godot_io_java = new GodotIOJavaWrapper(env, godot_java->get_member_object("io", "Lorg/godotengine/godot/GodotIO;", env));
 
 	ThreadAndroid::make_default(jvm);
@@ -153,7 +153,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *en
 	godot_java->on_video_init(env);
 }
 
-JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_ondestroy(JNIEnv *env, jclass clazz, jobject activity) {
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_ondestroy(JNIEnv *env, jclass clazz) {
 	// lets cleanup
 	if (godot_io_java) {
 		delete godot_io_java;

+ 2 - 2
platform/android/java_godot_lib_jni.h

@@ -37,8 +37,8 @@
 // These functions can be called from within JAVA and are the means by which our JAVA implementation calls back into our C++ code.
 // See java/src/org/godotengine/godot/GodotLib.java for the JAVA side of this (yes that's why we have the long names)
 extern "C" {
-JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jclass clazz, jobject activity, jobject p_asset_manager, jboolean p_use_apk_expansion);
-JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_ondestroy(JNIEnv *env, jclass clazz, jobject activity);
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jclass clazz, jobject activity, jobject godot_instance, jobject p_asset_manager, jboolean p_use_apk_expansion);
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_ondestroy(JNIEnv *env, jclass clazz);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jclass clazz, jobjectArray p_cmdline);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, jclass clazz, jint width, jint height);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_newcontext(JNIEnv *env, jclass clazz, jboolean p_32_bits);

+ 39 - 30
platform/android/java_godot_wrapper.cpp

@@ -37,36 +37,47 @@
 
 // TODO we could probably create a base class for this...
 
-GodotJavaWrapper::GodotJavaWrapper(JNIEnv *p_env, jobject p_godot_instance) {
+GodotJavaWrapper::GodotJavaWrapper(JNIEnv *p_env, jobject p_activity, jobject p_godot_instance) {
 	godot_instance = p_env->NewGlobalRef(p_godot_instance);
+	activity = p_env->NewGlobalRef(p_activity);
 
 	// get info about our Godot class so we can get pointers and stuff...
-	cls = p_env->FindClass("org/godotengine/godot/Godot");
-	if (cls) {
-		cls = (jclass)p_env->NewGlobalRef(cls);
+	godot_class = p_env->FindClass("org/godotengine/godot/Godot");
+	if (godot_class) {
+		godot_class = (jclass)p_env->NewGlobalRef(godot_class);
+	} else {
+		// this is a pretty serious fail.. bail... pointers will stay 0
+		return;
+	}
+	activity_class = p_env->FindClass("android/app/Activity");
+	if (activity_class) {
+		activity_class = (jclass)p_env->NewGlobalRef(activity_class);
 	} else {
 		// this is a pretty serious fail.. bail... pointers will stay 0
 		return;
 	}
 
-	// get some method pointers...
-	_on_video_init = p_env->GetMethodID(cls, "onVideoInit", "()V");
-	_restart = p_env->GetMethodID(cls, "restart", "()V");
-	_finish = p_env->GetMethodID(cls, "forceQuit", "()V");
-	_set_keep_screen_on = p_env->GetMethodID(cls, "setKeepScreenOn", "(Z)V");
-	_alert = p_env->GetMethodID(cls, "alert", "(Ljava/lang/String;Ljava/lang/String;)V");
-	_get_GLES_version_code = p_env->GetMethodID(cls, "getGLESVersionCode", "()I");
-	_get_clipboard = p_env->GetMethodID(cls, "getClipboard", "()Ljava/lang/String;");
-	_set_clipboard = p_env->GetMethodID(cls, "setClipboard", "(Ljava/lang/String;)V");
-	_request_permission = p_env->GetMethodID(cls, "requestPermission", "(Ljava/lang/String;)Z");
-	_request_permissions = p_env->GetMethodID(cls, "requestPermissions", "()Z");
-	_get_granted_permissions = p_env->GetMethodID(cls, "getGrantedPermissions", "()[Ljava/lang/String;");
-	_init_input_devices = p_env->GetMethodID(cls, "initInputDevices", "()V");
-	_get_surface = p_env->GetMethodID(cls, "getSurface", "()Landroid/view/Surface;");
-	_is_activity_resumed = p_env->GetMethodID(cls, "isActivityResumed", "()Z");
-	_vibrate = p_env->GetMethodID(cls, "vibrate", "(I)V");
-	_get_input_fallback_mapping = p_env->GetMethodID(cls, "getInputFallbackMapping", "()Ljava/lang/String;");
-	_on_godot_main_loop_started = p_env->GetMethodID(cls, "onGodotMainLoopStarted", "()V");
+	// get some Godot method pointers...
+	_on_video_init = p_env->GetMethodID(godot_class, "onVideoInit", "()V");
+	_restart = p_env->GetMethodID(godot_class, "restart", "()V");
+	_finish = p_env->GetMethodID(godot_class, "forceQuit", "()V");
+	_set_keep_screen_on = p_env->GetMethodID(godot_class, "setKeepScreenOn", "(Z)V");
+	_alert = p_env->GetMethodID(godot_class, "alert", "(Ljava/lang/String;Ljava/lang/String;)V");
+	_get_GLES_version_code = p_env->GetMethodID(godot_class, "getGLESVersionCode", "()I");
+	_get_clipboard = p_env->GetMethodID(godot_class, "getClipboard", "()Ljava/lang/String;");
+	_set_clipboard = p_env->GetMethodID(godot_class, "setClipboard", "(Ljava/lang/String;)V");
+	_request_permission = p_env->GetMethodID(godot_class, "requestPermission", "(Ljava/lang/String;)Z");
+	_request_permissions = p_env->GetMethodID(godot_class, "requestPermissions", "()Z");
+	_get_granted_permissions = p_env->GetMethodID(godot_class, "getGrantedPermissions", "()[Ljava/lang/String;");
+	_init_input_devices = p_env->GetMethodID(godot_class, "initInputDevices", "()V");
+	_get_surface = p_env->GetMethodID(godot_class, "getSurface", "()Landroid/view/Surface;");
+	_is_activity_resumed = p_env->GetMethodID(godot_class, "isActivityResumed", "()Z");
+	_vibrate = p_env->GetMethodID(godot_class, "vibrate", "(I)V");
+	_get_input_fallback_mapping = p_env->GetMethodID(godot_class, "getInputFallbackMapping", "()Ljava/lang/String;");
+	_on_godot_main_loop_started = p_env->GetMethodID(godot_class, "onGodotMainLoopStarted", "()V");
+
+	// get some Activity method pointers...
+	_get_class_loader = p_env->GetMethodID(activity_class, "getClassLoader", "()Ljava/lang/ClassLoader;");
 }
 
 GodotJavaWrapper::~GodotJavaWrapper() {
@@ -74,27 +85,25 @@ GodotJavaWrapper::~GodotJavaWrapper() {
 }
 
 jobject GodotJavaWrapper::get_activity() {
-	// our godot instance is our activity
-	return godot_instance;
+	return activity;
 }
 
 jobject GodotJavaWrapper::get_member_object(const char *p_name, const char *p_class, JNIEnv *p_env) {
-	if (cls) {
+	if (godot_class) {
 		if (p_env == NULL)
 			p_env = ThreadAndroid::get_env();
 
-		jfieldID fid = p_env->GetStaticFieldID(cls, p_name, p_class);
-		return p_env->GetStaticObjectField(cls, fid);
+		jfieldID fid = p_env->GetStaticFieldID(godot_class, p_name, p_class);
+		return p_env->GetStaticObjectField(godot_class, fid);
 	} else {
 		return NULL;
 	}
 }
 
 jobject GodotJavaWrapper::get_class_loader() {
-	if (cls) {
+	if (_get_class_loader) {
 		JNIEnv *env = ThreadAndroid::get_env();
-		jmethodID getClassLoader = env->GetMethodID(cls, "getClassLoader", "()Ljava/lang/ClassLoader;");
-		return env->CallObjectMethod(godot_instance, getClassLoader);
+		return env->CallObjectMethod(godot_instance, _get_class_loader);
 	} else {
 		return NULL;
 	}

+ 5 - 2
platform/android/java_godot_wrapper.h

@@ -43,7 +43,9 @@
 class GodotJavaWrapper {
 private:
 	jobject godot_instance;
-	jclass cls;
+	jobject activity;
+	jclass godot_class;
+	jclass activity_class;
 
 	jmethodID _on_video_init = 0;
 	jmethodID _restart = 0;
@@ -62,9 +64,10 @@ private:
 	jmethodID _vibrate = 0;
 	jmethodID _get_input_fallback_mapping = 0;
 	jmethodID _on_godot_main_loop_started = 0;
+	jmethodID _get_class_loader = 0;
 
 public:
-	GodotJavaWrapper(JNIEnv *p_env, jobject p_godot_instance);
+	GodotJavaWrapper(JNIEnv *p_env, jobject p_activity, jobject p_godot_instance);
 	~GodotJavaWrapper();
 
 	jobject get_activity();