committed by
bunnei
3 changed files with 229 additions and 250 deletions
-
249src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.java
-
228src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt
-
2src/android/app/src/main/res/values/strings.xml
@ -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(); |
|
||||
} |
|
||||
} |
|
||||
@ -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() |
||||
|
} |
||||
|
} |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue