summaryrefslogtreecommitdiff
path: root/Source/Android/app/src/main/java
diff options
context:
space:
mode:
authorEder Bastos <bastos.eder@gmail.com>2015-05-06 20:12:58 -0400
committerEder Bastos <bastos.eder@gmail.com>2015-05-07 22:27:42 -0400
commitb47835fc07371964816938c982c5aea3a9f564bb (patch)
tree7a66d02b900e00a4541d4292877c9d06bdc2c2c0 /Source/Android/app/src/main/java
parent80fe5e0a55260eec17d905cd224919c3734c5876 (diff)
Implement first few screens of Android 5.0-based UI.
Diffstat (limited to 'Source/Android/app/src/main/java')
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java6
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/GameGridActivity.java131
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.java113
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/dialogs/GameDetailsDialog.java96
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/Game.java23
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GcGame.java96
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/WiiGame.java53
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/viewholders/GameViewHolder.java83
8 files changed, 601 insertions, 0 deletions
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 ab9f25b306..e7d2e2b328 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
@@ -130,6 +130,12 @@ public final class NativeLibrary
*/
public static native String GetTitle(String filename);
+ public static native String GetDescription(String filename);
+ public static native String GetGameId(String filename);
+ public static native String GetDate(String filename);
+ public static native long GetFilesize(String filename);
+ public static native boolean IsWiiTitle(String filename);
+
/**
* Gets the Dolphin version string.
*
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/GameGridActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/GameGridActivity.java
new file mode 100644
index 0000000000..be0fbbed1a
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/GameGridActivity.java
@@ -0,0 +1,131 @@
+package org.dolphinemu.dolphinemu.activities;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Environment;
+import android.support.v7.widget.GridLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.widget.Toolbar;
+
+import org.dolphinemu.dolphinemu.AssetCopyService;
+import org.dolphinemu.dolphinemu.NativeLibrary;
+import org.dolphinemu.dolphinemu.R;
+import org.dolphinemu.dolphinemu.adapters.GameAdapter;
+import org.dolphinemu.dolphinemu.model.Game;
+import org.dolphinemu.dolphinemu.model.GcGame;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+public class GameGridActivity extends Activity
+{
+ private RecyclerView mRecyclerView;
+ private RecyclerView.Adapter mAdapter;
+ private RecyclerView.LayoutManager mLayoutManager;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_game_grid);
+
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar_game_list);
+ setActionBar(toolbar);
+
+ mRecyclerView = (RecyclerView) findViewById(R.id.grid_games);
+
+ // use this setting to improve performance if you know that changes
+ // in content do not change the layout size of the RecyclerView
+ //mRecyclerView.setHasFixedSize(true);
+
+ // Specifying the LayoutManager determines how the RecyclerView arranges views.
+ mLayoutManager = new GridLayoutManager(this, 4);
+ mRecyclerView.setLayoutManager(mLayoutManager);
+
+ mRecyclerView.addItemDecoration(new GameAdapter.SpacesItemDecoration(8));
+
+ // Create an adapter that will relate the dataset to the views on-screen.
+ mAdapter = new GameAdapter(getGameList());
+ mRecyclerView.setAdapter(mAdapter);
+
+ // Stuff in this block only happens when this activity is newly created (i.e. not a rotation)
+ if (savedInstanceState == null)
+ {
+ // Copy assets into appropriate locations.
+ Intent copyAssets = new Intent(this, AssetCopyService.class);
+ startService(copyAssets);
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu)
+ {
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.gamelist_menu, menu);
+ return true;
+
+ }
+
+ // TODO Replace all of this with a SQLite database
+ private ArrayList<Game> getGameList()
+ {
+ ArrayList<Game> gameList = new ArrayList<Game>();
+
+ final String DefaultDir = Environment.getExternalStorageDirectory() + File.separator + "dolphin-emu";
+
+ NativeLibrary.SetUserDirectory(DefaultDir);
+
+ String Directories = NativeLibrary.GetConfig("Dolphin.ini", "General", "ISOPaths", "0");
+ Log.v("DolphinEmu", "Directories: " + Directories);
+ int intDirectories = Integer.parseInt(Directories);
+
+ // Extensions to filter by.
+ Set<String> exts = new HashSet<String>(Arrays.asList(".dff", ".dol", ".elf", ".gcm", ".gcz", ".iso", ".wad", ".wbfs"));
+
+ for (int a = 0; a < intDirectories; ++a)
+ {
+ String BrowseDir = NativeLibrary.GetConfig("Dolphin.ini", "General", "ISOPath" + a, "");
+ Log.v("DolphinEmu", "Directory " + a + ": " + BrowseDir);
+
+ File currentDir = new File(BrowseDir);
+ File[] dirs = currentDir.listFiles();
+ try
+ {
+ for (File entry : dirs)
+ {
+ if (!entry.isHidden() && !entry.isDirectory())
+ {
+ String entryName = entry.getName();
+
+ // Check that the file has an appropriate extension before trying to read out of it.
+ if (exts.contains(entryName.toLowerCase().substring(entryName.lastIndexOf('.'))))
+ {
+ GcGame game = new GcGame(NativeLibrary.GetTitle(entry.getAbsolutePath()),
+ NativeLibrary.GetDescription(entry.getAbsolutePath()).replace("\n", " "),
+ // TODO Some games might actually not be from this region, believe it or not.
+ "United States",
+ entry.getAbsolutePath(),
+ NativeLibrary.GetGameId(entry.getAbsolutePath()),
+ NativeLibrary.GetDate(entry.getAbsolutePath()));
+
+ gameList.add(game);
+ }
+
+ }
+
+ }
+ } catch (Exception ignored)
+ {
+ }
+ }
+
+ return gameList;
+ }
+}
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
new file mode 100644
index 0000000000..30bc9daad6
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.java
@@ -0,0 +1,113 @@
+package org.dolphinemu.dolphinemu.adapters;
+
+import android.graphics.Rect;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.squareup.picasso.Picasso;
+
+import org.dolphinemu.dolphinemu.R;
+import org.dolphinemu.dolphinemu.model.Game;
+import org.dolphinemu.dolphinemu.viewholders.GameViewHolder;
+
+import java.util.ArrayList;
+
+public class GameAdapter extends RecyclerView.Adapter<GameViewHolder>
+{
+ private ArrayList<Game> mGameList;
+
+ /**
+ * Mostly just initializes the dataset to be displayed.
+ *
+ * @param gameList
+ */
+ public GameAdapter(ArrayList<Game> gameList)
+ {
+ mGameList = gameList;
+ }
+
+ /**
+ * Called by the LayoutManager when it is necessary to create a new view.
+ *
+ * @param parent The RecyclerView (I think?) the created view will be thrown into.
+ * @param viewType Not used here, but useful when more than one type of child will be used in the RecyclerView.
+ * @return The created ViewHolder with references to all the child view's members.
+ */
+ @Override
+ public GameViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
+ {
+ // Create a new view.
+ View gameCard = LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.card_game, parent, false);
+
+ // Use that view to create a ViewHolder.
+ GameViewHolder holder = new GameViewHolder(gameCard);
+ return holder;
+ }
+
+ /**
+ * Called by the LayoutManager when a new view is not necessary because we can recycle
+ * an existing one (for example, if a view just scrolled onto the screen from the bottom, we
+ * can use the view that just scrolled off the top instead of inflating a new one.)
+ *
+ * @param holder A ViewHolder representing the view we're recycling.
+ * @param position The position of the 'new' view in the dataset.
+ */
+ @Override
+ public void onBindViewHolder(GameViewHolder holder, int position)
+ {
+ // Get a reference to the item from the dataset; we'll use this to fill in the view contents.
+ final Game game = mGameList.get(position);
+
+ // Fill in the view contents.
+ Picasso.with(holder.imageScreenshot.getContext())
+ .load(game.getScreenPath())
+ .error(R.drawable.no_banner)
+ .into(holder.imageScreenshot);
+
+ holder.textGameTitle.setText(game.getTitle());
+ if (game.getDescription() != null)
+ {
+ holder.textDescription.setText(game.getDescription());
+ }
+ holder.buttonDetails.setTag(game.getGameId());
+
+ holder.path = game.getPath();
+ holder.screenshotPath = game.getScreenPath();
+ holder.game = game;
+
+ }
+
+ /**
+ * Called by the LayoutManager to find out how much data we have.
+ *
+ * @return Size of the dataset.
+ */
+ @Override
+ public int getItemCount()
+ {
+ return mGameList.size();
+ }
+
+ public static class SpacesItemDecoration extends RecyclerView.ItemDecoration
+ {
+ private int space;
+
+ public SpacesItemDecoration(int space)
+ {
+ this.space = space;
+ }
+
+ @Override
+ public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state)
+ {
+ outRect.left = space;
+ outRect.right = space;
+ outRect.bottom = space;
+ outRect.top = space;
+
+ }
+ }
+}
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
new file mode 100644
index 0000000000..19c6621345
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/dialogs/GameDetailsDialog.java
@@ -0,0 +1,96 @@
+package org.dolphinemu.dolphinemu.dialogs;
+
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.squareup.picasso.Picasso;
+
+import org.dolphinemu.dolphinemu.BuildConfig;
+import org.dolphinemu.dolphinemu.R;
+import org.dolphinemu.dolphinemu.emulation.EmulationActivity;
+import org.dolphinemu.dolphinemu.model.Game;
+
+import de.hdodenhof.circleimageview.CircleImageView;
+
+public class GameDetailsDialog extends DialogFragment
+{
+ public static final String ARGUMENT_GAME_TITLE = BuildConfig.APPLICATION_ID + ".game_title";
+ public static final String ARGUMENT_GAME_DESCRIPTION = BuildConfig.APPLICATION_ID + ".game_description";
+ public static final String ARGUMENT_GAME_COUNTRY = BuildConfig.APPLICATION_ID + ".game_country";
+ public static final String ARGUMENT_GAME_DATE = BuildConfig.APPLICATION_ID + ".game_date";
+ public static final String ARGUMENT_GAME_PATH = BuildConfig.APPLICATION_ID + ".game_path";
+ public static final String ARGUMENT_GAME_SCREENSHOT_PATH = BuildConfig.APPLICATION_ID + ".game_screenshot_path";
+
+
+ public static GameDetailsDialog newInstance(Game game)
+ {
+ GameDetailsDialog fragment = new GameDetailsDialog();
+
+ Bundle arguments = new Bundle();
+ arguments.putString(ARGUMENT_GAME_TITLE, game.getTitle());
+ arguments.putString(ARGUMENT_GAME_DESCRIPTION, game.getDescription());
+ arguments.putString(ARGUMENT_GAME_COUNTRY, game.getCountry());
+ arguments.putString(ARGUMENT_GAME_DATE, game.getDate());
+ arguments.putString(ARGUMENT_GAME_PATH, game.getPath());
+ arguments.putString(ARGUMENT_GAME_SCREENSHOT_PATH, game.getScreenPath());
+ fragment.setArguments(arguments);
+
+ return fragment;
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState)
+ {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ ViewGroup contents = (ViewGroup) getActivity().getLayoutInflater().inflate(R.layout.dialog_game_details, null);
+
+ final ImageView imageGameScreen = (ImageView) contents.findViewById(R.id.image_game_screen);
+ CircleImageView circleBanner = (CircleImageView) contents.findViewById(R.id.circle_banner);
+
+ TextView textTitle = (TextView) contents.findViewById(R.id.text_game_title);
+ TextView textDescription = (TextView) contents.findViewById(R.id.text_game_description);
+
+ TextView textCountry = (TextView) contents.findViewById(R.id.text_country);
+ TextView textDate = (TextView) contents.findViewById(R.id.text_date);
+
+ ImageButton buttonLaunch = (ImageButton) contents.findViewById(R.id.button_launch);
+
+ textTitle.setText(getArguments().getString(ARGUMENT_GAME_TITLE));
+ textDescription.setText(getArguments().getString(ARGUMENT_GAME_DESCRIPTION));
+ textCountry.setText(getArguments().getString(ARGUMENT_GAME_COUNTRY));
+ textDate.setText(getArguments().getString(ARGUMENT_GAME_DATE));
+ buttonLaunch.setOnClickListener(new View.OnClickListener()
+ {
+ @Override
+ public void onClick(View view)
+ {
+ // Start the emulation activity and send the path of the clicked ROM to it.
+ Intent intent = new Intent(view.getContext(), EmulationActivity.class);
+
+ intent.putExtra("SelectedGame", getArguments().getString(ARGUMENT_GAME_PATH));
+ startActivity(intent);
+ }
+ });
+
+ // Fill in the view contents.
+ Picasso.with(imageGameScreen.getContext())
+ .load(getArguments().getString(ARGUMENT_GAME_SCREENSHOT_PATH))
+ .noFade()
+ .noPlaceholder()
+ .into(imageGameScreen);
+
+ circleBanner.setImageResource(R.drawable.no_banner);
+
+ builder.setView(contents);
+ return builder.create();
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/Game.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/Game.java
new file mode 100644
index 0000000000..9d3e736841
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/Game.java
@@ -0,0 +1,23 @@
+package org.dolphinemu.dolphinemu.model;
+
+public interface Game
+{
+ public static final int PLATFORM_GC = 0;
+ public static final int PLATFORM_WII = 1;
+
+ public int getPlatform();
+
+ public String getDate();
+
+ public String getTitle();
+
+ public String getDescription();
+
+ public String getCountry();
+
+ public String getPath();
+
+ public String getGameId();
+
+ public String getScreenPath();
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GcGame.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GcGame.java
new file mode 100644
index 0000000000..d682bee0b6
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GcGame.java
@@ -0,0 +1,96 @@
+package org.dolphinemu.dolphinemu.model;
+
+
+import java.io.File;
+
+public final class GcGame implements Game
+{
+ private String mTitle;
+ private String mDescription;
+ private String mCountry;
+ private String mPath;
+ private String mGameId;
+
+ private String mScreenshotFolderPath;
+
+ private String mDate;
+ private int mPlatform = PLATFORM_GC;
+
+ private static final String PATH_SCREENSHOT_FOLDER = "file:///sdcard/dolphin-emu/ScreenShots/";
+
+ public GcGame(String title, String description, String country, String path, String gameId, String date)
+ {
+ mTitle = title;
+ mDescription = description;
+ mCountry = country;
+ mPath = path;
+ mGameId = gameId;
+ mDate = date;
+ mScreenshotFolderPath = PATH_SCREENSHOT_FOLDER + getGameId() + "/";
+ }
+
+ @Override
+ public int getPlatform()
+ {
+ return mPlatform;
+ }
+
+ @Override
+ public String getTitle()
+ {
+ return mTitle;
+ }
+
+ @Override
+ public String getDescription()
+ {
+ return mDescription;
+ }
+
+ @Override
+ public String getDate()
+ {
+ return mDate;
+ }
+
+ @Override
+ public String getCountry()
+ {
+ return mCountry;
+ }
+
+ @Override
+ public String getPath()
+ {
+ return mPath;
+ }
+
+ public String getGameId()
+ {
+ return mGameId;
+ }
+
+ public String getScreenshotFolderPath()
+ {
+ return mScreenshotFolderPath;
+ }
+
+ @Override
+ public String getScreenPath()
+ {
+ // Count how many screenshots are available, so we can use the most recent one.
+ File screenshotFolder = new File(mScreenshotFolderPath.substring(mScreenshotFolderPath.indexOf('s') - 1));
+ int screenCount = 0;
+
+ if (screenshotFolder.isDirectory())
+ {
+ screenCount = screenshotFolder.list().length;
+ }
+
+ String screenPath = mScreenshotFolderPath
+ + getGameId() + "-"
+ + screenCount + ".png";
+
+ return screenPath;
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/WiiGame.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/WiiGame.java
new file mode 100644
index 0000000000..c64de8d582
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/WiiGame.java
@@ -0,0 +1,53 @@
+package org.dolphinemu.dolphinemu.model;
+
+
+public final class WiiGame implements Game
+{
+ @Override
+ public int getPlatform()
+ {
+ return 0;
+ }
+
+ @Override
+ public String getDate()
+ {
+ return null;
+ }
+
+ @Override
+ public String getTitle()
+ {
+ return null;
+ }
+
+ @Override
+ public String getDescription()
+ {
+ return null;
+ }
+
+ @Override
+ public String getCountry()
+ {
+ return null;
+ }
+
+ @Override
+ public String getPath()
+ {
+ return null;
+ }
+
+ @Override
+ public String getGameId()
+ {
+ return null;
+ }
+
+ @Override
+ public String getScreenPath()
+ {
+ return null;
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/viewholders/GameViewHolder.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/viewholders/GameViewHolder.java
new file mode 100644
index 0000000000..47acf588de
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/viewholders/GameViewHolder.java
@@ -0,0 +1,83 @@
+package org.dolphinemu.dolphinemu.viewholders;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import org.dolphinemu.dolphinemu.R;
+import org.dolphinemu.dolphinemu.dialogs.GameDetailsDialog;
+import org.dolphinemu.dolphinemu.emulation.EmulationActivity;
+import org.dolphinemu.dolphinemu.model.Game;
+
+
+public class GameViewHolder extends RecyclerView.ViewHolder
+{
+ public ImageView imageScreenshot;
+ public TextView textGameTitle;
+ public TextView textDescription;
+ public ImageButton buttonDetails;
+
+ // Used to handle onClick(). Set this in onBindViewHolder().
+ public String path;
+ public String screenshotPath;
+ public Game game;
+
+ public GameViewHolder(View itemView)
+ {
+ super(itemView);
+
+ itemView.setOnClickListener(mCardClickListener);
+
+ imageScreenshot = (ImageView) itemView.findViewById(R.id.image_game_screen);
+ textGameTitle = (TextView) itemView.findViewById(R.id.text_game_title);
+ textDescription = (TextView) itemView.findViewById(R.id.text_game_description);
+ buttonDetails = (ImageButton) itemView.findViewById(R.id.button_details);
+
+ buttonDetails.setOnClickListener(mDetailsButtonListener);
+ }
+
+ private View.OnClickListener mCardClickListener = new View.OnClickListener()
+ {
+ /**
+ * Launches the game that was clicked on.
+ *
+ * @param view The card representing the game the user wants to play.
+ */
+ @Override
+ public void onClick(View view)
+ {
+ // Start the emulation activity and send the path of the clicked ROM to it.
+ Intent intent = new Intent(view.getContext(), EmulationActivity.class);
+
+ intent.putExtra("SelectedGame", path);
+
+ view.getContext().startActivity(intent);
+ }
+ };
+
+ private View.OnClickListener mDetailsButtonListener = new View.OnClickListener()
+ {
+
+ /**
+ * Launches the details activity for this Game, using an ID stored in the
+ * details button's Tag.
+ *
+ * @param view The Details button that was clicked on.
+ */
+ @Override
+ public void onClick(View view)
+ {
+ // Get the ID of the game we want to look at.
+ // TODO This should be all we need to pass in, eventually.
+ // String gameId = (String) view.getTag();
+
+ Activity activity = (Activity) view.getContext();
+ GameDetailsDialog.newInstance(game).show(activity.getFragmentManager(), "game_details");
+ }
+ };
+
+}