浏览代码

Merge pull request #89999 from melquiadess/prevent-potential-NPEs-and-improve-nullability-handling

Android: Prevent potential NPEs and improve nullability handling
Rémi Verschelde 1 年之前
父节点
当前提交
88f7012923

+ 60 - 53
platform/android/java/lib/src/org/godotengine/godot/Godot.kt

@@ -396,16 +396,19 @@ class Godot(private val context: Context) : SensorEventListener {
 			}
 
 			if (host == primaryHost) {
-				renderView!!.startRenderer()
+				renderView?.startRenderer()
 			}
-			val view: View = renderView!!.view
-			containerLayout?.addView(
-					view,
+
+			renderView?.let {
+				containerLayout?.addView(
+					it.view,
 					ViewGroup.LayoutParams(
 							ViewGroup.LayoutParams.MATCH_PARENT,
 							ViewGroup.LayoutParams.MATCH_PARENT
 					)
-			)
+				)
+			}
+
 			editText.setView(renderView)
 			io?.setEdit(editText)
 
@@ -448,20 +451,23 @@ class Godot(private val context: Context) : SensorEventListener {
 				})
 			} else {
 				// Infer the virtual keyboard height using visible area.
-				view.viewTreeObserver.addOnGlobalLayoutListener(object : OnGlobalLayoutListener {
+				renderView?.view?.viewTreeObserver?.addOnGlobalLayoutListener(object : OnGlobalLayoutListener {
 					// Don't allocate a new Rect every time the callback is called.
 					val visibleSize = Rect()
 					override fun onGlobalLayout() {
-						val surfaceView = renderView!!.view
-						surfaceView.getWindowVisibleDisplayFrame(visibleSize)
-						val keyboardHeight = surfaceView.height - visibleSize.bottom
-						GodotLib.setVirtualKeyboardHeight(keyboardHeight)
+						renderView?.let {
+							val surfaceView = it.view
+
+							surfaceView.getWindowVisibleDisplayFrame(visibleSize)
+							val keyboardHeight = surfaceView.height - visibleSize.bottom
+							GodotLib.setVirtualKeyboardHeight(keyboardHeight)
+						}
 					}
 				})
 			}
 
 			if (host == primaryHost) {
-				renderView!!.queueOnRenderThread {
+				renderView?.queueOnRenderThread {
 					for (plugin in pluginRegistry.allPlugins) {
 						plugin.onRegisterPluginWithGodotNative()
 					}
@@ -495,7 +501,7 @@ class Godot(private val context: Context) : SensorEventListener {
 			return
 		}
 
-		renderView!!.onActivityStarted()
+		renderView?.onActivityStarted()
 	}
 
 	fun onResume(host: GodotHost) {
@@ -503,7 +509,7 @@ class Godot(private val context: Context) : SensorEventListener {
 			return
 		}
 
-		renderView!!.onActivityResumed()
+		renderView?.onActivityResumed()
 		if (mAccelerometer != null) {
 			mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME)
 		}
@@ -535,7 +541,7 @@ class Godot(private val context: Context) : SensorEventListener {
 			return
 		}
 
-		renderView!!.onActivityPaused()
+		renderView?.onActivityPaused()
 		mSensorManager.unregisterListener(this)
 		for (plugin in pluginRegistry.allPlugins) {
 			plugin.onMainPause()
@@ -547,7 +553,7 @@ class Godot(private val context: Context) : SensorEventListener {
 			return
 		}
 
-		renderView!!.onActivityStopped()
+		renderView?.onActivityStopped()
 	}
 
 	fun onDestroy(primaryHost: GodotHost) {
@@ -569,7 +575,7 @@ class Godot(private val context: Context) : SensorEventListener {
 	 * Configuration change callback
 	*/
 	fun onConfigurationChanged(newConfig: Configuration) {
-		var newDarkMode = newConfig.uiMode?.and(Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES
+		val newDarkMode = newConfig.uiMode.and(Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES
 		if (darkMode != newDarkMode) {
 			darkMode = newDarkMode
 			GodotLib.onNightModeChanged()
@@ -686,9 +692,7 @@ class Godot(private val context: Context) : SensorEventListener {
 	 * This must be called after the render thread has started.
 	 */
 	fun runOnRenderThread(action: Runnable) {
-		if (renderView != null) {
-			renderView!!.queueOnRenderThread(action)
-		}
+		renderView?.queueOnRenderThread(action)
 	}
 
 	/**
@@ -765,7 +769,7 @@ class Godot(private val context: Context) : SensorEventListener {
 		return mClipboard.hasPrimaryClip()
 	}
 
-	fun getClipboard(): String? {
+	fun getClipboard(): String {
 		val clipData = mClipboard.primaryClip ?: return ""
 		val text = clipData.getItemAt(0).text ?: return ""
 		return text.toString()
@@ -782,15 +786,14 @@ class Godot(private val context: Context) : SensorEventListener {
 
 	@Keep
 	private fun forceQuit(instanceId: Int): Boolean {
-		if (primaryHost == null) {
-			return false
-		}
-		return if (instanceId == 0) {
-			primaryHost!!.onGodotForceQuit(this)
-			true
-		} else {
-			primaryHost!!.onGodotForceQuit(instanceId)
-		}
+		primaryHost?.let {
+			if (instanceId == 0) {
+				it.onGodotForceQuit(this)
+				return true
+			} else {
+				return it.onGodotForceQuit(instanceId)
+			}
+		} ?: return false
 	}
 
 	fun onBackPressed(host: GodotHost) {
@@ -804,14 +807,14 @@ class Godot(private val context: Context) : SensorEventListener {
 				shouldQuit = false
 			}
 		}
-		if (shouldQuit && renderView != null) {
-			renderView!!.queueOnRenderThread { GodotLib.back() }
+		if (shouldQuit) {
+			renderView?.queueOnRenderThread { GodotLib.back() }
 		}
 	}
 
 	private fun getRotatedValues(values: FloatArray?): FloatArray? {
 		if (values == null || values.size != 3) {
-			return values
+			return null
 		}
 		val display =
 			(requireActivity().getSystemService(Context.WINDOW_SERVICE) as WindowManager).defaultDisplay
@@ -848,35 +851,39 @@ class Godot(private val context: Context) : SensorEventListener {
 		}
 		when (event.sensor.type) {
 			Sensor.TYPE_ACCELEROMETER -> {
-				val rotatedValues = getRotatedValues(event.values)
-				renderView!!.queueOnRenderThread {
-					GodotLib.accelerometer(
-						-rotatedValues!![0], -rotatedValues[1], -rotatedValues[2]
-					)
+				getRotatedValues(event.values)?.let { rotatedValues ->
+					renderView?.queueOnRenderThread {
+						GodotLib.accelerometer(
+							-rotatedValues[0], -rotatedValues[1], -rotatedValues[2]
+						)
+					}
 				}
 			}
 			Sensor.TYPE_GRAVITY -> {
-				val rotatedValues = getRotatedValues(event.values)
-				renderView!!.queueOnRenderThread {
-					GodotLib.gravity(
-						-rotatedValues!![0], -rotatedValues[1], -rotatedValues[2]
-					)
+				getRotatedValues(event.values)?.let { rotatedValues ->
+					renderView?.queueOnRenderThread {
+						GodotLib.gravity(
+							-rotatedValues[0], -rotatedValues[1], -rotatedValues[2]
+						)
+					}
 				}
 			}
 			Sensor.TYPE_MAGNETIC_FIELD -> {
-				val rotatedValues = getRotatedValues(event.values)
-				renderView!!.queueOnRenderThread {
-					GodotLib.magnetometer(
-						-rotatedValues!![0], -rotatedValues[1], -rotatedValues[2]
-					)
+				getRotatedValues(event.values)?.let { rotatedValues ->
+					renderView?.queueOnRenderThread {
+						GodotLib.magnetometer(
+							-rotatedValues[0], -rotatedValues[1], -rotatedValues[2]
+						)
+					}
 				}
 			}
 			Sensor.TYPE_GYROSCOPE -> {
-				val rotatedValues = getRotatedValues(event.values)
-				renderView!!.queueOnRenderThread {
-					GodotLib.gyroscope(
-						rotatedValues!![0], rotatedValues[1], rotatedValues[2]
-					)
+				getRotatedValues(event.values)?.let { rotatedValues ->
+					renderView?.queueOnRenderThread {
+						GodotLib.gyroscope(
+							rotatedValues[0], rotatedValues[1], rotatedValues[2]
+						)
+					}
 				}
 			}
 		}
@@ -1039,7 +1046,7 @@ class Godot(private val context: Context) : SensorEventListener {
 
 	@Keep
 	private fun initInputDevices() {
-		renderView!!.initInputDevices()
+		renderView?.initInputDevices()
 	}
 
 	@Keep

+ 18 - 13
platform/android/java/lib/src/org/godotengine/godot/GodotActivity.kt

@@ -83,8 +83,9 @@ abstract class GodotActivity : FragmentActivity(), GodotHost {
 	override fun onDestroy() {
 		Log.v(TAG, "Destroying Godot app...")
 		super.onDestroy()
-		if (godotFragment != null) {
-			terminateGodotInstance(godotFragment!!.godot)
+
+		godotFragment?.let {
+			terminateGodotInstance(it.godot)
 		}
 	}
 
@@ -93,22 +94,26 @@ abstract class GodotActivity : FragmentActivity(), GodotHost {
 	}
 
 	private fun terminateGodotInstance(instance: Godot) {
-		if (godotFragment != null && instance === godotFragment!!.godot) {
-			Log.v(TAG, "Force quitting Godot instance")
-			ProcessPhoenix.forceQuit(this)
+		godotFragment?.let {
+			if (instance === it.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)
+			godotFragment?.let {
+				if (instance === it.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)
+				}
 			}
 		}
 	}

+ 19 - 11
platform/android/java/lib/src/org/godotengine/godot/io/file/FileAccessHandler.kt

@@ -56,7 +56,9 @@ class FileAccessHandler(val context: Context) {
 			}
 
 			return try {
-				DataAccess.fileExists(storageScope, context, path!!)
+				path?.let {
+					DataAccess.fileExists(storageScope, context, it)
+				} ?: false
 			} catch (e: SecurityException) {
 				false
 			}
@@ -69,20 +71,22 @@ class FileAccessHandler(val context: Context) {
 			}
 
 			return try {
-				DataAccess.removeFile(storageScope, context, path!!)
+				path?.let {
+					DataAccess.removeFile(storageScope, context, it)
+				} ?: false
 			} catch (e: Exception) {
 				false
 			}
 		}
 
-		internal fun renameFile(context: Context, storageScopeIdentifier: StorageScope.Identifier, from: String?, to: String?): Boolean {
+		internal fun renameFile(context: Context, storageScopeIdentifier: StorageScope.Identifier, from: String, to: String): Boolean {
 			val storageScope = storageScopeIdentifier.identifyStorageScope(from)
 			if (storageScope == StorageScope.UNKNOWN) {
 				return false
 			}
 
 			return try {
-				DataAccess.renameFile(storageScope, context, from!!, to!!)
+				DataAccess.renameFile(storageScope, context, from, to)
 			} catch (e: Exception) {
 				false
 			}
@@ -106,16 +110,18 @@ class FileAccessHandler(val context: Context) {
 			return INVALID_FILE_ID
 		}
 
-		try {
-			val dataAccess = DataAccess.generateDataAccess(storageScope, context, path!!, accessFlag) ?: return INVALID_FILE_ID
+		return try {
+			path?.let {
+				val dataAccess = DataAccess.generateDataAccess(storageScope, context, it, accessFlag) ?: return INVALID_FILE_ID
 
-			files.put(++lastFileId, dataAccess)
-			return lastFileId
+				files.put(++lastFileId, dataAccess)
+				lastFileId
+			} ?: INVALID_FILE_ID
 		} catch (e: FileNotFoundException) {
-			return FILE_NOT_FOUND_ERROR_ID
+			FILE_NOT_FOUND_ERROR_ID
 		} catch (e: Exception) {
 			Log.w(TAG, "Error while opening $path", e)
-			return INVALID_FILE_ID
+			INVALID_FILE_ID
 		}
 	}
 
@@ -176,7 +182,9 @@ class FileAccessHandler(val context: Context) {
 		}
 
 		return try {
-			DataAccess.fileLastModified(storageScope, context, filepath!!)
+			filepath?.let {
+				DataAccess.fileLastModified(storageScope, context, it)
+			} ?: 0L
 		} catch (e: SecurityException) {
 			0L
 		}