mirror of
https://github.com/jpd002/Play-.git
synced 2025-04-28 13:47:57 +03:00
650 lines
19 KiB
Java
650 lines
19 KiB
Java
package com.virtualapplications.play;
|
|
|
|
import android.Manifest;
|
|
import android.app.*;
|
|
import android.app.AlertDialog;
|
|
import android.app.ProgressDialog;
|
|
import android.content.*;
|
|
import android.content.pm.*;
|
|
import android.content.res.Configuration;
|
|
import android.graphics.Color;
|
|
import android.graphics.drawable.GradientDrawable;
|
|
import android.net.Uri;
|
|
import android.os.*;
|
|
|
|
import androidx.annotation.NonNull;
|
|
import androidx.documentfile.provider.DocumentFile;
|
|
import androidx.preference.PreferenceManager;
|
|
import androidx.core.app.ActivityCompat;
|
|
import androidx.core.content.ContextCompat;
|
|
import androidx.appcompat.app.*;
|
|
import androidx.appcompat.app.ActionBar;
|
|
import androidx.appcompat.widget.Toolbar;
|
|
|
|
import android.util.Log;
|
|
import android.view.*;
|
|
import android.view.View;
|
|
import android.widget.*;
|
|
import android.widget.GridView;
|
|
|
|
import java.net.URLDecoder;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.text.*;
|
|
import java.util.*;
|
|
|
|
import com.virtualapplications.play.database.GameIndexer;
|
|
import com.virtualapplications.play.database.GameInfo;
|
|
|
|
import static com.virtualapplications.play.BootablesInterop.PurgeInexistingFiles;
|
|
import static com.virtualapplications.play.BootablesInterop.UnregisterBootable;
|
|
import static com.virtualapplications.play.BootablesInterop.getBootables;
|
|
import static com.virtualapplications.play.BootablesInterop.setLastBootedTime;
|
|
import static com.virtualapplications.play.BootablesInterop.SORT_RECENT;
|
|
import static com.virtualapplications.play.BootablesInterop.SORT_HOMEBREW;
|
|
import static com.virtualapplications.play.BootablesInterop.SORT_NONE;
|
|
import static com.virtualapplications.play.Constants.PREF_UI_CLEAR_UNAVAILABLE;
|
|
import static com.virtualapplications.play.Constants.PREF_UI_MIGRATE_DATA_FILES;
|
|
import static com.virtualapplications.play.Constants.PREF_UI_RESCAN;
|
|
import static com.virtualapplications.play.ThemeManager.getThemeColor;
|
|
|
|
public class MainActivity extends AppCompatActivity implements NavigationDrawerFragment.NavigationDrawerCallbacks, SharedPreferences.OnSharedPreferenceChangeListener
|
|
{
|
|
private static final String PREF_ANDROID11_USER_NOTIFIED = "android11_user_notified";
|
|
|
|
private int currentOrientation;
|
|
private GameInfo gameInfo;
|
|
protected NavigationDrawerFragment mNavigationDrawerFragment;
|
|
private List<Bootable> currentGames = new ArrayList<>();
|
|
private int sortMethod = SORT_NONE;
|
|
private String navSubtitle;
|
|
private Toolbar toolbar;
|
|
|
|
static final int g_settingsRequestCode = 0xDEAD;
|
|
static final int g_folderPickerRequestCode = 0xBEEF;
|
|
static final int g_dataFilesFolderPickerRequestCode = 0xBEF0;
|
|
|
|
@Override
|
|
protected void onCreate(Bundle savedInstanceState)
|
|
{
|
|
super.onCreate(savedInstanceState);
|
|
//Log.w(Constants.TAG, "MainActivity - onCreate");
|
|
|
|
currentOrientation = getResources().getConfiguration().orientation;
|
|
|
|
ThemeManager.applyTheme(this, toolbar);
|
|
if(isAndroidTV(this))
|
|
{
|
|
setContentView(R.layout.tele);
|
|
}
|
|
else
|
|
{
|
|
setContentView(R.layout.main);
|
|
}
|
|
|
|
// if (isAndroidTV(this)) {
|
|
// // Load the menus for Android TV
|
|
// } else {
|
|
toolbar = findViewById(R.id.main_toolbar);
|
|
setSupportActionBar(toolbar);
|
|
toolbar.bringToFront();
|
|
setUIcolor();
|
|
|
|
mNavigationDrawerFragment = (NavigationDrawerFragment)
|
|
getFragmentManager().findFragmentById(R.id.navigation_drawer);
|
|
|
|
// Set up the drawer.
|
|
mNavigationDrawerFragment.setUp(
|
|
R.id.navigation_drawer,
|
|
findViewById(R.id.drawer_layout));
|
|
|
|
int attributeResourceId = getThemeColor(this, R.attr.colorPrimaryDark);
|
|
findViewById(R.id.navigation_drawer).setBackgroundColor(Color.parseColor(
|
|
("#" + Integer.toHexString(attributeResourceId)).replace("#ff", "#8e")
|
|
));
|
|
// }
|
|
|
|
//We can't request WRITE_EXTERNAL_STORAGE permission on SDK < 33 (we don't necessarily need it anyways)
|
|
if((Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) && (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED))
|
|
{
|
|
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, Constants.READ_WRITE_PERMISSION);
|
|
}
|
|
else
|
|
{
|
|
Startup();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onDestroy()
|
|
{
|
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
|
prefs.unregisterOnSharedPreferenceChangeListener(this);
|
|
super.onDestroy();
|
|
}
|
|
|
|
private void Startup()
|
|
{
|
|
NativeInterop.setFilesDirPath(getApplicationContext().getFilesDir().getAbsolutePath());
|
|
NativeInterop.setCacheDirPath(getApplicationContext().getCacheDir().getAbsolutePath());
|
|
NativeInterop.setAssetManager(getAssets());
|
|
NativeInterop.setContentResolver(getApplicationContext().getContentResolver());
|
|
|
|
EmulatorActivity.RegisterPreferences();
|
|
|
|
if(!NativeInterop.isVirtualMachineCreated())
|
|
{
|
|
NativeInterop.createVirtualMachine();
|
|
}
|
|
|
|
gameInfo = new GameInfo(MainActivity.this);
|
|
|
|
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
|
|
sortMethod = sp.getInt("sortMethod.v2", SORT_NONE);
|
|
onNavigationDrawerItemSelected(sortMethod);
|
|
sp.registerOnSharedPreferenceChangeListener(this);
|
|
|
|
Intent intent = getIntent();
|
|
if(intent.getAction() != null && intent.getAction().equals(Intent.ACTION_VIEW))
|
|
{
|
|
try
|
|
{
|
|
Uri uri = intent.getData();
|
|
VirtualMachineManager.launchGame(this, uri.toString(), this::finish);
|
|
}
|
|
catch(Exception e)
|
|
{
|
|
displaySimpleMessage("Error", e.getMessage());
|
|
finish();
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
|
|
{
|
|
if(requestCode == Constants.READ_WRITE_PERMISSION)
|
|
{// If request is cancelled, the result arrays are empty.
|
|
if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
|
|
{
|
|
Startup();
|
|
}
|
|
else
|
|
{
|
|
new AlertDialog.Builder(this)
|
|
.setTitle(R.string.permission_dialog_title)
|
|
.setMessage(R.string.permission_dialog_summary)
|
|
.setPositiveButton(android.R.string.ok, (dialog, id) ->
|
|
finish()
|
|
)
|
|
.create()
|
|
.show();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void setUIcolor()
|
|
{
|
|
View content = findViewById(R.id.content_frame);
|
|
if(content != null)
|
|
{
|
|
int[] colors = new int[2];// you can increase array size to add more colors to gradient.
|
|
int topgradientcolor = getThemeColor(this, R.attr.colorPrimary);
|
|
|
|
float[] hsv = new float[3];
|
|
Color.colorToHSV(topgradientcolor, hsv);
|
|
hsv[2] *= 0.8f;// make it darker
|
|
colors[0] = Color.HSVToColor(hsv);
|
|
/*
|
|
using this will blend the top of the gradient with actionbar (aka using the same color)
|
|
colors[0] = topgradientcolor
|
|
*/
|
|
colors[1] = Color.rgb(20, 20, 20);
|
|
GradientDrawable gradientbg = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, colors);
|
|
content.setBackground(gradientbg);
|
|
}
|
|
int attributeResourceId = getThemeColor(this, R.attr.colorPrimaryDark);
|
|
findViewById(R.id.navigation_drawer).setBackgroundColor(Color.parseColor(
|
|
("#" + Integer.toHexString(attributeResourceId)).replace("#ff", "#8e")
|
|
));
|
|
}
|
|
|
|
private void displaySimpleMessage(String title, String message)
|
|
{
|
|
new AlertDialog.Builder(this)
|
|
.setTitle(title)
|
|
.setMessage(message)
|
|
.setPositiveButton(android.R.string.ok, null)
|
|
.create()
|
|
.show();
|
|
}
|
|
|
|
private void displayGameNotFound(final Bootable game)
|
|
{
|
|
new AlertDialog.Builder(this)
|
|
.setTitle(R.string.not_found)
|
|
.setMessage(R.string.game_unavailable)
|
|
.setPositiveButton(android.R.string.ok, (dialog, id) -> {
|
|
UnregisterBootable(game.path);
|
|
prepareFileListView(false);
|
|
})
|
|
.setNegativeButton(android.R.string.cancel, null)
|
|
.create()
|
|
.show();
|
|
}
|
|
|
|
private void displaySettingsActivity()
|
|
{
|
|
Intent intent = new Intent(getApplicationContext(), SettingsActivity.class);
|
|
startActivityForResult(intent, g_settingsRequestCode);
|
|
}
|
|
|
|
private void displayFolderPicker()
|
|
{
|
|
try
|
|
{
|
|
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
|
|
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
|
intent.addFlags(Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
|
|
intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
|
|
intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
|
|
startActivityForResult(intent, g_folderPickerRequestCode);
|
|
}
|
|
catch(Exception ex)
|
|
{
|
|
displaySimpleMessage("Error", String.format("Error occurred while trying to use ACTION_OPEN_DOCUMENT_TREE intent:\n%s", ex.toString()));
|
|
}
|
|
}
|
|
|
|
protected void onActivityResult(int requestCode, int resultCode, Intent data)
|
|
{
|
|
super.onActivityResult(requestCode, resultCode, data);
|
|
if(requestCode == g_settingsRequestCode)
|
|
{
|
|
ThemeManager.applyTheme(this, toolbar);
|
|
setUIcolor();
|
|
}
|
|
|
|
if(requestCode == 1 && resultCode == RESULT_OK)
|
|
{
|
|
if(data != null)
|
|
{
|
|
gameInfo.removeBitmapFromMemCache(data.getStringExtra("indexid"));
|
|
}
|
|
prepareFileListView(false);
|
|
}
|
|
|
|
if(requestCode == g_folderPickerRequestCode && resultCode == RESULT_OK)
|
|
{
|
|
Uri folderUri = data.getData();
|
|
getContentResolver().takePersistableUriPermission(folderUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
|
prepareFileListView(false);
|
|
}
|
|
|
|
if(requestCode == g_dataFilesFolderPickerRequestCode && resultCode == RESULT_OK)
|
|
{
|
|
Uri folderUri = data.getData();
|
|
executeDataFilesMigration(folderUri);
|
|
}
|
|
}
|
|
|
|
private void displayAboutDialog()
|
|
{
|
|
Date buildDate = BuildConfig.buildTime;
|
|
String buildDateString = new SimpleDateFormat("yyyy/MM/dd K:mm a", Locale.getDefault()).format(buildDate);
|
|
String timestamp = buildDateString.substring(11).startsWith("0:")
|
|
? buildDateString.replace("0:", "12:") : buildDateString;
|
|
String aboutMessage = String.format(getString(R.string.about_play_emu) + "\n\n" + getString(R.string.about_play_version) + " %s\n" + getString(R.string.about_play_date) + " %s\n\n" + getString(R.string.about_play_founder) + "\nJean-Philip Desjardins", BuildConfig.VERSION_NAME, timestamp);
|
|
displaySimpleMessage(getString(R.string.about_play), aboutMessage);
|
|
}
|
|
|
|
@Override
|
|
public void onConfigurationChanged(@NonNull Configuration newConfig)
|
|
{
|
|
super.onConfigurationChanged(newConfig);
|
|
mNavigationDrawerFragment.onConfigurationChanged(newConfig);
|
|
if(newConfig.orientation != currentOrientation)
|
|
{
|
|
currentOrientation = newConfig.orientation;
|
|
setUIcolor();
|
|
prepareFileListView(currentGames != null && !currentGames.isEmpty());
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onNavigationDrawerItemSelected(int position)
|
|
{
|
|
switch(position)
|
|
{
|
|
case SORT_RECENT:
|
|
sortMethod = SORT_RECENT;
|
|
navSubtitle = getString(R.string.file_list_recent);
|
|
break;
|
|
case SORT_HOMEBREW:
|
|
sortMethod = SORT_HOMEBREW;
|
|
navSubtitle = getString(R.string.file_list_homebrew);
|
|
break;
|
|
case SORT_NONE:
|
|
default:
|
|
sortMethod = SORT_NONE;
|
|
navSubtitle = getString(R.string.file_list_default);
|
|
break;
|
|
}
|
|
|
|
ActionBar actionbar = getSupportActionBar();
|
|
if(actionbar != null)
|
|
{
|
|
actionbar.setSubtitle(getString(R.string.menu_title_shut) + " - " + navSubtitle);
|
|
}
|
|
|
|
prepareFileListView(false);
|
|
|
|
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
|
|
sp.edit().putInt("sortMethod.v2", sortMethod).apply();
|
|
}
|
|
|
|
@Override
|
|
public void onNavigationDrawerBottomItemSelected(int position)
|
|
{
|
|
switch(position)
|
|
{
|
|
case 0:
|
|
displaySettingsActivity();
|
|
break;
|
|
case 1:
|
|
displayFolderPicker();
|
|
break;
|
|
case 2:
|
|
displayAboutDialog();
|
|
break;
|
|
}
|
|
}
|
|
|
|
public void restoreActionBar()
|
|
{
|
|
ActionBar actionBar = getSupportActionBar();
|
|
actionBar.setDisplayShowTitleEnabled(true);
|
|
actionBar.setTitle(R.string.app_name);
|
|
actionBar.setSubtitle(getString(R.string.menu_title_shut) + " - " + navSubtitle);
|
|
}
|
|
|
|
public boolean onCreateOptionsMenu(Menu menu)
|
|
{
|
|
if(!mNavigationDrawerFragment.isDrawerOpen())
|
|
{
|
|
// Only show items in the action bar relevant to this screen
|
|
// if the drawer is not showing. Otherwise, let the drawer
|
|
// decide what to show in the action bar.
|
|
//getMenuInflater().inflate(R.menu.main, menu);
|
|
restoreActionBar();
|
|
return true;
|
|
}
|
|
return super.onCreateOptionsMenu(menu);
|
|
}
|
|
|
|
@Override
|
|
public void onBackPressed()
|
|
{
|
|
if(NavigationDrawerFragment.mDrawerLayout != null && mNavigationDrawerFragment.isDrawerOpen())
|
|
{
|
|
NavigationDrawerFragment.mDrawerLayout.closeDrawer(NavigationDrawerFragment.mFragmentContainerView);
|
|
return;
|
|
}
|
|
super.onBackPressed();
|
|
finish();
|
|
}
|
|
|
|
@Override
|
|
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)
|
|
{
|
|
if(key.equals(PREF_UI_RESCAN))
|
|
{
|
|
if(sharedPreferences.getBoolean(PREF_UI_RESCAN, false))
|
|
{
|
|
sharedPreferences.edit().putBoolean(PREF_UI_RESCAN, false).apply();
|
|
prepareFileListView(false, true);
|
|
}
|
|
}
|
|
else if(key.equals(PREF_UI_CLEAR_UNAVAILABLE))
|
|
{
|
|
if(sharedPreferences.getBoolean(PREF_UI_CLEAR_UNAVAILABLE, false))
|
|
{
|
|
sharedPreferences.edit().putBoolean(PREF_UI_CLEAR_UNAVAILABLE, false).apply();
|
|
PurgeInexistingFiles();
|
|
prepareFileListView(false);
|
|
}
|
|
}
|
|
else if(key.equals(PREF_UI_MIGRATE_DATA_FILES))
|
|
{
|
|
if(sharedPreferences.getBoolean(PREF_UI_MIGRATE_DATA_FILES, false))
|
|
{
|
|
sharedPreferences.edit().putBoolean(PREF_UI_MIGRATE_DATA_FILES, false).apply();
|
|
selectDataFilesFolderToMigrate();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void scanContentFolder(DocumentFile folderDoc)
|
|
{
|
|
for(DocumentFile fileDoc : folderDoc.listFiles())
|
|
{
|
|
try
|
|
{
|
|
if(fileDoc.isDirectory())
|
|
{
|
|
scanContentFolder(fileDoc);
|
|
}
|
|
else
|
|
{
|
|
String docUriString = fileDoc.getUri().toString();
|
|
if(!BootablesInterop.tryRegisterBootable(docUriString))
|
|
{
|
|
Log.w(Constants.TAG, String.format("scanContentFolder: Failed to register '%s'.", docUriString));
|
|
}
|
|
else
|
|
{
|
|
Log.w(Constants.TAG, String.format("scanContentFolder: Registered '%s'.", docUriString));
|
|
}
|
|
}
|
|
}
|
|
catch(Exception ex)
|
|
{
|
|
Log.w(Constants.TAG, String.format("scanContentFolder: Error while processing '%s': %s", fileDoc.getUri().toString(), ex.toString()));
|
|
}
|
|
}
|
|
}
|
|
|
|
private final class ImageFinder extends AsyncTask<String, Integer, List<Bootable>>
|
|
{
|
|
private final boolean fullscan;
|
|
private ProgressDialog progDialog;
|
|
|
|
public ImageFinder(boolean fullscan)
|
|
{
|
|
this.fullscan = fullscan;
|
|
}
|
|
|
|
@Override
|
|
protected void onPreExecute()
|
|
{
|
|
progDialog = ProgressDialog.show(MainActivity.this,
|
|
getString(R.string.search_games),
|
|
getString(R.string.search_games_msg), true);
|
|
}
|
|
|
|
void updateProgressText(String progressText)
|
|
{
|
|
runOnUiThread(new Runnable()
|
|
{
|
|
@Override
|
|
public void run()
|
|
{
|
|
progDialog.setMessage(progressText);
|
|
}
|
|
});
|
|
}
|
|
|
|
@Override
|
|
protected List<Bootable> doInBackground(String... paths)
|
|
{
|
|
//With scoped storage on Android 30, it's not possible to scan the device's filesystem
|
|
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.R)
|
|
{
|
|
updateProgressText(getString(R.string.search_games_scanning));
|
|
if(fullscan)
|
|
{
|
|
GameIndexer.fullScan();
|
|
}
|
|
else
|
|
{
|
|
GameIndexer.startupScan();
|
|
}
|
|
}
|
|
|
|
List<UriPermission> uriPermissions = getContentResolver().getPersistedUriPermissions();
|
|
if(!uriPermissions.isEmpty())
|
|
{
|
|
updateProgressText(getString(R.string.search_games_scan_folders));
|
|
|
|
for(UriPermission uriPermission : uriPermissions)
|
|
{
|
|
DocumentFile folderDoc = DocumentFile.fromTreeUri(MainActivity.this, uriPermission.getUri());
|
|
scanContentFolder(folderDoc);
|
|
}
|
|
|
|
updateProgressText(getString(R.string.search_games_fetching_titles));
|
|
BootablesInterop.fetchGameTitles();
|
|
}
|
|
|
|
updateProgressText(getString(R.string.search_games_fetching));
|
|
Bootable[] bootables = getBootables(sortMethod);
|
|
|
|
return new ArrayList<>(Arrays.asList(bootables));
|
|
}
|
|
|
|
@Override
|
|
protected void onPostExecute(List<Bootable> images)
|
|
{
|
|
updateProgressText(getString(R.string.search_games_populating));
|
|
|
|
currentGames = images;
|
|
// Create the list of acceptable images
|
|
populateImages(images);
|
|
|
|
if(progDialog != null && progDialog.isShowing())
|
|
{
|
|
try
|
|
{
|
|
progDialog.dismiss();
|
|
}
|
|
catch(final Exception e)
|
|
{
|
|
//We don't really care if we get an exception while dismissing
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void populateImages(List<Bootable> images)
|
|
{
|
|
GridView gameGrid = findViewById(R.id.game_grid);
|
|
if(gameGrid != null)
|
|
{
|
|
gameGrid.setAdapter(null);
|
|
if(isAndroidTV(this))
|
|
{
|
|
gameGrid.setOnItemClickListener((parent, v, position, id) -> v.performClick());
|
|
}
|
|
if(images == null || images.isEmpty())
|
|
{
|
|
// Display warning that no disks exist
|
|
ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, (sortMethod == SORT_RECENT) ? new String[]{getString(R.string.no_recent_adapter)} : new String[]{getString(R.string.no_game_found_adapter)});
|
|
gameGrid.setNumColumns(1);
|
|
gameGrid.setAdapter(adapter);
|
|
}
|
|
else
|
|
{
|
|
GamesAdapter adapter = new GamesAdapter(this, R.layout.game_list_item, images, gameInfo);
|
|
/*
|
|
-1 = autofit
|
|
*/
|
|
gameGrid.setNumColumns(-1);
|
|
gameGrid.setColumnWidth((int)getResources().getDimension(R.dimen.cover_width));
|
|
|
|
gameGrid.setAdapter(adapter);
|
|
gameGrid.invalidate();
|
|
}
|
|
}
|
|
}
|
|
|
|
public void launchGame(Bootable game)
|
|
{
|
|
if(BootablesInterop.DoesBootableExist(game.path))
|
|
{
|
|
setLastBootedTime(game.path, System.currentTimeMillis());
|
|
try
|
|
{
|
|
VirtualMachineManager.launchGame(this, game.path, null);
|
|
}
|
|
catch(Exception e)
|
|
{
|
|
displaySimpleMessage("Error", e.getMessage());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
displayGameNotFound(game);
|
|
}
|
|
}
|
|
|
|
private boolean isAndroidTV(Context context)
|
|
{
|
|
UiModeManager uiModeManager = (UiModeManager)
|
|
context.getSystemService(Context.UI_MODE_SERVICE);
|
|
return uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION;
|
|
}
|
|
|
|
public void prepareFileListView(boolean retainList)
|
|
{
|
|
prepareFileListView(retainList, false);
|
|
}
|
|
|
|
private void prepareFileListView(boolean retainList, boolean fullscan)
|
|
{
|
|
if(gameInfo == null)
|
|
{
|
|
gameInfo = new GameInfo(MainActivity.this);
|
|
}
|
|
|
|
if(retainList)
|
|
{
|
|
populateImages(currentGames);
|
|
}
|
|
else
|
|
{
|
|
new ImageFinder(fullscan).execute();
|
|
}
|
|
}
|
|
|
|
private void selectDataFilesFolderToMigrate()
|
|
{
|
|
new AlertDialog.Builder(this)
|
|
.setTitle(getString(R.string.migration_title))
|
|
.setMessage(getString(R.string.migration_selectfolder))
|
|
.setPositiveButton(android.R.string.ok, (dialog, id) -> {
|
|
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
|
|
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
|
intent.addFlags(Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
|
|
intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
|
|
intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
|
|
startActivityForResult(intent, g_dataFilesFolderPickerRequestCode);
|
|
})
|
|
.create()
|
|
.show();
|
|
}
|
|
|
|
private void executeDataFilesMigration(Uri dataFilesFolderUri)
|
|
{
|
|
DataFilesMigrationProcessTask task = new DataFilesMigrationProcessTask(this, dataFilesFolderUri);
|
|
task.execute();
|
|
}
|
|
}
|