diff --git a/Source/Android/app/build.gradle b/Source/Android/app/build.gradle
index 857eef27f6..db2d89db8e 100644
--- a/Source/Android/app/build.gradle
+++ b/Source/Android/app/build.gradle
@@ -96,6 +96,8 @@ dependencies {
// Allows FRP-style asynchronous operations in Android.
api 'io.reactivex:rxandroid:1.2.1'
+
+ compile 'com.nononsenseapps:filepicker:4.1.0'
}
def getVersion() {
diff --git a/Source/Android/app/src/main/AndroidManifest.xml b/Source/Android/app/src/main/AndroidManifest.xml
index d445f5d822..6e854150b9 100644
--- a/Source/Android/app/src/main/AndroidManifest.xml
+++ b/Source/Android/app/src/main/AndroidManifest.xml
@@ -50,11 +50,6 @@
-
-
+
+
+
+
+
+
@@ -74,6 +78,16 @@
android:exported="false">
+
+
+
+
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
deleted file mode 100644
index 84080854d6..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/AddDirectoryActivity.java
+++ /dev/null
@@ -1,141 +0,0 @@
-package org.dolphinemu.dolphinemu.activities;
-
-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;
-import android.support.v7.widget.Toolbar;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-
-import org.dolphinemu.dolphinemu.R;
-import org.dolphinemu.dolphinemu.adapters.FileAdapter;
-import org.dolphinemu.dolphinemu.model.GameDatabase;
-import org.dolphinemu.dolphinemu.model.GameProvider;
-import org.dolphinemu.dolphinemu.ui.main.MainPresenter;
-
-/**
- * An Activity that shows a list of files and folders, allowing the user to tell the app which folder(s)
- * contains the user's games.
- */
-public class AddDirectoryActivity extends AppCompatActivity implements FileAdapter.FileClickListener
-{
- private static final String KEY_CURRENT_PATH = "path";
-
- private FileAdapter mAdapter;
- private Toolbar mToolbar;
-
- @Override
- protected void onCreate(Bundle savedInstanceState)
- {
- super.onCreate(savedInstanceState);
-
- setContentView(R.layout.activity_add_directory);
-
- mToolbar = (Toolbar) findViewById(R.id.toolbar_folder_list);
- setSupportActionBar(mToolbar);
-
- RecyclerView recyclerView = (RecyclerView) findViewById(R.id.list_files);
-
- // Specifying the LayoutManager determines how the RecyclerView arranges views.
- RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
- recyclerView.setLayoutManager(layoutManager);
-
- String path;
- // Stuff in this block only happens when this activity is newly created (i.e. not a rotation)
- if (savedInstanceState == null)
- {
- path = Environment.getExternalStorageDirectory().getPath();
- }
- else
- {
- // Get the path we were looking at before we rotated.
- path = savedInstanceState.getString(KEY_CURRENT_PATH);
- }
-
- mAdapter = new FileAdapter(path, this);
- recyclerView.setAdapter(mAdapter);
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu)
- {
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.menu_add_directory, menu);
-
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item)
- {
- switch (item.getItemId())
- {
- case R.id.menu_up_one_level:
- mAdapter.upOneLevel();
- break;
- }
-
- return super.onOptionsItemSelected(item);
- }
-
-
- @Override
- protected void onSaveInstanceState(Bundle outState)
- {
- super.onSaveInstanceState(outState);
-
- // Save the path we're looking at so when rotation is done, we start from same folder.
- outState.putString(KEY_CURRENT_PATH, mAdapter.getPath());
- }
-
- /**
- * Add a directory to the library, and if successful, end the activity.
- */
- @Override
- public void addDirectory()
- {
- // Set up a callback for when the addition is complete
- // TODO This has a nasty warning on it; find a cleaner way to do this Insert asynchronously
- AsyncQueryHandler handler = new AsyncQueryHandler(getContentResolver())
- {
- @Override
- protected void onInsertComplete(int token, Object cookie, Uri uri)
- {
- Intent resultData = new Intent();
-
- resultData.putExtra(KEY_CURRENT_PATH, mAdapter.getPath());
- setResult(RESULT_OK, resultData);
-
- finish();
- }
- };
-
- ContentValues file = new ContentValues();
- file.put(GameDatabase.KEY_FOLDER_PATH, mAdapter.getPath());
-
- handler.startInsert(0, // We don't need to identify this call to the handler
- null, // We don't need to pass additional data to the handler
- GameProvider.URI_FOLDER, // Tell the GameProvider we are adding a folder
- file); // Tell the GameProvider what folder we are adding
- }
-
- @Override
- public void updateSubtitle(String path)
- {
- mToolbar.setSubtitle(path);
- }
-
- 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/CustomFilePickerActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/CustomFilePickerActivity.java
new file mode 100644
index 0000000000..d14b92e38d
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/CustomFilePickerActivity.java
@@ -0,0 +1,28 @@
+package org.dolphinemu.dolphinemu.activities;
+
+import android.os.Environment;
+import android.support.annotation.Nullable;
+
+import com.nononsenseapps.filepicker.AbstractFilePickerFragment;
+import com.nononsenseapps.filepicker.FilePickerActivity;
+
+import org.dolphinemu.dolphinemu.fragments.CustomFilePickerFragment;
+
+import java.io.File;
+
+public class CustomFilePickerActivity extends FilePickerActivity
+
+{
+ @Override
+ protected AbstractFilePickerFragment getFragment(
+ @Nullable final String startPath, final int mode, final boolean allowMultiple,
+ final boolean allowCreateDir, final boolean allowExistingFile,
+ final boolean singleClick)
+ {
+ AbstractFilePickerFragment fragment = new CustomFilePickerFragment();
+ // startPath is allowed to be null. In that case, default folder should be SD-card and not "/"
+ fragment.setArgs(startPath != null ? startPath : Environment.getExternalStorageDirectory().getPath(),
+ mode, allowMultiple, allowCreateDir, allowExistingFile, singleClick);
+ return fragment;
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/FileAdapter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/FileAdapter.java
deleted file mode 100644
index 3e1048ffa5..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/FileAdapter.java
+++ /dev/null
@@ -1,217 +0,0 @@
-package org.dolphinemu.dolphinemu.adapters;
-
-import android.os.Environment;
-import android.support.v7.widget.RecyclerView;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Toast;
-
-import org.dolphinemu.dolphinemu.R;
-import org.dolphinemu.dolphinemu.model.FileListItem;
-import org.dolphinemu.dolphinemu.viewholders.FileViewHolder;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Collections;
-
-public final class FileAdapter extends RecyclerView.Adapter implements View.OnClickListener
-{
- private ArrayList mFileList;
-
- private String mPath;
-
- private FileClickListener mListener;
-
- /**
- * Initializes the dataset to be displayed, and associates the Adapter with the
- * Activity as an event listener.
- *
- * @param path A String containing the path to the directory to be shown by this Adapter.
- * @param listener An Activity that can respond to callbacks from this Adapter.
- */
- public FileAdapter(String path, FileClickListener listener)
- {
- mFileList = generateFileList(new File(path));
- mListener = listener;
- mListener.updateSubtitle(path);
- }
-
- /**
- * 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 FileViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
- {
- // Create a new view.
- View listItem = LayoutInflater.from(parent.getContext())
- .inflate(R.layout.list_item_file, parent, false);
-
- listItem.setOnClickListener(this);
-
- // Use that view to create a ViewHolder.
- return new FileViewHolder(listItem);
- }
-
- /**
- * 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(FileViewHolder holder, int position)
- {
- // Get a reference to the item from the dataset; we'll use this to fill in the view contents.
- final FileListItem file = mFileList.get(position);
-
- // Fill in the view contents.
- switch (file.getType())
- {
- case FileListItem.TYPE_FOLDER:
- holder.imageType.setImageResource(R.drawable.ic_folder);
- break;
-
- case FileListItem.TYPE_GC:
- holder.imageType.setImageResource(R.drawable.ic_gamecube);
- break;
-
- case FileListItem.TYPE_WII:
- holder.imageType.setImageResource(R.drawable.ic_wii);
- break;
-
- case FileListItem.TYPE_OTHER:
- holder.imageType.setImageResource(android.R.color.transparent);
- break;
- }
-
- holder.textFileName.setText(file.getFilename());
- holder.itemView.setTag(file.getPath());
- }
-
- /**
- * Called by the LayoutManager to find out how much data we have.
- *
- * @return Size of the dataset.
- */
- @Override
- public int getItemCount()
- {
- return mFileList.size();
- }
-
- /**
- * When a file is clicked, determine if it is a directory; if it is, show that new directory's
- * contents. If it is not, end the activity successfully.
- *
- * @param view The View representing the file the user clicked on.
- */
- @Override
- public void onClick(final View view)
- {
- final String path = (String) view.getTag();
-
- File clickedFile = new File(path);
-
- if (clickedFile.isDirectory())
- {
- final ArrayList fileList = generateFileList(clickedFile);
-
- if (fileList.isEmpty())
- {
- Toast.makeText(view.getContext(), R.string.add_directory_empty_folder, Toast.LENGTH_SHORT).show();
- }
- else
- {
- // Delay the loading of the new directory to give a little bit of time for UI feedback
- // to happen. Hacky, but good enough for now; this is necessary because we're modifying
- // the RecyclerView's contents, rather than constructing a new one.
- view.getHandler().postDelayed(() ->
- {
- mFileList = fileList;
- notifyDataSetChanged();
- mListener.updateSubtitle(path);
- }, 200);
- }
- }
- else
- {
- // Pass the activity the path of the parent directory of the clicked file.
- mListener.addDirectory();
- }
- }
-
- /**
- * For a given directory, return a list of Files it contains.
- *
- * @param directory A File representing the directory that should have its contents displayed.
- * @return The list of files contained in the directory.
- */
- private ArrayList generateFileList(File directory)
- {
- File[] children = directory.listFiles();
- mPath = directory.getAbsolutePath();
- ArrayList fileList = new ArrayList(0);
-
- if (children != null)
- {
-
- fileList = new ArrayList(children.length);
-
- for (File child : children)
- {
- if (!child.isHidden())
- {
- FileListItem item = new FileListItem(child);
- fileList.add(item);
- }
- }
-
- Collections.sort(fileList);
- }
- return fileList;
- }
-
- public String getPath()
- {
- return mPath;
- }
-
- public void setPath(String path)
- {
- File directory = new File(path);
-
- mFileList = generateFileList(directory);
- notifyDataSetChanged();
- mListener.updateSubtitle(path);
- }
-
- public void upOneLevel()
- {
- if (!mPath.equals("/"))
- {
- File currentDirectory = new File(mPath);
- File parentDirectory = currentDirectory.getParentFile();
-
- mFileList = generateFileList(parentDirectory);
- notifyDataSetChanged();
- mListener.updateSubtitle(mPath);
- }
- }
-
- /**
- * Callback to the containing Activity.
- */
- public interface FileClickListener
- {
- void addDirectory();
-
- void updateSubtitle(String path);
- }
-}
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 7c5a6ea415..1ba972d841 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
@@ -18,9 +18,9 @@ import org.dolphinemu.dolphinemu.utils.PicassoUtils;
import org.dolphinemu.dolphinemu.viewholders.GameViewHolder;
/**
- * This adapter, unlike {@link FileAdapter} which is backed by an ArrayList, gets its
- * information from a database Cursor. This fact, paired with the usage of ContentProviders
- * and Loaders, allows for efficient display of a limited view into a (possibly) large dataset.
+ * This adapter gets its information from a database Cursor. This fact, paired with the usage of
+ * ContentProviders and Loaders, allows for efficient display of a limited view into a (possibly)
+ * large dataset.
*/
public final class GameAdapter extends RecyclerView.Adapter implements
View.OnClickListener,
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/CustomFilePickerFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/CustomFilePickerFragment.java
new file mode 100644
index 0000000000..9d15d0fe1a
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/CustomFilePickerFragment.java
@@ -0,0 +1,22 @@
+package org.dolphinemu.dolphinemu.fragments;
+
+import android.net.Uri;
+import android.support.annotation.NonNull;
+import android.support.v4.content.FileProvider;
+
+import com.nononsenseapps.filepicker.FilePickerFragment;
+
+import java.io.File;
+
+public class CustomFilePickerFragment extends FilePickerFragment
+{
+ @NonNull
+ @Override
+ public Uri toUri(@NonNull final File file)
+ {
+ return FileProvider
+ .getUriForFile(getContext(),
+ getContext().getApplicationContext().getPackageName() + ".filesprovider",
+ file);
+ }
+}
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 1f46f8eecb..9b584201a7 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
@@ -17,13 +17,14 @@ import android.view.View;
import android.widget.Toast;
import org.dolphinemu.dolphinemu.R;
-import org.dolphinemu.dolphinemu.activities.AddDirectoryActivity;
import org.dolphinemu.dolphinemu.adapters.PlatformPagerAdapter;
import org.dolphinemu.dolphinemu.model.GameProvider;
import org.dolphinemu.dolphinemu.services.DirectoryInitializationService;
import org.dolphinemu.dolphinemu.ui.platform.Platform;
import org.dolphinemu.dolphinemu.ui.platform.PlatformGamesView;
import org.dolphinemu.dolphinemu.ui.settings.SettingsActivity;
+import org.dolphinemu.dolphinemu.utils.AddDirectoryHelper;
+import org.dolphinemu.dolphinemu.utils.FileBrowserHelper;
import org.dolphinemu.dolphinemu.utils.PermissionsHandler;
import org.dolphinemu.dolphinemu.utils.StartupHandler;
@@ -71,6 +72,13 @@ public final class MainActivity extends AppCompatActivity implements MainView
}
}
+ @Override
+ protected void onResume()
+ {
+ super.onResume();
+ mPresenter.addDirIfNeeded(new AddDirectoryHelper(this));
+ }
+
// TODO: Replace with a ButterKnife injection.
private void findViews()
{
@@ -127,7 +135,7 @@ public final class MainActivity extends AppCompatActivity implements MainView
@Override
public void launchFileListActivity()
{
- AddDirectoryActivity.launch(this);
+ FileBrowserHelper.openDirectoryPicker(this);
}
@Override
@@ -137,8 +145,6 @@ public final class MainActivity extends AppCompatActivity implements MainView
}
/**
- * Callback from AddDirectoryActivity. Applies any changes necessary to the GameGridActivity.
- *
* @param requestCode An int describing whether the Activity that is returning did so successfully.
* @param resultCode An int describing what Activity is giving us this callback.
* @param result The information the returning Activity is providing us.
@@ -146,7 +152,20 @@ public final class MainActivity extends AppCompatActivity implements MainView
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent result)
{
- mPresenter.handleActivityResult(requestCode, resultCode);
+ switch (requestCode)
+ {
+ case MainPresenter.REQUEST_ADD_DIRECTORY:
+ // If the user picked a file, as opposed to just backing out.
+ if (resultCode == MainActivity.RESULT_OK)
+ {
+ mPresenter.onDirectorySelected(FileBrowserHelper.getSelectedDirectory(result));
+ }
+ break;
+
+ case MainPresenter.REQUEST_EMULATE_GAME:
+ mPresenter.refreshFragmentScreenshot(resultCode);
+ break;
+ }
}
@Override
@@ -198,7 +217,7 @@ public final class MainActivity extends AppCompatActivity implements MainView
@Nullable
private PlatformGamesView getPlatformGamesView(Platform platform)
{
- String fragmentTag = "android:switcher:" + mViewPager.getId() + ":" + platform;
+ String fragmentTag = "android:switcher:" + mViewPager.getId() + ":" + platform.toInt();
return (PlatformGamesView) getSupportFragmentManager().findFragmentByTag(fragmentTag);
}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.java
index 57ee61baef..4ed97b6ecb 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.java
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.java
@@ -1,17 +1,15 @@
package org.dolphinemu.dolphinemu.ui.main;
-import android.database.Cursor;
-
import org.dolphinemu.dolphinemu.BuildConfig;
import org.dolphinemu.dolphinemu.DolphinApplication;
import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.model.GameDatabase;
import org.dolphinemu.dolphinemu.ui.platform.Platform;
+import org.dolphinemu.dolphinemu.utils.AddDirectoryHelper;
import org.dolphinemu.dolphinemu.utils.SettingsFile;
import rx.android.schedulers.AndroidSchedulers;
-import rx.functions.Action1;
import rx.schedulers.Schedulers;
public final class MainPresenter
@@ -20,6 +18,7 @@ public final class MainPresenter
public static final int REQUEST_EMULATE_GAME = 2;
private final MainView mView;
+ private String mDirToAdd;
public MainPresenter(MainView view)
{
@@ -71,24 +70,27 @@ public final class MainPresenter
return false;
}
- public void handleActivityResult(int requestCode, int resultCode)
+ public void addDirIfNeeded(AddDirectoryHelper helper)
{
- switch (requestCode)
+ if (mDirToAdd != null)
{
- case REQUEST_ADD_DIRECTORY:
- // If the user picked a file, as opposed to just backing out.
- if (resultCode == MainActivity.RESULT_OK)
- {
- mView.refresh();
- }
- break;
+ helper.addDirectory(mDirToAdd, mView::refresh);
- case REQUEST_EMULATE_GAME:
- mView.refreshFragmentScreenshot(resultCode);
- break;
+ mDirToAdd = null;
}
}
+ public void onDirectorySelected(String dir)
+ {
+ mDirToAdd = dir;
+ }
+
+ public void refreshFragmentScreenshot(int resultCode)
+ {
+ mView.refreshFragmentScreenshot(resultCode);
+ }
+
+
public void loadGames(final Platform platform)
{
GameDatabase databaseHelper = DolphinApplication.databaseHelper;
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 cb72c34a3e..46de94b2d6 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
@@ -12,17 +12,12 @@ import android.support.v17.leanback.widget.CursorObjectAdapter;
import android.support.v17.leanback.widget.HeaderItem;
import android.support.v17.leanback.widget.ListRow;
import android.support.v17.leanback.widget.ListRowPresenter;
-import android.support.v17.leanback.widget.OnItemViewClickedListener;
-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;
import org.dolphinemu.dolphinemu.R;
-import org.dolphinemu.dolphinemu.activities.AddDirectoryActivity;
import org.dolphinemu.dolphinemu.activities.EmulationActivity;
import org.dolphinemu.dolphinemu.adapters.GameRowPresenter;
import org.dolphinemu.dolphinemu.adapters.SettingsRowPresenter;
@@ -31,6 +26,8 @@ import org.dolphinemu.dolphinemu.model.TvSettingsItem;
import org.dolphinemu.dolphinemu.services.DirectoryInitializationService;
import org.dolphinemu.dolphinemu.ui.platform.Platform;
import org.dolphinemu.dolphinemu.ui.settings.SettingsActivity;
+import org.dolphinemu.dolphinemu.utils.AddDirectoryHelper;
+import org.dolphinemu.dolphinemu.utils.FileBrowserHelper;
import org.dolphinemu.dolphinemu.utils.PermissionsHandler;
import org.dolphinemu.dolphinemu.utils.StartupHandler;
import org.dolphinemu.dolphinemu.viewholders.TvGameViewHolder;
@@ -58,6 +55,13 @@ public final class TvMainActivity extends FragmentActivity implements MainView
StartupHandler.HandleInit(this);
}
+ @Override
+ protected void onResume()
+ {
+ super.onResume();
+ mPresenter.addDirIfNeeded(new AddDirectoryHelper(this));
+ }
+
void setupUI() {
final FragmentManager fragmentManager = getSupportFragmentManager();
mBrowseFragment = new BrowseSupportFragment();
@@ -125,7 +129,7 @@ public final class TvMainActivity extends FragmentActivity implements MainView
@Override
public void launchFileListActivity()
{
- AddDirectoryActivity.launch(this);
+ FileBrowserHelper.openDirectoryPicker(this);
}
@Override
@@ -150,7 +154,20 @@ public final class TvMainActivity extends FragmentActivity implements MainView
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent result)
{
- mPresenter.handleActivityResult(requestCode, resultCode);
+ switch (requestCode)
+ {
+ case MainPresenter.REQUEST_ADD_DIRECTORY:
+ // If the user picked a file, as opposed to just backing out.
+ if (resultCode == MainActivity.RESULT_OK)
+ {
+ mPresenter.onDirectorySelected(FileBrowserHelper.getSelectedDirectory(result));
+ }
+ break;
+
+ case MainPresenter.REQUEST_EMULATE_GAME:
+ mPresenter.refreshFragmentScreenshot(resultCode);
+ break;
+ }
}
@Override
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/AddDirectoryHelper.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/AddDirectoryHelper.java
new file mode 100644
index 0000000000..55feddb957
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/AddDirectoryHelper.java
@@ -0,0 +1,44 @@
+package org.dolphinemu.dolphinemu.utils;
+
+import android.content.AsyncQueryHandler;
+import android.content.ContentValues;
+import android.content.Context;
+import android.net.Uri;
+
+import org.dolphinemu.dolphinemu.model.GameDatabase;
+import org.dolphinemu.dolphinemu.model.GameProvider;
+
+public class AddDirectoryHelper
+{
+ private Context mContext;
+
+ public interface AddDirectoryListener
+ {
+ void onDirectoryAdded();
+ }
+
+ public AddDirectoryHelper(Context context)
+ {
+ this.mContext = context;
+ }
+
+ public void addDirectory(String dir, AddDirectoryListener addDirectoryListener)
+ {
+ AsyncQueryHandler handler = new AsyncQueryHandler(mContext.getContentResolver())
+ {
+ @Override
+ protected void onInsertComplete(int token, Object cookie, Uri uri)
+ {
+ addDirectoryListener.onDirectoryAdded();
+ }
+ };
+
+ ContentValues file = new ContentValues();
+ file.put(GameDatabase.KEY_FOLDER_PATH, dir);
+
+ handler.startInsert(0, // We don't need to identify this call to the handler
+ null, // We don't need to pass additional data to the handler
+ GameProvider.URI_FOLDER, // Tell the GameProvider we are adding a folder
+ file);
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/FileBrowserHelper.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/FileBrowserHelper.java
new file mode 100644
index 0000000000..e2fe1cf818
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/FileBrowserHelper.java
@@ -0,0 +1,43 @@
+package org.dolphinemu.dolphinemu.utils;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Environment;
+import android.support.annotation.Nullable;
+import android.support.v4.app.FragmentActivity;
+
+import com.nononsenseapps.filepicker.FilePickerActivity;
+import com.nononsenseapps.filepicker.Utils;
+
+import org.dolphinemu.dolphinemu.activities.CustomFilePickerActivity;
+import org.dolphinemu.dolphinemu.ui.main.MainPresenter;
+
+import java.io.File;
+import java.util.List;
+
+public final class FileBrowserHelper
+{
+ public static void openDirectoryPicker(FragmentActivity activity) {
+ Intent i = new Intent(activity, CustomFilePickerActivity.class);
+
+ i.putExtra(FilePickerActivity.EXTRA_ALLOW_MULTIPLE, false);
+ i.putExtra(FilePickerActivity.EXTRA_ALLOW_CREATE_DIR, false);
+ i.putExtra(FilePickerActivity.EXTRA_MODE, FilePickerActivity.MODE_DIR);
+ i.putExtra(FilePickerActivity.EXTRA_START_PATH, Environment.getExternalStorageDirectory().getPath());
+
+ activity.startActivityForResult(i, MainPresenter.REQUEST_ADD_DIRECTORY);
+ }
+
+ @Nullable
+ public static String getSelectedDirectory(Intent result) {
+ // Use the provided utility method to parse the result
+ List files = Utils.getSelectedFilesFromResult(result);
+ if(!files.isEmpty()) {
+ File file = Utils.getFileForUri(files.get(0));
+ return file.getAbsolutePath();
+ }
+
+ return null;
+ }
+}
diff --git a/Source/Android/app/src/main/res/values/styles.xml b/Source/Android/app/src/main/res/values/styles.xml
index eb8cf73dcb..a211077fee 100644
--- a/Source/Android/app/src/main/res/values/styles.xml
+++ b/Source/Android/app/src/main/res/values/styles.xml
@@ -145,4 +145,27 @@
- @color/button_text_color
-
\ No newline at end of file
+
+
+
+
+
+