From 5c8372a56603f185c6b193d05dea3cfb0130d59c Mon Sep 17 00:00:00 2001 From: Charles Lombardo Date: Sat, 11 Mar 2023 00:33:51 -0500 Subject: [PATCH] android: Convert MainActivity to Kotlin --- .../yuzu/yuzu_emu/ui/main/MainActivity.java | 249 ------------------ .../org/yuzu/yuzu_emu/ui/main/MainActivity.kt | 228 ++++++++++++++++ .../app/src/main/res/values/strings.xml | 2 +- 3 files changed, 229 insertions(+), 250 deletions(-) delete mode 100644 src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.java create mode 100644 src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.java b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.java deleted file mode 100644 index d5009bc60..000000000 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.java +++ /dev/null @@ -1,249 +0,0 @@ -package org.yuzu.yuzu_emu.ui.main; - -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.widget.Toast; - -import androidx.annotation.NonNull; -import androidx.appcompat.app.AlertDialog; -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.widget.Toolbar; - -import org.yuzu.yuzu_emu.NativeLibrary; -import org.yuzu.yuzu_emu.R; -import org.yuzu.yuzu_emu.activities.EmulationActivity; -import org.yuzu.yuzu_emu.features.settings.ui.SettingsActivity; -import org.yuzu.yuzu_emu.model.GameProvider; -import org.yuzu.yuzu_emu.ui.platform.PlatformGamesFragment; -import org.yuzu.yuzu_emu.utils.AddDirectoryHelper; -import org.yuzu.yuzu_emu.utils.DirectoryInitialization; -import org.yuzu.yuzu_emu.utils.FileBrowserHelper; -import org.yuzu.yuzu_emu.utils.FileUtil; -import org.yuzu.yuzu_emu.utils.GpuDriverHelper; -import org.yuzu.yuzu_emu.utils.PicassoUtils; -import org.yuzu.yuzu_emu.utils.StartupHandler; -import org.yuzu.yuzu_emu.utils.ThemeUtil; - -/** - * The main Activity of the Lollipop style UI. Manages several PlatformGamesFragments, which - * individually display a grid of available games for each Fragment, in a tabbed layout. - */ -public final class MainActivity extends AppCompatActivity implements MainView { - private Toolbar mToolbar; - private int mFrameLayoutId; - private PlatformGamesFragment mPlatformGamesFragment; - - private MainPresenter mPresenter = new MainPresenter(this); - - @Override - protected void onCreate(Bundle savedInstanceState) { - ThemeUtil.applyTheme(); - - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - - findViews(); - - setSupportActionBar(mToolbar); - - mFrameLayoutId = R.id.games_platform_frame; - mPresenter.onCreate(); - - if (savedInstanceState == null) { - StartupHandler.handleInit(this); - mPlatformGamesFragment = new PlatformGamesFragment(); - getSupportFragmentManager().beginTransaction().add(mFrameLayoutId, mPlatformGamesFragment).commit(); - } else { - mPlatformGamesFragment = (PlatformGamesFragment) getSupportFragmentManager().getFragment(savedInstanceState, "mPlatformGamesFragment"); - } - PicassoUtils.init(); - - // Dismiss previous notifications (should not happen unless a crash occurred) - EmulationActivity.tryDismissRunningNotification(this); - } - - @Override - protected void onSaveInstanceState(@NonNull Bundle outState) { - super.onSaveInstanceState(outState); - if (getSupportFragmentManager() == null) { - return; - } - if (outState == null) { - return; - } - getSupportFragmentManager().putFragment(outState, "mPlatformGamesFragment", mPlatformGamesFragment); - } - - @Override - protected void onResume() { - super.onResume(); - mPresenter.addDirIfNeeded(new AddDirectoryHelper(this)); - } - - // TODO: Replace with a ButterKnife injection. - private void findViews() { - mToolbar = findViewById(R.id.toolbar_main); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.menu_game_grid, menu); - - return true; - } - - /** - * MainView - */ - - @Override - public void setVersionString(String version) { - mToolbar.setSubtitle(version); - } - - @Override - public void refresh() { - getContentResolver().insert(GameProvider.URI_REFRESH, null); - refreshFragment(); - } - - @Override - public void launchSettingsActivity(String menuTag) { - SettingsActivity.launch(this, menuTag, ""); - } - - @Override - public void launchFileListActivity(int request) { - switch (request) { - case MainPresenter.REQUEST_ADD_DIRECTORY: - FileBrowserHelper.openDirectoryPicker(this, - MainPresenter.REQUEST_ADD_DIRECTORY, - R.string.select_game_folder); - break; - case MainPresenter.REQUEST_INSTALL_KEYS: - FileBrowserHelper.openFilePicker(this, - MainPresenter.REQUEST_INSTALL_KEYS, - R.string.install_keys); - break; - case MainPresenter.REQUEST_SELECT_GPU_DRIVER: - AlertDialog.Builder builder = new AlertDialog.Builder(this); - - // Get the driver name for the dialog message. - String driverName = GpuDriverHelper.getCustomDriverName(); - if (driverName == null) { - driverName = getString(R.string.system_gpu_driver); - } - - // Set the dialog message and title. - builder.setTitle(getString(R.string.select_gpu_driver_title)); - builder.setMessage(driverName); - - // Cancel button is a no-op. - builder.setNegativeButton(android.R.string.cancel, null); - - // Select the default system driver. - builder.setPositiveButton(R.string.select_gpu_driver_default, (dialogInterface, i) -> - { - GpuDriverHelper.installDefaultDriver(this); - Toast.makeText(this, R.string.select_gpu_driver_use_default, Toast.LENGTH_SHORT).show(); - }); - - // Use the file picker to install a custom driver. - builder.setNeutralButton(R.string.select_gpu_driver_install, (dialogInterface, i) -> { - FileBrowserHelper.openFilePicker(this, - MainPresenter.REQUEST_SELECT_GPU_DRIVER, - R.string.select_gpu_driver); - }); - - // Show the dialog. - AlertDialog alertDialog = builder.create(); - alertDialog.show(); - - break; - } - } - - /** - * @param requestCode An int describing whether the Activity that is returning did so successfully. - * @param resultCode An int describing what Activity is giving us this callback. - * @param result The information the returning Activity is providing us. - */ - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent result) { - super.onActivityResult(requestCode, resultCode, result); - switch (requestCode) { - case MainPresenter.REQUEST_ADD_DIRECTORY: - if (resultCode == MainActivity.RESULT_OK) { - int takeFlags = (Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION); - getContentResolver().takePersistableUriPermission(Uri.parse(result.getDataString()), takeFlags); - // When a new directory is picked, we currently will reset the existing games - // database. This effectively means that only one game directory is supported. - // TODO(bunnei): Consider fixing this in the future, or removing code for this. - getContentResolver().insert(GameProvider.URI_RESET, null); - // Add the new directory - mPresenter.onDirectorySelected(FileBrowserHelper.getSelectedDirectory(result)); - } - break; - - case MainPresenter.REQUEST_INSTALL_KEYS: - if (resultCode == MainActivity.RESULT_OK) { - int takeFlags = (Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION); - getContentResolver().takePersistableUriPermission(Uri.parse(result.getDataString()), takeFlags); - String dstPath = DirectoryInitialization.getUserDirectory() + "/keys/"; - if (FileUtil.copyUriToInternalStorage(this, result.getData(), dstPath, "prod.keys")) { - if (NativeLibrary.ReloadKeys()) { - Toast.makeText(this, R.string.install_keys_success, Toast.LENGTH_SHORT).show(); - refreshFragment(); - } else { - Toast.makeText(this, R.string.install_keys_failure, Toast.LENGTH_LONG).show(); - launchFileListActivity(MainPresenter.REQUEST_INSTALL_KEYS); - } - } - } - break; - - case MainPresenter.REQUEST_SELECT_GPU_DRIVER: - if (resultCode == MainActivity.RESULT_OK) { - int takeFlags = (Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION); - getContentResolver().takePersistableUriPermission(Uri.parse(result.getDataString()), takeFlags); - GpuDriverHelper.installCustomDriver(this, result.getData()); - String driverName = GpuDriverHelper.getCustomDriverName(); - if (driverName != null) { - Toast.makeText(this, getString(R.string.select_gpu_driver_install_success) + " " + driverName, Toast.LENGTH_SHORT).show(); - } else { - Toast.makeText(this, R.string.select_gpu_driver_error, Toast.LENGTH_LONG).show(); - } - } - break; - } - } - - /** - * Called by the framework whenever any actionbar/toolbar icon is clicked. - * - * @param item The icon that was clicked on. - * @return True if the event was handled, false to bubble it up to the OS. - */ - @Override - public boolean onOptionsItemSelected(MenuItem item) { - return mPresenter.handleOptionSelection(item.getItemId()); - } - - private void refreshFragment() { - if (mPlatformGamesFragment != null) { - NativeLibrary.ResetRomMetadata(); - mPlatformGamesFragment.refresh(); - } - } - - @Override - protected void onDestroy() { - EmulationActivity.tryDismissRunningNotification(this); - super.onDestroy(); - } -} diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt new file mode 100644 index 000000000..6ea5fed27 --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt @@ -0,0 +1,228 @@ +package org.yuzu.yuzu_emu.ui.main + +import android.content.DialogInterface +import android.content.Intent +import android.net.Uri +import android.os.Bundle +import android.view.Menu +import android.view.MenuItem +import android.widget.Toast +import androidx.appcompat.app.AppCompatActivity +import androidx.appcompat.widget.Toolbar +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import org.yuzu.yuzu_emu.NativeLibrary +import org.yuzu.yuzu_emu.R +import org.yuzu.yuzu_emu.activities.EmulationActivity +import org.yuzu.yuzu_emu.features.settings.ui.SettingsActivity +import org.yuzu.yuzu_emu.model.GameProvider +import org.yuzu.yuzu_emu.ui.platform.PlatformGamesFragment +import org.yuzu.yuzu_emu.utils.* + +class MainActivity : AppCompatActivity(), MainView { + private lateinit var toolbar: Toolbar + private var platformGamesFragment: PlatformGamesFragment? = null + private val presenter = MainPresenter(this) + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + findViews() + setSupportActionBar(toolbar) + presenter.onCreate() + if (savedInstanceState == null) { + StartupHandler.handleInit(this) + platformGamesFragment = PlatformGamesFragment() + supportFragmentManager.beginTransaction() + .add(R.id.games_platform_frame, platformGamesFragment!!) + .commit() + } else { + platformGamesFragment = supportFragmentManager.getFragment( + savedInstanceState, + PlatformGamesFragment.TAG + ) as PlatformGamesFragment? + } + PicassoUtils.init() + + // Dismiss previous notifications (should not happen unless a crash occurred) + EmulationActivity.tryDismissRunningNotification(this) + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + supportFragmentManager.putFragment( + outState, + PlatformGamesFragment.TAG, + platformGamesFragment!! + ) + } + + override fun onResume() { + super.onResume() + presenter.addDirIfNeeded(AddDirectoryHelper(this)) + } + + // TODO: Replace with view binding + private fun findViews() { + toolbar = findViewById(R.id.toolbar_main) + } + + override fun onCreateOptionsMenu(menu: Menu): Boolean { + menuInflater.inflate(R.menu.menu_game_grid, menu) + return true + } + + /** + * MainView + */ + override fun setVersionString(version: String) { + toolbar.subtitle = version + } + + override fun refresh() { + contentResolver.insert(GameProvider.URI_REFRESH, null) + refreshFragment() + } + + override fun launchSettingsActivity(menuTag: String) { + SettingsActivity.launch(this, menuTag, "") + } + + override fun launchFileListActivity(request: Int) { + when (request) { + MainPresenter.REQUEST_ADD_DIRECTORY -> FileBrowserHelper.openDirectoryPicker( + this, + MainPresenter.REQUEST_ADD_DIRECTORY, + R.string.select_game_folder + ) + MainPresenter.REQUEST_INSTALL_KEYS -> FileBrowserHelper.openFilePicker( + this, + MainPresenter.REQUEST_INSTALL_KEYS, + R.string.install_keys + ) + MainPresenter.REQUEST_SELECT_GPU_DRIVER -> { + // Get the driver name for the dialog message. + var driverName = GpuDriverHelper.customDriverName + if (driverName == null) { + driverName = getString(R.string.system_gpu_driver) + } + + MaterialAlertDialogBuilder(this) + .setTitle(getString(R.string.select_gpu_driver_title)) + .setMessage(driverName) + .setNegativeButton(android.R.string.cancel, null) + .setPositiveButton(R.string.select_gpu_driver_default) { _: DialogInterface?, _: Int -> + GpuDriverHelper.installDefaultDriver(this) + Toast.makeText( + this, + R.string.select_gpu_driver_use_default, + Toast.LENGTH_SHORT + ).show() + } + .setNeutralButton(R.string.select_gpu_driver_install) { _: DialogInterface?, _: Int -> + FileBrowserHelper.openFilePicker( + this, + MainPresenter.REQUEST_SELECT_GPU_DRIVER, + R.string.select_gpu_driver + ) + } + .show() + } + } + } + + /** + * @param requestCode An int describing whether the Activity that is returning did so successfully. + * @param resultCode An int describing what Activity is giving us this callback. + * @param result The information the returning Activity is providing us. + */ + override fun onActivityResult(requestCode: Int, resultCode: Int, result: Intent?) { + super.onActivityResult(requestCode, resultCode, result) + when (requestCode) { + MainPresenter.REQUEST_ADD_DIRECTORY -> if (resultCode == RESULT_OK) { + val takeFlags = + Intent.FLAG_GRANT_WRITE_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION + contentResolver.takePersistableUriPermission( + Uri.parse(result!!.dataString), + takeFlags + ) + // When a new directory is picked, we currently will reset the existing games + // database. This effectively means that only one game directory is supported. + // TODO(bunnei): Consider fixing this in the future, or removing code for this. + contentResolver.insert(GameProvider.URI_RESET, null) + // Add the new directory + presenter.onDirectorySelected(FileBrowserHelper.getSelectedDirectory(result)) + } + MainPresenter.REQUEST_INSTALL_KEYS -> if (resultCode == RESULT_OK) { + val takeFlags = + Intent.FLAG_GRANT_WRITE_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION + contentResolver.takePersistableUriPermission( + Uri.parse(result!!.dataString), + takeFlags + ) + val dstPath = DirectoryInitialization.userDirectory + "/keys/" + if (FileUtil.copyUriToInternalStorage(this, result.data, dstPath, "prod.keys")) { + if (NativeLibrary.ReloadKeys()) { + Toast.makeText( + this, + R.string.install_keys_success, + Toast.LENGTH_SHORT + ).show() + refreshFragment() + } else { + Toast.makeText( + this, + R.string.install_keys_failure, + Toast.LENGTH_LONG + ).show() + launchFileListActivity(MainPresenter.REQUEST_INSTALL_KEYS) + } + } + } + MainPresenter.REQUEST_SELECT_GPU_DRIVER -> if (resultCode == RESULT_OK) { + val takeFlags = + Intent.FLAG_GRANT_WRITE_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION + contentResolver.takePersistableUriPermission( + Uri.parse(result!!.dataString), + takeFlags + ) + GpuDriverHelper.installCustomDriver(this, result.data) + val driverName = GpuDriverHelper.customDriverName + if (driverName != null) { + Toast.makeText( + this, + getString(R.string.select_gpu_driver_install_success, driverName), + Toast.LENGTH_SHORT + ).show() + } else { + Toast.makeText( + this, + R.string.select_gpu_driver_error, + Toast.LENGTH_LONG + ).show() + } + } + } + } + + /** + * Called by the framework whenever any actionbar/toolbar icon is clicked. + * + * @param item The icon that was clicked on. + * @return True if the event was handled, false to bubble it up to the OS. + */ + override fun onOptionsItemSelected(item: MenuItem): Boolean { + return presenter.handleOptionSelection(item.itemId) + } + + private fun refreshFragment() { + if (platformGamesFragment != null) { + NativeLibrary.ResetRomMetadata() + platformGamesFragment!!.refresh() + } + } + + override fun onDestroy() { + EmulationActivity.tryDismissRunningNotification(this) + super.onDestroy() + } +} diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 7ef6b803e..fbf8fe9c1 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -64,7 +64,7 @@ Would you like to replace your current GPU driver? Install Default - Installed + Installed %s Using default GPU driver Invalid driver selected, using system default! System GPU driver