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