Compare commits

...

4 Commits

Author SHA1 Message Date
OatmealDome
0e92a14703
Merge pull request #14488 from Simonx22/android/convert-permissionshandler-to-kotlin
Android: Convert PermissionsHandler to Kotlin
2026-03-21 12:14:53 -04:00
OatmealDome
d572931213
Merge pull request #14487 from Simonx22/android/convert-insetshelper-to-kotlin
Android: Convert InsetsHelper to Kotlin
2026-03-21 12:14:40 -04:00
Simonx22
385ac49109 Android: Convert PermissionsHandler to Kotlin 2026-03-20 13:01:54 -04:00
Simonx22
b4933d3799 Android: Convert InsetsHelper to Kotlin 2026-03-20 12:59:27 -04:00
4 changed files with 151 additions and 153 deletions

View File

@ -1,72 +0,0 @@
package org.dolphinemu.dolphinemu.utils;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Rect;
import android.view.View;
import android.view.ViewGroup;
import androidx.core.graphics.Insets;
import com.google.android.material.appbar.AppBarLayout;
public class InsetsHelper
{
public static final int THREE_BUTTON_NAVIGATION = 0;
public static final int TWO_BUTTON_NAVIGATION = 1;
public static final int GESTURE_NAVIGATION = 2;
public static void insetAppBar(Insets insets, AppBarLayout appBarLayout)
{
ViewGroup.MarginLayoutParams mlpAppBar =
(ViewGroup.MarginLayoutParams) appBarLayout.getLayoutParams();
mlpAppBar.leftMargin = insets.left;
mlpAppBar.topMargin = insets.top;
mlpAppBar.rightMargin = insets.right;
appBarLayout.setLayoutParams(mlpAppBar);
}
// Workaround for a bug on Android 13 that allows users to interact with UI behind the
// navigation bar https://issuetracker.google.com/issues/248761842
public static void applyNavbarWorkaround(int bottomInset, View workaroundView)
{
if (bottomInset > 0)
{
ViewGroup.LayoutParams lpWorkaround = workaroundView.getLayoutParams();
lpWorkaround.height = bottomInset;
workaroundView.setLayoutParams(lpWorkaround);
}
}
public static int getSystemGestureType(Context context)
{
Resources resources = context.getResources();
int resourceId = resources.getIdentifier("config_navBarInteractionMode", "integer", "android");
if (resourceId != 0)
{
return resources.getInteger(resourceId);
}
return 0;
}
public static int getNavigationBarHeight(Context context)
{
Resources resources = context.getResources();
int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
if (resourceId > 0)
{
return resources.getDimensionPixelSize(resourceId);
}
return 0;
}
// This is primarily intended to account for any navigation bar at the bottom of the screen
public static int getBottomPaddingRequired(Activity activity)
{
Rect visibleFrame = new Rect();
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(visibleFrame);
return visibleFrame.bottom - visibleFrame.top -
activity.getResources().getDisplayMetrics().heightPixels;
}
}

View File

@ -0,0 +1,67 @@
package org.dolphinemu.dolphinemu.utils
import android.app.Activity
import android.content.Context
import android.content.res.Resources
import android.graphics.Rect
import android.view.View
import android.view.ViewGroup
import androidx.core.graphics.Insets
import com.google.android.material.appbar.AppBarLayout
object InsetsHelper {
const val THREE_BUTTON_NAVIGATION = 0
const val TWO_BUTTON_NAVIGATION = 1
const val GESTURE_NAVIGATION = 2
@JvmStatic
fun insetAppBar(insets: Insets, appBarLayout: AppBarLayout) {
val mlpAppBar = appBarLayout.layoutParams as ViewGroup.MarginLayoutParams
mlpAppBar.leftMargin = insets.left
mlpAppBar.topMargin = insets.top
mlpAppBar.rightMargin = insets.right
appBarLayout.layoutParams = mlpAppBar
}
// Workaround for a bug on Android 13 that allows users to interact with UI behind the
// navigation bar https://issuetracker.google.com/issues/248761842
@JvmStatic
fun applyNavbarWorkaround(bottomInset: Int, workaroundView: View) {
if (bottomInset > 0) {
val lpWorkaround = workaroundView.layoutParams
lpWorkaround.height = bottomInset
workaroundView.layoutParams = lpWorkaround
}
}
@JvmStatic
fun getSystemGestureType(context: Context): Int {
val resources: Resources = context.resources
val resourceId =
resources.getIdentifier("config_navBarInteractionMode", "integer", "android")
return if (resourceId != 0) {
resources.getInteger(resourceId)
} else {
0
}
}
@JvmStatic
fun getNavigationBarHeight(context: Context): Int {
val resources: Resources = context.resources
val resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android")
return if (resourceId > 0) {
resources.getDimensionPixelSize(resourceId)
} else {
0
}
}
// This is primarily intended to account for any navigation bar at the bottom of the screen
@JvmStatic
fun getBottomPaddingRequired(activity: Activity): Int {
val visibleFrame = Rect()
activity.window.decorView.getWindowVisibleDisplayFrame(visibleFrame)
return visibleFrame.bottom - visibleFrame.top - activity.resources.displayMetrics.heightPixels
}
}

View File

@ -1,81 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.utils;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Environment;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentActivity;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
import static android.Manifest.permission.RECORD_AUDIO;
import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.DolphinApplication;
import org.dolphinemu.dolphinemu.NativeLibrary;
public class PermissionsHandler
{
public static final int REQUEST_CODE_WRITE_PERMISSION = 500;
public static final int REQUEST_CODE_RECORD_AUDIO = 501;
private static boolean sWritePermissionDenied = false;
public static void requestWritePermission(final FragmentActivity activity)
{
activity.requestPermissions(new String[]{WRITE_EXTERNAL_STORAGE},
REQUEST_CODE_WRITE_PERMISSION);
}
public static boolean hasWriteAccess(Context context)
{
if (!isExternalStorageLegacy())
return false;
int hasWritePermission = ContextCompat.checkSelfPermission(context, WRITE_EXTERNAL_STORAGE);
return hasWritePermission == PackageManager.PERMISSION_GRANTED;
}
public static boolean isExternalStorageLegacy()
{
return Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || Environment.isExternalStorageLegacy();
}
public static void setWritePermissionDenied()
{
sWritePermissionDenied = true;
}
public static boolean isWritePermissionDenied()
{
return sWritePermissionDenied;
}
public static boolean hasRecordAudioPermission(Context context)
{
if (context == null)
context = DolphinApplication.getAppContext();
int hasRecordPermission = ContextCompat.checkSelfPermission(context, RECORD_AUDIO);
return hasRecordPermission == PackageManager.PERMISSION_GRANTED;
}
public static void requestRecordAudioPermission(Activity activity)
{
if (activity == null)
{
// Calling from C++ code
activity = DolphinApplication.getAppActivity();
// Since the emulation (and cubeb) has already started, enabling the microphone permission
// now might require restarting the game to be effective. Warn the user about it.
NativeLibrary.displayAlertMsg(
activity.getString(R.string.wii_speak_permission_warning),
activity.getString(R.string.wii_speak_permission_warning_description),
false, true, false);
}
activity.requestPermissions(new String[]{RECORD_AUDIO}, REQUEST_CODE_RECORD_AUDIO);
}
}

View File

@ -0,0 +1,84 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.utils
import android.Manifest
import android.app.Activity
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import android.os.Environment
import androidx.core.content.ContextCompat
import androidx.fragment.app.FragmentActivity
import org.dolphinemu.dolphinemu.DolphinApplication
import org.dolphinemu.dolphinemu.NativeLibrary
import org.dolphinemu.dolphinemu.R
object PermissionsHandler {
const val REQUEST_CODE_WRITE_PERMISSION = 500
const val REQUEST_CODE_RECORD_AUDIO = 501
private var writePermissionDenied = false
@JvmStatic
fun requestWritePermission(activity: FragmentActivity) {
activity.requestPermissions(
arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), REQUEST_CODE_WRITE_PERMISSION
)
}
@JvmStatic
fun hasWriteAccess(context: Context): Boolean {
if (!isExternalStorageLegacy()) {
return false
}
val hasWritePermission =
ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE)
return hasWritePermission == PackageManager.PERMISSION_GRANTED
}
@JvmStatic
fun isExternalStorageLegacy(): Boolean {
return Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || Environment.isExternalStorageLegacy()
}
@JvmStatic
fun setWritePermissionDenied() {
writePermissionDenied = true
}
@JvmStatic
fun isWritePermissionDenied(): Boolean {
return writePermissionDenied
}
@JvmStatic
fun hasRecordAudioPermission(context: Context?): Boolean {
val nonNullContext = context ?: DolphinApplication.getAppContext()
val hasRecordPermission =
ContextCompat.checkSelfPermission(nonNullContext, Manifest.permission.RECORD_AUDIO)
return hasRecordPermission == PackageManager.PERMISSION_GRANTED
}
@JvmStatic
fun requestRecordAudioPermission(activity: Activity?) {
val targetActivity = activity ?: DolphinApplication.getAppActivity()!!
if (activity == null) {
// Calling from C++ code
// Since the emulation (and cubeb) has already started, enabling the microphone permission
// now might require restarting the game to be effective. Warn the user about it.
NativeLibrary.displayAlertMsg(
targetActivity.getString(R.string.wii_speak_permission_warning),
targetActivity.getString(R.string.wii_speak_permission_warning_description),
false,
true,
false
)
}
targetActivity.requestPermissions(
arrayOf(Manifest.permission.RECORD_AUDIO), REQUEST_CODE_RECORD_AUDIO
)
}
}