Skip to content

Commit

Permalink
Android: Add online system update functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
Simonx22 authored and OatmealDome committed Jan 21, 2022
1 parent 8ad1292 commit 55378ca
Show file tree
Hide file tree
Showing 13 changed files with 548 additions and 15 deletions.
1 change: 0 additions & 1 deletion Source/Android/app/src/main/AndroidManifest.xml
Expand Up @@ -155,4 +155,3 @@
</application>

</manifest>

Expand Up @@ -9,7 +9,6 @@
import android.graphics.Rect;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.util.SparseIntArray;
import android.view.InputDevice;
import android.view.KeyEvent;
Expand Down Expand Up @@ -80,12 +79,14 @@ public final class EmulationActivity extends AppCompatActivity
private boolean activityRecreated;
private String[] mPaths;
private boolean mRiivolution;
private boolean mLaunchSystemMenu;
private boolean mIgnoreWarnings;
private static boolean sUserPausedEmulation;
private boolean mMenuToastShown;

public static final String EXTRA_SELECTED_GAMES = "SelectedGames";
public static final String EXTRA_RIIVOLUTION = "Riivolution";
public static final String EXTRA_SYSTEM_MENU = "SystemMenu";
public static final String EXTRA_IGNORE_WARNINGS = "IgnoreWarnings";
public static final String EXTRA_USER_PAUSED_EMULATION = "sUserPausedEmulation";
public static final String EXTRA_MENU_TOAST_SHOWN = "MenuToastShown";
Expand Down Expand Up @@ -171,11 +172,9 @@ public static void launch(FragmentActivity activity, String filePath, boolean ri
launch(activity, new String[]{filePath}, riivolution);
}

public static void launch(FragmentActivity activity, String[] filePaths, boolean riivolution)
private static void performLaunchChecks(FragmentActivity activity,
Runnable continueCallback)
{
if (sIgnoreLaunchRequests)
return;

new AfterDirectoryInitializationRunner().runWithLifecycle(activity, true, () ->
{
if (FileBrowserHelper.isPathEmptyOrValid(StringSetting.MAIN_DEFAULT_ISO) &&
Expand All @@ -185,7 +184,7 @@ public static void launch(FragmentActivity activity, String[] filePaths, boolean
FileBrowserHelper.isPathEmptyOrValid(StringSetting.MAIN_RESOURCEPACK_PATH) &&
FileBrowserHelper.isPathEmptyOrValid(StringSetting.MAIN_SD_PATH))
{
launchWithoutChecks(activity, filePaths, riivolution);
continueCallback.run();
}
else
{
Expand All @@ -194,12 +193,44 @@ public static void launch(FragmentActivity activity, String[] filePaths, boolean
builder.setPositiveButton(R.string.yes, (dialogInterface, i) ->
SettingsActivity.launch(activity, MenuTag.CONFIG_PATHS));
builder.setNeutralButton(R.string.continue_anyway, (dialogInterface, i) ->
launchWithoutChecks(activity, filePaths, riivolution));
continueCallback.run());
builder.show();
}
});
}


public static void launchSystemMenu(FragmentActivity activity)
{
if (sIgnoreLaunchRequests)
return;

performLaunchChecks(activity, () ->
{
launchSystemMenuWithoutChecks(activity);
});
}

public static void launch(FragmentActivity activity, String[] filePaths, boolean riivolution)
{
if (sIgnoreLaunchRequests)
return;

performLaunchChecks(activity, () ->
{
launchWithoutChecks(activity, filePaths, riivolution);
});
}

private static void launchSystemMenuWithoutChecks(FragmentActivity activity)
{
sIgnoreLaunchRequests = true;

Intent launcher = new Intent(activity, EmulationActivity.class);
launcher.putExtra(EmulationActivity.EXTRA_SYSTEM_MENU, true);
activity.startActivity(launcher);
}

private static void launchWithoutChecks(FragmentActivity activity, String[] filePaths,
boolean riivolution)
{
Expand Down Expand Up @@ -256,6 +287,7 @@ protected void onCreate(Bundle savedInstanceState)
Intent gameToEmulate = getIntent();
mPaths = gameToEmulate.getStringArrayExtra(EXTRA_SELECTED_GAMES);
mRiivolution = gameToEmulate.getBooleanExtra(EXTRA_RIIVOLUTION, false);
mLaunchSystemMenu = gameToEmulate.getBooleanExtra(EXTRA_SYSTEM_MENU, false);
mIgnoreWarnings = gameToEmulate.getBooleanExtra(EXTRA_IGNORE_WARNINGS, false);
sUserPausedEmulation = gameToEmulate.getBooleanExtra(EXTRA_USER_PAUSED_EMULATION, false);
mMenuToastShown = false;
Expand Down Expand Up @@ -288,7 +320,7 @@ protected void onCreate(Bundle savedInstanceState)
.findFragmentById(R.id.frame_emulation_fragment);
if (mEmulationFragment == null)
{
mEmulationFragment = EmulationFragment.newInstance(mPaths, mRiivolution);
mEmulationFragment = EmulationFragment.newInstance(mPaths, mRiivolution, mLaunchSystemMenu);
getSupportFragmentManager().beginTransaction()
.add(R.id.frame_emulation_fragment, mEmulationFragment)
.commit();
Expand Down
@@ -0,0 +1,110 @@
package org.dolphinemu.dolphinemu.features.sysupdate.ui;

import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.pm.ActivityInfo;
import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
import androidx.lifecycle.ViewModelProvider;

import org.dolphinemu.dolphinemu.R;

public class OnlineUpdateProgressBarDialogFragment extends DialogFragment
{
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState)
{
// Store the current orientation to be restored later
final int orientation = getActivity().getRequestedOrientation();
// Rotating the device while the update is running can result in a title failing to import.
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);

SystemUpdateViewModel viewModel =
new ViewModelProvider(requireActivity()).get(SystemUpdateViewModel.class);

ProgressDialog progressDialog = new ProgressDialog(requireContext());
progressDialog.setTitle(getString(R.string.updating));
// We need to set the message to something here, otherwise the text will not appear when we set it later.
progressDialog.setMessage("");
progressDialog.setButton(Dialog.BUTTON_NEGATIVE, getString(R.string.cancel), (dialog, i) ->
{
});
progressDialog.setOnShowListener((dialogInterface) ->
{
// By default, the ProgressDialog will immediately dismiss itself upon a button being pressed.
// Setting the OnClickListener again after the dialog is shown overrides this behavior.
progressDialog.getButton(Dialog.BUTTON_NEGATIVE).setOnClickListener((view) ->
{
viewModel.setCanceled();
});
});
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);

viewModel.getProgressData().observe(this, (@Nullable Integer progress) ->
{
progressDialog.setProgress(progress.intValue());
});

viewModel.getTotalData().observe(this, (@Nullable Integer total) ->
{
if (total == 0)
{
return;
}

progressDialog.setMax(total.intValue());
});

viewModel.getTitleIdData().observe(this, (@Nullable Long titleId) ->
{
progressDialog.setMessage(getString(R.string.updating_message, titleId));
});

viewModel.getResultData().observe(this, (@Nullable Integer result) ->
{
if (result == -1)
{
// This is the default value, ignore
return;
}

OnlineUpdateResultFragment progressBarFragment = new OnlineUpdateResultFragment();
progressBarFragment.show(getParentFragmentManager(), "OnlineUpdateResultFragment");

getActivity().setRequestedOrientation(orientation);

dismiss();
});

if (savedInstanceState == null)
{
final String region;
int selectedItem = viewModel.getRegion();

switch (selectedItem)
{
case 0:
region = "EUR";
break;
case 1:
region = "JPN";
break;
case 2:
region = "KOR";
break;
case 3:
region = "USA";
break;
default:
region = "";
break;
}
viewModel.startUpdate(region);
}
return progressDialog;
}
}
@@ -0,0 +1,42 @@
package org.dolphinemu.dolphinemu.features.sysupdate.ui;

import android.app.Dialog;
import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;
import androidx.lifecycle.ViewModelProvider;

import org.dolphinemu.dolphinemu.R;

public class OnlineUpdateRegionSelectDialogFragment extends DialogFragment
{
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState)
{
String[] items = {getString(R.string.europe), getString(
R.string.japan), getString(R.string.korea), getString(R.string.united_states)};
int checkedItem = -1;

return new AlertDialog.Builder(requireContext(), R.style.DolphinDialogBase)
.setTitle(R.string.region_select_title)
.setSingleChoiceItems(items, checkedItem, (dialog, which) ->
{
SystemUpdateViewModel viewModel =
new ViewModelProvider(requireActivity()).get(SystemUpdateViewModel.class);
viewModel.setRegion(which);

OnlineUpdateProgressBarDialogFragment progressBarFragment =
new OnlineUpdateProgressBarDialogFragment();
progressBarFragment
.show(getParentFragmentManager(), "OnlineUpdateProgressBarDialogFragment");
progressBarFragment.setCancelable(false);

dismiss();
})
.create();
}
}
@@ -0,0 +1,105 @@
package org.dolphinemu.dolphinemu.features.sysupdate.ui;

import android.app.Dialog;
import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;
import androidx.lifecycle.ViewModelProvider;

import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.utils.WiiUtils;

public class OnlineUpdateResultFragment extends DialogFragment
{
private int mResult;

@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
SystemUpdateViewModel viewModel =
new ViewModelProvider(requireActivity()).get(SystemUpdateViewModel.class);
if (savedInstanceState == null)
{
mResult = viewModel.getResultData().getValue().intValue();
viewModel.clear();
}
else
{
mResult = savedInstanceState.getInt("result");
}

String message;
switch (mResult)
{
case WiiUtils.UPDATE_RESULT_SUCCESS:
message = getString(R.string.update_success);
break;
case WiiUtils.UPDATE_RESULT_ALREADY_UP_TO_DATE:
message = getString(R.string.already_up_to_date);
break;
case WiiUtils.UPDATE_RESULT_REGION_MISMATCH:
message = getString(R.string.region_mismatch);
break;
case WiiUtils.UPDATE_RESULT_MISSING_UPDATE_PARTITION:
message = getString(R.string.missing_update_partition);
break;
case WiiUtils.UPDATE_RESULT_DISC_READ_FAILED:
message = getString(R.string.disc_read_failed);
break;
case WiiUtils.UPDATE_RESULT_SERVER_FAILED:
message = getString(R.string.server_failed);
break;
case WiiUtils.UPDATE_RESULT_DOWNLOAD_FAILED:
message = getString(R.string.download_failed);
break;
case WiiUtils.UPDATE_RESULT_IMPORT_FAILED:
message = getString(R.string.import_failed);
break;
case WiiUtils.UPDATE_RESULT_CANCELLED:
message = getString(R.string.update_cancelled);
break;
default:
throw new IllegalStateException("Unexpected value: " + mResult);
}

String title;
switch (mResult)
{
case WiiUtils.UPDATE_RESULT_SUCCESS:
case WiiUtils.UPDATE_RESULT_ALREADY_UP_TO_DATE:
title = getString(R.string.update_success_title);
break;
case WiiUtils.UPDATE_RESULT_REGION_MISMATCH:
case WiiUtils.UPDATE_RESULT_MISSING_UPDATE_PARTITION:
case WiiUtils.UPDATE_RESULT_DISC_READ_FAILED:
case WiiUtils.UPDATE_RESULT_SERVER_FAILED:
case WiiUtils.UPDATE_RESULT_DOWNLOAD_FAILED:
case WiiUtils.UPDATE_RESULT_IMPORT_FAILED:
title = getString(R.string.update_failed_title);
break;
case WiiUtils.UPDATE_RESULT_CANCELLED:
title = getString(R.string.update_cancelled_title);
break;
default:
throw new IllegalStateException("Unexpected value: " + mResult);
}

return new AlertDialog.Builder(requireContext(), R.style.DolphinDialogBase)
.setTitle(title)
.setMessage(message)
.setPositiveButton(R.string.ok, (dialog, which) ->
{
dismiss();
})
.create();
}

@Override
public void onSaveInstanceState(@NonNull Bundle outState)
{
super.onSaveInstanceState(outState);
outState.putInt("result", mResult);
}
}

0 comments on commit 55378ca

Please sign in to comment.