diff --git a/Source/Android/app/build.gradle b/Source/Android/app/build.gradle index bdb0df444e5b..ae502037b129 100644 --- a/Source/Android/app/build.gradle +++ b/Source/Android/app/build.gradle @@ -1,8 +1,8 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 25 - buildToolsVersion '25.0.2' + compileSdkVersion 26 + buildToolsVersion '26.0.2' lintOptions { // This is important as it will run lint but not abort on error @@ -71,7 +71,7 @@ android { } ext { - androidSupportVersion = '25.3.0' + androidSupportVersion = '26.1.0' } dependencies { diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java index 614a1076f66d..3cbbf3299ab4 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java @@ -12,13 +12,15 @@ import org.dolphinemu.dolphinemu.activities.EmulationActivity; import org.dolphinemu.dolphinemu.utils.Log; +import java.lang.ref.WeakReference; + /** * Class which contains methods that interact * with the native side of the Dolphin code. */ public final class NativeLibrary { - public static EmulationActivity sEmulationActivity; + public static WeakReference sEmulationActivity = new WeakReference<>(null); /** * Button type for use in onTouchEvent @@ -379,25 +381,34 @@ private NativeLibrary() public static void displayAlertMsg(final String alert) { Log.error("[NativeLibrary] Alert: " + alert); - sEmulationActivity.runOnUiThread(new Runnable() + final EmulationActivity emulationActivity = sEmulationActivity.get(); + if (emulationActivity != null) { - @Override - public void run() + emulationActivity.runOnUiThread(new Runnable() { - Toast.makeText(sEmulationActivity, "Panic Alert: " + alert, Toast.LENGTH_LONG).show(); - } - }); + @Override + public void run() + { + Toast.makeText(emulationActivity, "Panic Alert: " + alert, Toast.LENGTH_LONG).show(); + } + }); + } + else + { + Log.warning("[NativeLibrary] EmulationActivity is null, can't do panic toast."); + } } - public static void endEmulationActivity() + public static void setEmulationActivity(EmulationActivity emulationActivity) { - Log.verbose("[NativeLibrary]Ending EmulationActivity."); - sEmulationActivity.exitWithAnimation(); + Log.verbose("[NativeLibrary] Registering EmulationActivity."); + sEmulationActivity = new WeakReference<>(emulationActivity); } - public static void setEmulationActivity(EmulationActivity emulationActivity) + public static void clearEmulationActivity() { - Log.verbose("[NativeLibrary]Registering EmulationActivity."); - sEmulationActivity = emulationActivity; + Log.verbose("[NativeLibrary] Unregistering EmulationActivity."); + + sEmulationActivity.clear(); } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/AddDirectoryActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/AddDirectoryActivity.java index 45e1f87ca9c1..84080854d6e3 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/AddDirectoryActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/AddDirectoryActivity.java @@ -1,12 +1,12 @@ package org.dolphinemu.dolphinemu.activities; -import android.app.Activity; import android.content.AsyncQueryHandler; import android.content.ContentValues; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.os.Environment; +import android.support.v4.app.FragmentActivity; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; @@ -133,7 +133,7 @@ public void updateSubtitle(String path) mToolbar.setSubtitle(path); } - public static void launch(Activity activity) + public static void launch(FragmentActivity activity) { Intent fileChooser = new Intent(activity, AddDirectoryActivity.class); activity.startActivityForResult(fileChooser, MainPresenter.REQUEST_ADD_DIRECTORY); diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java index 3162b650d369..2753735200c3 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java @@ -1,9 +1,6 @@ package org.dolphinemu.dolphinemu.activities; -import android.app.Activity; -import android.app.ActivityOptions; import android.app.AlertDialog; -import android.app.Fragment; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; @@ -14,6 +11,10 @@ import android.os.Message; import android.preference.PreferenceManager; import android.support.annotation.IntDef; +import android.support.v4.app.ActivityOptionsCompat; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentActivity; +import android.support.v4.app.FragmentManager; import android.support.v7.app.AppCompatActivity; import android.util.SparseIntArray; import android.view.InputDevice; @@ -23,10 +24,7 @@ import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; -import android.view.ViewTreeObserver; -import android.widget.FrameLayout; import android.widget.ImageView; -import android.widget.LinearLayout; import android.widget.SeekBar; import android.widget.TextView; import android.widget.Toast; @@ -44,7 +42,6 @@ import org.dolphinemu.dolphinemu.utils.Animations; import org.dolphinemu.dolphinemu.utils.Java_GCAdapter; import org.dolphinemu.dolphinemu.utils.Java_WiimoteAdapter; -import org.dolphinemu.dolphinemu.utils.Log; import java.lang.annotation.Retention; import java.util.List; @@ -53,12 +50,11 @@ public final class EmulationActivity extends AppCompatActivity { - private static final String FRAGMENT_SUBMENU_TAG = "submenu"; + private static final String BACKSTACK_NAME_MENU = "menu"; + private static final String BACKSTACK_NAME_SUBMENU = "submenu"; private View mDecorView; private ImageView mImageView; - - private FrameLayout mFrameEmulation; - private LinearLayout mMenuLayout; + private EmulationFragment mEmulationFragment; private SharedPreferences mPreferences; @@ -68,14 +64,8 @@ public final class EmulationActivity extends AppCompatActivity private boolean mDeviceHasTouchScreen; private boolean mSystemUiVisible; private boolean mMenuVisible; - private boolean mSubMenuVisible = false; - - private static boolean mIsGameCubeGame; - private enum MenuType - { - SAVE, LOAD - } + private static boolean sIsGameCubeGame; /** * Handlers are a way to pass a message to an Activity telling it to do something @@ -91,7 +81,6 @@ public void handleMessage(Message msg) } }; private String mScreenPath; - private FrameLayout mFrameContent; private String mSelectedTitle; @Retention(SOURCE) @@ -157,7 +146,7 @@ public void handleMessage(Message msg) buttonsActionsMap.append(R.id.menu_exit, EmulationActivity.MENU_ACTION_EXIT); } - public static void launch(Activity activity, String path, String title, String screenshotPath, int position, View sharedView) + public static void launch(FragmentActivity activity, String path, String title, String screenshotPath, int position, View sharedView) { Intent launcher = new Intent(activity, EmulationActivity.class); @@ -166,17 +155,28 @@ public static void launch(Activity activity, String path, String title, String s launcher.putExtra("ScreenPath", screenshotPath); launcher.putExtra("GridPosition", position); - ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation( + ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation( activity, sharedView, "image_game_screenshot"); + // I believe this warning is a bug. Activities are FragmentActivity from the support lib + //noinspection RestrictedApi activity.startActivityForResult(launcher, MainPresenter.REQUEST_EMULATE_GAME, options.toBundle()); } @Override protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // Get params we were passed + Intent gameToEmulate = getIntent(); + String path = gameToEmulate.getStringExtra("SelectedGame"); + sIsGameCubeGame = Platform.fromNativeInt(NativeLibrary.GetPlatform(path)) == Platform.GAMECUBE; + mSelectedTitle = gameToEmulate.getStringExtra("SelectedTitle"); + mScreenPath = gameToEmulate.getStringExtra("ScreenPath"); + mPosition = gameToEmulate.getIntExtra("GridPosition", -1); mDeviceHasTouchScreen = getPackageManager().hasSystemFeature("android.hardware.touchscreen"); int themeId; @@ -219,30 +219,22 @@ public void onSystemUiVisibilityChange(int flags) } setTheme(themeId); - super.onCreate(savedInstanceState); Java_GCAdapter.manager = (UsbManager) getSystemService(Context.USB_SERVICE); Java_WiimoteAdapter.manager = (UsbManager) getSystemService(Context.USB_SERVICE); - // Picasso will take a while to load these big-ass screenshots. So don't run - // the animation until we say so. - postponeEnterTransition(); - setContentView(R.layout.activity_emulation); mImageView = (ImageView) findViewById(R.id.image_screenshot); - mFrameContent = (FrameLayout) findViewById(R.id.frame_content); - mFrameEmulation = (FrameLayout) findViewById(R.id.frame_emulation_fragment); - mMenuLayout = (LinearLayout) findViewById(R.id.layout_ingame_menu); - - Intent gameToEmulate = getIntent(); - String path = gameToEmulate.getStringExtra("SelectedGame"); - mSelectedTitle = gameToEmulate.getStringExtra("SelectedTitle"); - mScreenPath = gameToEmulate.getStringExtra("ScreenPath"); - mPosition = gameToEmulate.getIntExtra("GridPosition", -1); + mEmulationFragment = (EmulationFragment) getSupportFragmentManager() + .findFragmentById(R.id.fragment_emulation); if (savedInstanceState == null) { + // Picasso will take a while to load these big-ass screenshots. So don't run + // the animation until we say so. + postponeEnterTransition(); + Picasso.with(this) .load(mScreenPath) .noFade() @@ -252,27 +244,19 @@ public void onSystemUiVisibilityChange(int flags) @Override public void onSuccess() { - scheduleStartPostponedTransition(mImageView); + supportStartPostponedEnterTransition(); } @Override public void onError() { // Still have to do this, or else the app will crash. - scheduleStartPostponedTransition(mImageView); + supportStartPostponedEnterTransition(); } }); Animations.fadeViewOut(mImageView) .setStartDelay(2000) - .withStartAction(new Runnable() - { - @Override - public void run() - { - mFrameEmulation.setVisibility(View.VISIBLE); - } - }) .withEndAction(new Runnable() { @Override @@ -282,55 +266,21 @@ public void run() } }); - // Instantiate an EmulationFragment. - EmulationFragment emulationFragment = EmulationFragment.newInstance(path); - - // Add fragment to the activity - this triggers all its lifecycle callbacks. - getFragmentManager().beginTransaction() - .add(R.id.frame_emulation_fragment, emulationFragment, EmulationFragment.FRAGMENT_TAG) - .commit(); + mEmulationFragment.setGamePath(path); + mEmulationFragment.startEmulation(); } else { mImageView.setVisibility(View.GONE); - mFrameEmulation.setVisibility(View.VISIBLE); } if (mDeviceHasTouchScreen) { setTitle(mSelectedTitle); } - else - { - MenuFragment menuFragment = (MenuFragment) getFragmentManager() - .findFragmentById(R.id.fragment_menu); - - if (menuFragment != null) - { - menuFragment.setTitleText(mSelectedTitle); - } - } mPreferences = PreferenceManager.getDefaultSharedPreferences(this); - mIsGameCubeGame = Platform.fromNativeInt(NativeLibrary.GetPlatform(path)) == Platform.GAMECUBE; - } - - @Override - protected void onStart() - { - super.onStart(); - Log.debug("[EmulationActivity] EmulationActivity starting."); - NativeLibrary.setEmulationActivity(this); - } - - @Override - protected void onStop() - { - super.onStop(); - Log.debug("[EmulationActivity] EmulationActivity stopping."); - - NativeLibrary.setEmulationActivity(null); } @Override @@ -370,56 +320,43 @@ public void onBackPressed() { if (!mDeviceHasTouchScreen) { - if (mSubMenuVisible) - { - removeSubMenu(); - } - else + boolean popResult = getSupportFragmentManager().popBackStackImmediate( + BACKSTACK_NAME_SUBMENU, FragmentManager.POP_BACK_STACK_INCLUSIVE); + if (!popResult) { toggleMenu(); } } else { - stopEmulation(); + mEmulationFragment.stopEmulation(); + exitWithAnimation(); } + } private void toggleMenu() { - if (mMenuVisible) - { - mMenuVisible = false; - - Animations.fadeViewOutToLeft(mMenuLayout) - .withEndAction(new Runnable() - { - @Override - public void run() - { - if (mMenuVisible) - { - mMenuLayout.setVisibility(View.GONE); - } - } - }); - } - else - { + boolean result = getSupportFragmentManager().popBackStackImmediate( + BACKSTACK_NAME_MENU, FragmentManager.POP_BACK_STACK_INCLUSIVE); + mMenuVisible = false; + + if (!result) { + // Removing the menu failed, so that means it wasn't visible. Add it. + Fragment fragment = MenuFragment.newInstance(mSelectedTitle); + getSupportFragmentManager().beginTransaction() + .setCustomAnimations( + R.animator.menu_slide_in_from_left, + R.animator.menu_slide_out_to_left, + R.animator.menu_slide_in_from_left, + R.animator.menu_slide_out_to_left) + .add(R.id.frame_menu, fragment) + .addToBackStack(BACKSTACK_NAME_MENU) + .commit(); mMenuVisible = true; - Animations.fadeViewInFromLeft(mMenuLayout); } } - private void stopEmulation() - { - EmulationFragment fragment = (EmulationFragment) getFragmentManager() - .findFragmentByTag(EmulationFragment.FRAGMENT_TAG); - fragment.notifyEmulationStopped(); - - NativeLibrary.StopEmulation(); - } - public void exitWithAnimation() { runOnUiThread(new Runnable() @@ -463,9 +400,8 @@ private void showScreenshot() @Override public void run() { - mFrameContent.removeView(mFrameEmulation); setResult(mPosition); - finishAfterTransition(); + supportFinishAfterTransition(); } }; @@ -473,7 +409,7 @@ public void run() public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. - if (mIsGameCubeGame) + if (sIsGameCubeGame) { getMenuInflater().inflate(R.menu.menu_emulation, menu); } @@ -542,14 +478,14 @@ public void handleMenuAction(@MenuAction int menuAction) case MENU_ACTION_SAVE_ROOT: if (!mDeviceHasTouchScreen) { - showMenu(SaveLoadStateFragment.SaveOrLoad.SAVE); + showSubMenu(SaveLoadStateFragment.SaveOrLoad.SAVE); } return; case MENU_ACTION_LOAD_ROOT: if (!mDeviceHasTouchScreen) { - showMenu(SaveLoadStateFragment.SaveOrLoad.LOAD); + showSubMenu(SaveLoadStateFragment.SaveOrLoad.LOAD); } return; @@ -604,20 +540,23 @@ public void handleMenuAction(@MenuAction int menuAction) return; case MENU_ACTION_EXIT: - toggleMenu(); - stopEmulation(); + toggleMenu(); // Hide the menu (it will be showing since we just clicked it) + mEmulationFragment.stopEmulation(); + exitWithAnimation(); return; } } - private void editControlsPlacement() { - EmulationFragment emulationFragment = (EmulationFragment) getFragmentManager() - .findFragmentById(R.id.frame_emulation_fragment); - if (emulationFragment.isConfiguringControls()) { - emulationFragment.stopConfiguringControls(); - } else { - emulationFragment.startConfiguringControls(); + private void editControlsPlacement() + { + if (mEmulationFragment.isConfiguringControls()) + { + mEmulationFragment.stopConfiguringControls(); + } + else + { + mEmulationFragment.startConfiguringControls(); } } @@ -660,7 +599,7 @@ private void toggleControls() { boolean[] enabledButtons = new boolean[14]; AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(R.string.emulation_toggle_controls); - if (mIsGameCubeGame || mPreferences.getInt("wiiController", 3) == 0) { + if (sIsGameCubeGame || mPreferences.getInt("wiiController", 3) == 0) { for (int i = 0; i < enabledButtons.length; i++) { enabledButtons[i] = mPreferences.getBoolean("buttonToggleGc" + i, true); } @@ -706,20 +645,18 @@ public void onClick(DialogInterface dialog, int indexSelected, boolean isChecked } builder.setNeutralButton(getString(R.string.emulation_toggle_all), new DialogInterface.OnClickListener() { @Override - public void onClick(DialogInterface dialogInterface, int i) { - EmulationFragment emulationFragment = (EmulationFragment) getFragmentManager() - .findFragmentByTag(EmulationFragment.FRAGMENT_TAG); - emulationFragment.toggleInputOverlayVisibility(); + public void onClick(DialogInterface dialogInterface, int i) + { + mEmulationFragment.toggleInputOverlayVisibility(); } }); builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() { @Override - public void onClick(DialogInterface dialogInterface, int i) { + public void onClick(DialogInterface dialogInterface, int i) + { editor.apply(); - EmulationFragment emulationFragment = (EmulationFragment) getFragmentManager() - .findFragmentByTag(EmulationFragment.FRAGMENT_TAG); - emulationFragment.refreshInputOverlay(); + mEmulationFragment.refreshInputOverlay(); } }); @@ -764,9 +701,7 @@ public void onClick(DialogInterface dialogInterface, int i) { editor.putInt("controlScale", seekbar.getProgress()); editor.apply(); - EmulationFragment emulationFragment = (EmulationFragment) getFragmentManager() - .findFragmentByTag(EmulationFragment.FRAGMENT_TAG); - emulationFragment.refreshInputOverlay(); + mEmulationFragment.refreshInputOverlay(); } }); @@ -793,9 +728,7 @@ public void onClick(DialogInterface dialog, int indexSelected) { public void onClick(DialogInterface dialogInterface, int i) { editor.apply(); - EmulationFragment emulationFragment = (EmulationFragment) getFragmentManager() - .findFragmentByTag(EmulationFragment.FRAGMENT_TAG); - emulationFragment.refreshInputOverlay(); + mEmulationFragment.refreshInputOverlay(); Toast.makeText(getApplication(), R.string.emulation_controller_changed, Toast.LENGTH_SHORT).show(); } @@ -866,60 +799,22 @@ private void showSystemUI() hideSystemUiAfterDelay(); } - - private void scheduleStartPostponedTransition(final View sharedElement) + private void showSubMenu(SaveLoadStateFragment.SaveOrLoad saveOrLoad) { - sharedElement.getViewTreeObserver().addOnPreDrawListener( - new ViewTreeObserver.OnPreDrawListener() - { - @Override - public boolean onPreDraw() - { - sharedElement.getViewTreeObserver().removeOnPreDrawListener(this); - startPostponedEnterTransition(); - return true; - } - }); - } + // Get rid of any visible submenu + getSupportFragmentManager().popBackStack( + BACKSTACK_NAME_SUBMENU, FragmentManager.POP_BACK_STACK_INCLUSIVE); - private void showMenu(SaveLoadStateFragment.SaveOrLoad saveOrLoad) - { Fragment fragment = SaveLoadStateFragment.newInstance(saveOrLoad); - getFragmentManager().beginTransaction() - .setCustomAnimations(R.animator.menu_slide_in, R.animator.menu_slide_out) - .replace(R.id.frame_submenu, fragment, FRAGMENT_SUBMENU_TAG) + getSupportFragmentManager().beginTransaction() + .setCustomAnimations( + R.animator.menu_slide_in_from_right, + R.animator.menu_slide_out_to_right, + R.animator.menu_slide_in_from_right, + R.animator.menu_slide_out_to_right) + .replace(R.id.frame_submenu, fragment) + .addToBackStack(BACKSTACK_NAME_SUBMENU) .commit(); - mSubMenuVisible = true; - } - - private void removeSubMenu() - { - final Fragment fragment = getFragmentManager().findFragmentByTag(FRAGMENT_SUBMENU_TAG); - - if (fragment != null) - { - // When removing a fragment without replacement, its animation must be done - // manually beforehand. - Animations.fadeViewOutToRight(fragment.getView()) - .withEndAction(new Runnable() - { - @Override - public void run() - { - if (mMenuVisible) - { - getFragmentManager().beginTransaction() - .remove(fragment) - .commit(); - } - } - }); - } - else - { - Log.error("[EmulationActivity] Fragment not found, can't remove."); - } - mSubMenuVisible = false; } public String getSelectedTitle() @@ -929,6 +824,6 @@ public String getSelectedTitle() public static boolean isGameCubeGame() { - return mIsGameCubeGame; + return sIsGameCubeGame; } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.java index 153470df6ad2..7c5a6ea415fe 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.java @@ -1,9 +1,9 @@ package org.dolphinemu.dolphinemu.adapters; -import android.app.Activity; import android.database.Cursor; import android.database.DataSetObserver; import android.graphics.Rect; +import android.support.v4.app.FragmentActivity; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; @@ -202,7 +202,7 @@ public void onClick(View view) { GameViewHolder holder = (GameViewHolder) view.getTag(); - EmulationActivity.launch((Activity) view.getContext(), + EmulationActivity.launch((FragmentActivity) view.getContext(), holder.path, holder.title, holder.screenshotPath, @@ -225,13 +225,13 @@ public boolean onLongClick(View view) // TODO This should be all we need to pass in, eventually. // String gameId = (String) holder.gameId; - Activity activity = (Activity) view.getContext(); + FragmentActivity activity = (FragmentActivity) view.getContext(); GameDetailsDialog.newInstance(holder.title, holder.description, holder.country, holder.company, holder.path, - holder.screenshotPath).show(activity.getFragmentManager(), "game_details"); + holder.screenshotPath).show(activity.getSupportFragmentManager(), "game_details"); return true; } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/PlatformPagerAdapter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/PlatformPagerAdapter.java index afdf67f34e0f..c5ab5522bba8 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/PlatformPagerAdapter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/PlatformPagerAdapter.java @@ -1,10 +1,10 @@ package org.dolphinemu.dolphinemu.adapters; -import android.app.Fragment; -import android.app.FragmentManager; import android.content.Context; import android.graphics.drawable.Drawable; -import android.support.v13.app.FragmentPagerAdapter; +import android.support.v4.app.FragmentPagerAdapter; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; import android.text.Spannable; import android.text.SpannableString; import android.text.style.ImageSpan; diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/dialogs/GameDetailsDialog.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/dialogs/GameDetailsDialog.java index f67ac0c4426f..10c04778d025 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/dialogs/GameDetailsDialog.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/dialogs/GameDetailsDialog.java @@ -2,9 +2,9 @@ import android.app.AlertDialog; import android.app.Dialog; -import android.app.DialogFragment; import android.os.Bundle; import android.support.design.widget.FloatingActionButton; +import android.support.v4.app.DialogFragment; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java index 94d411a78d64..0572d048f4eb 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java @@ -1,9 +1,10 @@ package org.dolphinemu.dolphinemu.fragments; -import android.app.Fragment; +import android.content.Context; import android.content.SharedPreferences; import android.os.Bundle; import android.preference.PreferenceManager; +import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.Surface; import android.view.SurfaceHolder; @@ -14,15 +15,12 @@ import org.dolphinemu.dolphinemu.NativeLibrary; import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.activities.EmulationActivity; import org.dolphinemu.dolphinemu.overlay.InputOverlay; import org.dolphinemu.dolphinemu.utils.Log; public final class EmulationFragment extends Fragment implements SurfaceHolder.Callback { - public static final String FRAGMENT_TAG = "emulation_fragment"; - - private static final String ARG_GAME_PATH = "game_path"; - private SharedPreferences mPreferences; private Surface mSurface; @@ -31,18 +29,22 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C private Thread mEmulationThread; - private boolean mEmulationStarted; - private boolean mEmulationRunning; + private String mGamePath; + private final EmulationState mEmulationState = new EmulationState(); - public static EmulationFragment newInstance(String path) + @Override + public void onAttach(Context context) { - EmulationFragment fragment = new EmulationFragment(); + super.onAttach(context); - Bundle arguments = new Bundle(); - arguments.putString(ARG_GAME_PATH, path); - fragment.setArguments(arguments); - - return fragment; + if (context instanceof EmulationActivity) + { + NativeLibrary.setEmulationActivity((EmulationActivity) context); + } + else + { + throw new IllegalStateException("EmulationFragment must have EmulationActivity parent"); + } } /** @@ -67,38 +69,20 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa { View contents = inflater.inflate(R.layout.fragment_emulation, container, false); - SurfaceView surfaceView = (SurfaceView) contents.findViewById(R.id.surface_emulation); - mInputOverlay = (InputOverlay) contents.findViewById(R.id.surface_input_overlay); - + SurfaceView surfaceView = contents.findViewById(R.id.surface_emulation); surfaceView.getHolder().addCallback(this); - // If the input overlay was previously disabled, then don't show it. + mInputOverlay = contents.findViewById(R.id.surface_input_overlay); if (mInputOverlay != null) { + // If the input overlay was previously disabled, then don't show it. if (!mPreferences.getBoolean("showInputOverlay", true)) { mInputOverlay.setVisibility(View.GONE); } } - if (savedInstanceState == null) - { - mEmulationThread = new Thread(mEmulationRunner); - } - else - { - // Likely a rotation occurred. - // TODO Pass native code the Surface, which will have been recreated, from surfaceChanged() - // TODO Also, write the native code that will get the video backend to accept the new Surface as one of its own. - } - - return contents; - } - - @Override - public void onViewCreated(View view, Bundle savedInstanceState) - { - Button doneButton = (Button) view.findViewById(R.id.done_control_config); + Button doneButton = contents.findViewById(R.id.done_control_config); if (doneButton != null) { doneButton.setOnClickListener(new View.OnClickListener() @@ -110,29 +94,29 @@ public void onClick(View v) } }); } - } - @Override - public void onStart() - { - super.onStart(); - startEmulation(); + // The new Surface created here will get passed to the native code via onSurfaceChanged. + + return contents; } @Override public void onStop() { + pauseEmulation(); super.onStop(); } @Override - public void onDestroyView() + public void onDetach() { - super.onDestroyView(); - if (getActivity().isFinishing() && mEmulationStarted) - { - NativeLibrary.StopEmulation(); - } + NativeLibrary.clearEmulationActivity(); + super.onDetach(); + } + + public void setGamePath(String gamePath) + { + mGamePath = gamePath; } public void toggleInputOverlayVisibility() @@ -171,6 +155,12 @@ public void surfaceCreated(SurfaceHolder holder) public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { Log.debug("[EmulationFragment] Surface changed. Resolution: " + width + "x" + height); + + if (mEmulationState.isPaused()) + { + NativeLibrary.UnPauseEmulation(); + } + mSurface = holder.getSurface(); NativeLibrary.SurfaceChanged(mSurface); } @@ -181,45 +171,57 @@ public void surfaceDestroyed(SurfaceHolder holder) Log.debug("[EmulationFragment] Surface destroyed."); NativeLibrary.SurfaceDestroyed(); - if (mEmulationRunning) + if (mEmulationState.isRunning()) { pauseEmulation(); } } - private void startEmulation() + public void startEmulation() { - if (!mEmulationStarted) + synchronized (mEmulationState) { - Log.debug("[EmulationFragment] Starting emulation thread."); + if (mEmulationState.isStopped()) + { + Log.debug("[EmulationFragment] Starting emulation thread."); - mEmulationThread.start(); + mEmulationThread = new Thread(mEmulationRunner, "NativeEmulation"); + mEmulationThread.start(); + // The thread will call mEmulationState.run() + } + else if (mEmulationState.isPaused()) + { + Log.debug("[EmulationFragment] Resuming emulation."); + NativeLibrary.UnPauseEmulation(); + mEmulationState.run(); + } + else + { + Log.debug("[EmulationFragment] Bug, startEmulation called while running."); + } } - else + } + + public void stopEmulation() { + synchronized (mEmulationState) { - Log.debug("[EmulationFragment] Resuming emulation."); - NativeLibrary.UnPauseEmulation(); + if (!mEmulationState.isStopped()) + { + NativeLibrary.StopEmulation(); + mEmulationState.stop(); + } } - - mEmulationRunning = true; } private void pauseEmulation() { - Log.debug("[EmulationFragment] Pausing emulation."); - - NativeLibrary.PauseEmulation(); - mEmulationRunning = false; - } + synchronized (mEmulationState) + { + Log.debug("[EmulationFragment] Pausing emulation."); - /** - * Called by containing activity to tell the Fragment emulation is already stopping, - * so it doesn't try to stop emulation on its way to the garbage collector. - */ - public void notifyEmulationStopped() - { - mEmulationStarted = false; - mEmulationRunning = false; + NativeLibrary.PauseEmulation(); + mEmulationState.pause(); + } } private Runnable mEmulationRunner = new Runnable() @@ -227,18 +229,17 @@ public void notifyEmulationStopped() @Override public void run() { - mEmulationRunning = true; - mEmulationStarted = true; - - while (mSurface == null) - if (!mEmulationRunning) - return; + // Busy-wait for surface to be set + while (mSurface == null) {} - Log.info("[EmulationFragment] Starting emulation: " + mSurface); + synchronized (mEmulationState) + { + Log.info("[EmulationFragment] Starting emulation: " + mSurface); + mEmulationState.run(); + } // Start emulation using the provided Surface. - String path = getArguments().getString(ARG_GAME_PATH); - NativeLibrary.Run(path); + NativeLibrary.Run(mGamePath); } }; @@ -258,4 +259,50 @@ public boolean isConfiguringControls() { return mInputOverlay.isInEditMode(); } + + private static class EmulationState + { + private enum State + { + STOPPED, RUNNING, PAUSED + } + + private State state; + + EmulationState() + { + // Starting state is stopped. + state = State.STOPPED; + } + + public boolean isStopped() + { + return state == State.STOPPED; + } + + public boolean isRunning() + { + return state == State.RUNNING; + } + + public boolean isPaused() + { + return state == State.PAUSED; + } + + public void run() + { + state = State.RUNNING; + } + + public void pause() + { + state = State.PAUSED; + } + + public void stop() + { + state = State.STOPPED; + } + } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/MenuFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/MenuFragment.java index 2ab3e0ba6a54..34898e8f8b61 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/MenuFragment.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/MenuFragment.java @@ -1,8 +1,8 @@ package org.dolphinemu.dolphinemu.fragments; -import android.app.Fragment; import android.os.Bundle; import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; import android.util.SparseIntArray; import android.view.LayoutInflater; import android.view.View; @@ -16,7 +16,7 @@ public final class MenuFragment extends Fragment implements View.OnClickListener { - private TextView mTitleText; + private static final String KEY_TITLE = "title"; private static SparseIntArray buttonsActionsMap = new SparseIntArray(); static { buttonsActionsMap.append(R.id.menu_take_screenshot, EmulationActivity.MENU_ACTION_TAKE_SCREENSHOT); @@ -28,6 +28,17 @@ public final class MenuFragment extends Fragment implements View.OnClickListener buttonsActionsMap.append(R.id.menu_exit, EmulationActivity.MENU_ACTION_EXIT); } + public static MenuFragment newInstance(String title) + { + MenuFragment fragment = new MenuFragment(); + + Bundle arguments = new Bundle(); + arguments.putSerializable(KEY_TITLE, title); + fragment.setArguments(arguments); + + return fragment; + } + @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) @@ -42,7 +53,12 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa button.setOnClickListener(this); } - mTitleText = (TextView) rootView.findViewById(R.id.text_game_title); + TextView titleText = rootView.findViewById(R.id.text_game_title); + String title = getArguments().getString(KEY_TITLE); + if (title != null) + { + titleText.setText(title); + } return rootView; } @@ -57,9 +73,4 @@ public void onClick(View button) ((EmulationActivity) getActivity()).handleMenuAction(action); } } - - public void setTitleText(String title) - { - mTitleText.setText(title); - } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/SaveLoadStateFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/SaveLoadStateFragment.java index 2752a8d4b38d..a59e435da089 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/SaveLoadStateFragment.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/SaveLoadStateFragment.java @@ -1,8 +1,8 @@ package org.dolphinemu.dolphinemu.fragments; -import android.app.Fragment; import android.os.Bundle; import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; import android.util.SparseIntArray; import android.view.LayoutInflater; import android.view.View; diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/NVidiaShieldWorkaroundView.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/NVidiaShieldWorkaroundView.java new file mode 100644 index 000000000000..5d2e4a8bbe99 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/NVidiaShieldWorkaroundView.java @@ -0,0 +1,25 @@ +/** + * Copyright 2013 Dolphin Emulator Project + * Licensed under GPLv2+ + * Refer to the license.txt file included. + */ + +package org.dolphinemu.dolphinemu.ui; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; + +/** + * Work around a bug with the nVidia Shield. + */ +public final class NVidiaShieldWorkaroundView extends View +{ + public NVidiaShieldWorkaroundView(Context context, AttributeSet attrs) + { + super(context, attrs); + + // Setting this seems to workaround the bug + setWillNotDraw(false); + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java index 10d76b4e42ed..7c9fa225b171 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java @@ -70,7 +70,8 @@ public void onClick(View view) if (PermissionsHandler.hasWriteAccess(this)) { - PlatformPagerAdapter platformPagerAdapter = new PlatformPagerAdapter(getFragmentManager(), this); + PlatformPagerAdapter platformPagerAdapter = new PlatformPagerAdapter( + getSupportFragmentManager(), this); mViewPager.setAdapter(platformPagerAdapter); } else { mViewPager.setVisibility(View.INVISIBLE); @@ -162,7 +163,8 @@ public void onRequestPermissionsResult(int requestCode, String[] permissions, in if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { StartupHandler.copyAssetsIfNeeded(this); - PlatformPagerAdapter platformPagerAdapter = new PlatformPagerAdapter(getFragmentManager(), this); + PlatformPagerAdapter platformPagerAdapter = new PlatformPagerAdapter( + getSupportFragmentManager(), this); mViewPager.setAdapter(platformPagerAdapter); mTabLayout.setupWithViewPager(mViewPager); mViewPager.setVisibility(View.VISIBLE); @@ -205,6 +207,6 @@ private PlatformGamesView getPlatformGamesView(Platform platform) { String fragmentTag = "android:switcher:" + mViewPager.getId() + ":" + platform; - return (PlatformGamesView) getFragmentManager().findFragmentByTag(fragmentTag); + return (PlatformGamesView) getSupportFragmentManager().findFragmentByTag(fragmentTag); } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.java index 567e2ca4926b..383b30aeba38 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.java @@ -1,12 +1,11 @@ package org.dolphinemu.dolphinemu.ui.main; -import android.app.Activity; -import android.app.FragmentManager; import android.content.Intent; import android.content.pm.PackageManager; import android.database.Cursor; import android.os.Bundle; import android.support.v17.leanback.app.BrowseFragment; +import android.support.v17.leanback.app.BrowseSupportFragment; import android.support.v17.leanback.database.CursorMapper; import android.support.v17.leanback.widget.ArrayObjectAdapter; import android.support.v17.leanback.widget.CursorObjectAdapter; @@ -17,6 +16,8 @@ import android.support.v17.leanback.widget.Presenter; import android.support.v17.leanback.widget.Row; import android.support.v17.leanback.widget.RowPresenter; +import android.support.v4.app.FragmentActivity; +import android.support.v4.app.FragmentManager; import android.support.v4.content.ContextCompat; import android.widget.Toast; @@ -33,11 +34,11 @@ import org.dolphinemu.dolphinemu.utils.StartupHandler; import org.dolphinemu.dolphinemu.viewholders.TvGameViewHolder; -public final class TvMainActivity extends Activity implements MainView +public final class TvMainActivity extends FragmentActivity implements MainView { private MainPresenter mPresenter = new MainPresenter(this); - private BrowseFragment mBrowseFragment; + private BrowseSupportFragment mBrowseFragment; private ArrayObjectAdapter mRowsAdapter; @@ -57,8 +58,8 @@ protected void onCreate(Bundle savedInstanceState) } void setupUI() { - final FragmentManager fragmentManager = getFragmentManager(); - mBrowseFragment = new BrowseFragment(); + final FragmentManager fragmentManager = getSupportFragmentManager(); + mBrowseFragment = new BrowseSupportFragment(); fragmentManager .beginTransaction() .add(R.id.content, mBrowseFragment, "BrowseFragment") diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/platform/PlatformGamesFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/platform/PlatformGamesFragment.java index 45bfee591bc3..3325a1ca2371 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/platform/PlatformGamesFragment.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/platform/PlatformGamesFragment.java @@ -1,9 +1,9 @@ package org.dolphinemu.dolphinemu.ui.platform; -import android.app.Fragment; import android.database.Cursor; import android.os.Bundle; import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsActivity.java index 7c30cd54f174..43715cecba84 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsActivity.java @@ -1,9 +1,9 @@ package org.dolphinemu.dolphinemu.ui.settings; -import android.app.FragmentTransaction; import android.content.Context; import android.content.Intent; import android.os.Bundle; +import android.support.v4.app.FragmentTransaction; import android.support.v7.app.AppCompatActivity; import android.view.Menu; import android.view.MenuInflater; @@ -88,7 +88,7 @@ public void onBackPressed() @Override public void showSettingsFragment(String menuTag, boolean addToStack) { - FragmentTransaction transaction = getFragmentManager().beginTransaction(); + FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); if (addToStack) { @@ -149,7 +149,7 @@ public void showToastMessage(String message) @Override public void popBackStack() { - getFragmentManager().popBackStackImmediate(); + getSupportFragmentManager().popBackStackImmediate(); } @Override @@ -178,6 +178,6 @@ public void onExtensionSettingChanged(String key, int value) private SettingsFragment getFragment() { - return (SettingsFragment) getFragmentManager().findFragmentByTag(FRAGMENT_TAG); + return (SettingsFragment) getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG); } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragment.java index dd752c666462..276a26ee9a7e 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragment.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragment.java @@ -1,10 +1,10 @@ package org.dolphinemu.dolphinemu.ui.settings; import android.app.Activity; -import android.app.Fragment; import android.content.Context; import android.os.Bundle; import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentView.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentView.java index 43453ffb2a80..3029dc2a9dc9 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentView.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentView.java @@ -1,6 +1,6 @@ package org.dolphinemu.dolphinemu.ui.settings; -import android.app.Activity; +import android.support.v4.app.FragmentActivity; import org.dolphinemu.dolphinemu.model.settings.Setting; import org.dolphinemu.dolphinemu.model.settings.SettingSection; @@ -48,7 +48,7 @@ public interface SettingsFragmentView /** * @return The Fragment's containing activity. */ - Activity getActivity(); + FragmentActivity getActivity(); /** * Tell the Fragment to tell the containing Activity to show a new diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Animations.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Animations.java index cff0dcb363ee..777a92149356 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Animations.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Animations.java @@ -2,55 +2,13 @@ import android.view.View; import android.view.ViewPropertyAnimator; -import android.view.animation.AccelerateInterpolator; -import android.view.animation.DecelerateInterpolator; -import android.view.animation.Interpolator; public final class Animations { - private static final Interpolator DECELERATOR = new DecelerateInterpolator(); - private static final Interpolator ACCELERATOR = new AccelerateInterpolator(); - private Animations() { } - public static ViewPropertyAnimator fadeViewOutToRight(View view) - { - return view.animate() - .withLayer() - .setDuration(200) - .setInterpolator(ACCELERATOR) - .alpha(0.0f) - .translationX(view.getWidth()); - } - - public static ViewPropertyAnimator fadeViewOutToLeft(View view) - { - return view.animate() - .withLayer() - .setDuration(200) - .setInterpolator(ACCELERATOR) - .alpha(0.0f) - .translationX(-view.getWidth()); - } - - public static ViewPropertyAnimator fadeViewInFromLeft(View view) - { - - view.setVisibility(View.VISIBLE); - - view.setTranslationX(-view.getWidth()); - view.setAlpha(0.0f); - - return view.animate() - .withLayer() - .setDuration(300) - .setInterpolator(DECELERATOR) - .alpha(1.0f) - .translationX(0.0f); - } - public static ViewPropertyAnimator fadeViewIn(View view) { view.setVisibility(View.VISIBLE); diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Java_GCAdapter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Java_GCAdapter.java index d7731b604049..91e2a9ca4622 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Java_GCAdapter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Java_GCAdapter.java @@ -1,6 +1,8 @@ package org.dolphinemu.dolphinemu.utils; +import android.app.Activity; import android.app.PendingIntent; +import android.content.Context; import android.content.Intent; import android.hardware.usb.UsbConfiguration; import android.hardware.usb.UsbConstants; @@ -15,7 +17,6 @@ import org.dolphinemu.dolphinemu.services.USBPermService; import java.util.HashMap; -import java.util.Iterator; import java.util.Map; public class Java_GCAdapter { @@ -29,22 +30,31 @@ public class Java_GCAdapter { private static void RequestPermission() { - HashMap devices = manager.getDeviceList(); - for (Map.Entry pair : devices.entrySet()) + Context context = NativeLibrary.sEmulationActivity.get(); + if (context != null) { - UsbDevice dev = pair.getValue(); - if (dev.getProductId() == 0x0337 && dev.getVendorId() == 0x057e) + HashMap devices = manager.getDeviceList(); + for (Map.Entry pair : devices.entrySet()) { - if (!manager.hasPermission(dev)) + UsbDevice dev = pair.getValue(); + if (dev.getProductId() == 0x0337 && dev.getVendorId() == 0x057e) { - Intent intent = new Intent(); - PendingIntent pend_intent; - intent.setClass(NativeLibrary.sEmulationActivity, USBPermService.class); - pend_intent = PendingIntent.getService(NativeLibrary.sEmulationActivity, 0, intent, 0); - manager.requestPermission(dev, pend_intent); + if (!manager.hasPermission(dev)) + { + Intent intent = new Intent(); + PendingIntent pend_intent; + intent.setClass(context, USBPermService.class); + pend_intent = PendingIntent.getService(context, 0, intent, 0); + manager.requestPermission(dev, pend_intent); + } } } } + else + { + Log.warning("Cannot request GameCube Adapter permission as EmulationActivity is null."); + } + } public static void Shutdown() @@ -124,14 +134,22 @@ public static boolean OpenAdapter() } } - NativeLibrary.sEmulationActivity.runOnUiThread(new Runnable() + final Activity emulationActivity = NativeLibrary.sEmulationActivity.get(); + if (emulationActivity != null) { - @Override - public void run() + emulationActivity.runOnUiThread(new Runnable() { - Toast.makeText(NativeLibrary.sEmulationActivity, "GameCube Adapter couldn't be opened. Please re-plug the device.", Toast.LENGTH_LONG).show(); - } - }); + @Override + public void run() + { + Toast.makeText(emulationActivity, "GameCube Adapter couldn't be opened. Please re-plug the device.", Toast.LENGTH_LONG).show(); + } + }); + } + else + { + Log.warning("Cannot show toast for GameCube Adapter failure."); + } usb_con.close(); } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Java_WiimoteAdapter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Java_WiimoteAdapter.java index 5fdc49b021a6..a38f7ecd4b91 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Java_WiimoteAdapter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Java_WiimoteAdapter.java @@ -1,6 +1,7 @@ package org.dolphinemu.dolphinemu.utils; import android.app.PendingIntent; +import android.content.Context; import android.content.Intent; import android.hardware.usb.UsbConfiguration; import android.hardware.usb.UsbDevice; @@ -33,23 +34,31 @@ public class Java_WiimoteAdapter private static void RequestPermission() { - HashMap devices = manager.getDeviceList(); - for (Map.Entry pair : devices.entrySet()) + Context context = NativeLibrary.sEmulationActivity.get(); + if (context != null) { - UsbDevice dev = pair.getValue(); - if (dev.getProductId() == NINTENDO_WIIMOTE_PRODUCT_ID && dev.getVendorId() == NINTENDO_VENDOR_ID) + HashMap devices = manager.getDeviceList(); + for (Map.Entry pair : devices.entrySet()) { - if (!manager.hasPermission(dev)) + UsbDevice dev = pair.getValue(); + if (dev.getProductId() == NINTENDO_WIIMOTE_PRODUCT_ID && dev.getVendorId() == NINTENDO_VENDOR_ID) { - Log.warning("Requesting permission for Wii Remote adapter"); - Intent intent = new Intent(); - PendingIntent pend_intent; - intent.setClass(NativeLibrary.sEmulationActivity, USBPermService.class); - pend_intent = PendingIntent.getService(NativeLibrary.sEmulationActivity, 0, intent, 0); - manager.requestPermission(dev, pend_intent); + if (!manager.hasPermission(dev)) + { + Log.warning("Requesting permission for Wii Remote adapter"); + Intent intent = new Intent(); + PendingIntent pend_intent; + intent.setClass(context, USBPermService.class); + pend_intent = PendingIntent.getService(context, 0, intent, 0); + manager.requestPermission(dev, pend_intent); + } } } } + else + { + Log.warning("Cannot request Wiimote adapter permission as EmulationActivity is null."); + } } public static boolean QueryAdapter() diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/PermissionsHandler.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/PermissionsHandler.java index 84ea110884b8..ceca9e419539 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/PermissionsHandler.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/PermissionsHandler.java @@ -1,11 +1,11 @@ package org.dolphinemu.dolphinemu.utils; import android.annotation.TargetApi; -import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.pm.PackageManager; import android.os.Build; +import android.support.v4.app.FragmentActivity; import android.support.v4.content.ContextCompat; import android.widget.Toast; @@ -17,7 +17,7 @@ public class PermissionsHandler { public static final int REQUEST_CODE_WRITE_PERMISSION = 500; @TargetApi(Build.VERSION_CODES.M) - public static boolean checkWritePermission(final Activity activity) { + public static boolean checkWritePermission(final FragmentActivity activity) { if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { return true; } @@ -45,7 +45,7 @@ public void onClick(DialogInterface dialog, int which) { return true; } - public static boolean hasWriteAccess(Activity activity) { + public static boolean hasWriteAccess(FragmentActivity activity) { if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { int hasWritePermission = ContextCompat.checkSelfPermission(activity, WRITE_EXTERNAL_STORAGE); return hasWritePermission == PackageManager.PERMISSION_GRANTED; @@ -54,7 +54,7 @@ public static boolean hasWriteAccess(Activity activity) { return true; } - private static void showMessageOKCancel(final Activity activity, String message, DialogInterface.OnClickListener okListener) { + private static void showMessageOKCancel(final FragmentActivity activity, String message, DialogInterface.OnClickListener okListener) { new AlertDialog.Builder(activity) .setMessage(message) .setPositiveButton(android.R.string.ok, okListener) diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/StartupHandler.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/StartupHandler.java index 2e31f405d007..34cde9e59ce4 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/StartupHandler.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/StartupHandler.java @@ -1,10 +1,10 @@ package org.dolphinemu.dolphinemu.utils; -import android.app.Activity; import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; import android.preference.PreferenceManager; +import android.support.v4.app.FragmentActivity; import android.text.TextUtils; import org.dolphinemu.dolphinemu.NativeLibrary; @@ -13,7 +13,7 @@ public final class StartupHandler { - public static boolean HandleInit(Activity parent) + public static boolean HandleInit(FragmentActivity parent) { NativeLibrary.SetUserDirectory(""); // Auto-Detect @@ -46,7 +46,7 @@ public static boolean HandleInit(Activity parent) return false; } - public static void copyAssetsIfNeeded(Activity parent) { + public static void copyAssetsIfNeeded(FragmentActivity parent) { SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(parent); boolean assetsCopied = preferences.getBoolean("assetsCopied", false); diff --git a/Source/Android/app/src/main/res/animator/menu_slide_in_from_left.xml b/Source/Android/app/src/main/res/animator/menu_slide_in_from_left.xml new file mode 100644 index 000000000000..4612aee134d1 --- /dev/null +++ b/Source/Android/app/src/main/res/animator/menu_slide_in_from_left.xml @@ -0,0 +1,20 @@ + + + + + + + + \ No newline at end of file diff --git a/Source/Android/app/src/main/res/animator/menu_slide_in.xml b/Source/Android/app/src/main/res/animator/menu_slide_in_from_right.xml similarity index 93% rename from Source/Android/app/src/main/res/animator/menu_slide_in.xml rename to Source/Android/app/src/main/res/animator/menu_slide_in_from_right.xml index fff198cb47e3..3f1495c75705 100644 --- a/Source/Android/app/src/main/res/animator/menu_slide_in.xml +++ b/Source/Android/app/src/main/res/animator/menu_slide_in_from_right.xml @@ -4,7 +4,7 @@ diff --git a/Source/Android/app/src/main/res/animator/menu_slide_out_to_left.xml b/Source/Android/app/src/main/res/animator/menu_slide_out_to_left.xml new file mode 100644 index 000000000000..0e21cf848969 --- /dev/null +++ b/Source/Android/app/src/main/res/animator/menu_slide_out_to_left.xml @@ -0,0 +1,21 @@ + + + + + + + + + \ No newline at end of file diff --git a/Source/Android/app/src/main/res/animator/menu_slide_out.xml b/Source/Android/app/src/main/res/animator/menu_slide_out_to_right.xml similarity index 87% rename from Source/Android/app/src/main/res/animator/menu_slide_out.xml rename to Source/Android/app/src/main/res/animator/menu_slide_out_to_right.xml index 88f300280a50..78edf872cf78 100644 --- a/Source/Android/app/src/main/res/animator/menu_slide_out.xml +++ b/Source/Android/app/src/main/res/animator/menu_slide_out_to_right.xml @@ -6,9 +6,9 @@ android:propertyName="translationX" android:valueType="floatType" android:valueFrom="0" - android:valueTo="1280" + android:valueTo="1280dp" android:interpolator="@android:interpolator/decelerate_quad" - android:duration="300"/> + android:duration="200"/> + android:duration="200"/> \ No newline at end of file diff --git a/Source/Android/app/src/main/res/layout-television/activity_emulation.xml b/Source/Android/app/src/main/res/layout-television/activity_emulation.xml index a8cba9adb526..3009f40e8406 100644 --- a/Source/Android/app/src/main/res/layout-television/activity_emulation.xml +++ b/Source/Android/app/src/main/res/layout-television/activity_emulation.xml @@ -5,11 +5,15 @@ xmlns:tools="http://schemas.android.com/tools" android:id="@+id/frame_content"> - + android:layout_height="match_parent"/> + + + + android:orientation="horizontal"> - + android:layout_weight=".75"/> - \ No newline at end of file + diff --git a/Source/Android/app/src/main/res/layout-television/fragment_emulation.xml b/Source/Android/app/src/main/res/layout-television/fragment_emulation.xml index 276f5ad133bd..27243e841161 100644 --- a/Source/Android/app/src/main/res/layout-television/fragment_emulation.xml +++ b/Source/Android/app/src/main/res/layout-television/fragment_emulation.xml @@ -1,15 +1,7 @@ - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/Source/Android/app/src/main/res/layout/activity_emulation.xml b/Source/Android/app/src/main/res/layout/activity_emulation.xml index 3aa230a07059..2562d5a44bc5 100644 --- a/Source/Android/app/src/main/res/layout/activity_emulation.xml +++ b/Source/Android/app/src/main/res/layout/activity_emulation.xml @@ -3,11 +3,11 @@ android:layout_height="match_parent" android:id="@+id/frame_content"> - + android:layout_height="match_parent"/> - - - - -