Android: backend support for a file locator

Automatically lists all files that fit the extension and sets the root
game folder when one of the items is selected.

Clicking the Reset Folder preference will remove the stored base folder
and return to the complete list.

TODO: Add a method to refresh the list when clearing the preference or
returning from the emulator.

Conflicts:
	Source/ui_android/java/com/virtualapplications/play/MainActivity.java
This commit is contained in:
TwistedUmbrella 2015-07-11 15:12:15 -04:00
parent 5a9714eb90
commit 0b0b198501
8 changed files with 333 additions and 64 deletions

3
.gitignore vendored
View File

@ -1,6 +1,6 @@
libPlay.so
build_android/bin
build_android/gen
build_android/libs
build_android/obj
build_android/jni/ExternalDependencies.mk
build_android/local.properties
@ -17,5 +17,6 @@ ReleaseAot
*.suo
*.user
*.userprops
*.orig
xcuserdata

View File

@ -0,0 +1,73 @@
package com.android.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.nio.IntBuffer;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Vector;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
public class FileUtils {
public void saveArray(String filename, List<String> output_field) {
try {
FileOutputStream fos = new FileOutputStream(filename);
GZIPOutputStream gzos = new GZIPOutputStream(fos);
ObjectOutputStream out = new ObjectOutputStream(gzos);
out.writeObject(output_field);
out.flush();
out.close();
} catch (IOException e) {
e.getStackTrace();
}
}
@SuppressWarnings("unchecked")
public List<String> loadArray(String filename) {
try {
FileInputStream fis = new FileInputStream(filename);
GZIPInputStream gzis = new GZIPInputStream(fis);
ObjectInputStream in = new ObjectInputStream(gzis);
List<String> read_field = (List<String>) in.readObject();
in.close();
return read_field;
} catch (Exception e) {
e.getStackTrace();
}
return null;
}
public Collection<File> listFiles(File directory, FilenameFilter[] filter,
int recurse) {
Vector<File> files = new Vector<File>();
File[] entries = directory.listFiles();
if (entries != null) {
for (File entry : entries) {
for (FilenameFilter filefilter : filter) {
if (filter == null
|| filefilter.accept(directory, entry.getName())) {
files.add(entry);
}
}
if ((recurse <= -1) || (recurse > 0 && entry.isDirectory())) {
recurse--;
files.addAll(listFiles(entry, filter, recurse));
recurse++;
}
}
}
return files;
}
}

View File

@ -12,6 +12,8 @@ import java.io.*;
import java.text.*;
import java.util.*;
import java.util.zip.*;
import org.apache.commons.lang3.StringUtils;
import com.android.util.FileUtils;
public class MainActivity extends Activity
{
@ -21,6 +23,8 @@ public class MainActivity extends Activity
private FileListItem[] _fileListItems;
private ListView _fileListView;
private TextView _fileListViewHeader;
private ArrayList<FileListItem> fileListItems;
private static Activity mActivity;
@Override
protected void onCreate(Bundle savedInstanceState)
@ -30,6 +34,8 @@ public class MainActivity extends Activity
setContentView(R.layout.main);
mActivity = MainActivity.this;
File filesDir = getFilesDir();
NativeInterop.setFilesDirPath(Environment.getExternalStorageDirectory().getAbsolutePath());
@ -42,22 +48,40 @@ public class MainActivity extends Activity
}
prepareFileListView();
updateFileListView();
// updateFileListView();
String sdcard = getCurrentDirectory();
new ImageFinder(R.array.disks).execute(sdcard);
new ImageFinder(R.array.elves).execute(sdcard);
if (sdcard.equals(Environment.getExternalStorageDirectory().getAbsolutePath())) {
HashSet<String> extStorage = MainActivity.getExternalMounts();
if (extStorage != null && !extStorage.isEmpty()) {
for (Iterator<String> sd = extStorage.iterator(); sd.hasNext();) {
String sdCardPath = sd.next().replace("mnt/media_rw", "storage");
if (!sdCardPath.equals(sdcard)) {
if (new File(sdCardPath).canRead()) {
new ImageFinder(R.array.disks).execute(sdCardPath);
new ImageFinder(R.array.elves).execute(sdCardPath);
}
}
}
}
}
}
@Override
public void onBackPressed()
{
File currentDirectoryFile = new File(getCurrentDirectory());
File parentDirectoryFile = currentDirectoryFile.getParentFile();
if(parentDirectoryFile == null) {
finish();
} else {
setCurrentDirectory(currentDirectoryFile.getParentFile().getAbsolutePath());
updateFileListView();
}
}
// @Override
// public void onBackPressed()
// {
// File currentDirectoryFile = new File(getCurrentDirectory());
// File parentDirectoryFile = currentDirectoryFile.getParentFile();
// if(parentDirectoryFile == null) {
// finish();
// }
// setCurrentDirectory(currentDirectoryFile.getParentFile().getAbsolutePath());
// updateFileListView();
// }
private static long getBuildDate(Context context)
{
@ -144,6 +168,42 @@ public class MainActivity extends Activity
return _preferences.getString(PREFERENCE_CURRENT_DIRECTORY, Environment.getExternalStorageDirectory().getAbsolutePath());
}
public static HashSet<String> getExternalMounts() {
final HashSet<String> out = new HashSet<String>();
String reg = "(?i).*vold.*(vfat|ntfs|exfat|fat32|ext3|ext4|fuse).*rw.*";
String s = "";
try {
final java.lang.Process process = new ProcessBuilder().command("mount")
.redirectErrorStream(true).start();
process.waitFor();
final InputStream is = process.getInputStream();
final byte[] buffer = new byte[1024];
while (is.read(buffer) != -1) {
s = s + new String(buffer);
}
is.close();
} catch (final Exception e) {
}
final String[] lines = s.split("\n");
for (String line : lines) {
if (StringUtils.containsIgnoreCase(line, "secure"))
continue;
if (StringUtils.containsIgnoreCase(line, "asec"))
continue;
if (line.matches(reg)) {
String[] parts = line.split(" ");
for (String part : parts) {
if (part.startsWith("/"))
if (!StringUtils.containsIgnoreCase(part, "vold"))
out.add(part);
}
}
}
return out;
}
private void setCurrentDirectory(String currentDirectory)
{
SharedPreferences.Editor preferencesEditor = _preferences.edit();
@ -151,6 +211,17 @@ public class MainActivity extends Activity
preferencesEditor.commit();
}
private void clearCurrentDirectory()
{
SharedPreferences.Editor preferencesEditor = _preferences.edit();
preferencesEditor.remove(PREFERENCE_CURRENT_DIRECTORY);
preferencesEditor.commit();
}
public static void resetDirectory() {
((MainActivity) mActivity).clearCurrentDirectory();
}
private static boolean IsLoadableExecutableFileName(String fileName)
{
return fileName.toLowerCase().endsWith(".elf");
@ -166,6 +237,100 @@ public class MainActivity extends Activity
fileName.toLowerCase().endsWith(".isz");
}
private final class ImageFinder extends AsyncTask<String, Integer, List<File>> {
private int array;
public ImageFinder(int arrayType) {
this.array = arrayType;
}
protected void onPreExecute() {
_fileListView.setOnItemClickListener(
new OnItemClickListener()
{
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
//Remove one to compensate for header
position = position - 1;
FileListItem fileListItem = _fileListItems[position];
try
{
if(IsLoadableExecutableFileName(fileListItem.getPath()))
{
NativeInterop.loadElf(fileListItem.getPath());
}
else
{
NativeInterop.bootDiskImage(fileListItem.getPath());
}
setCurrentDirectory(fileListItem.getPath().substring(0, fileListItem.getPath().lastIndexOf(File.separator)));
}
catch(Exception ex)
{
displaySimpleMessage("Error", ex.getMessage());
return;
}
//TODO: Catch errors that might happen while loading files
Intent intent = new Intent(getApplicationContext(), EmulatorActivity.class);
startActivity(intent);
}
}
);
}
@Override
protected List<File> doInBackground(String... paths) {
File storage = new File(paths[0]);
String[] mediaTypes = MainActivity.this.getResources().getStringArray(array);
FilenameFilter[] filter = new FilenameFilter[mediaTypes.length];
int i = 0;
for (final String type : mediaTypes) {
filter[i] = new FilenameFilter() {
public boolean accept(File dir, String name) {
if (dir.getName().startsWith(".") || name.startsWith(".")) {
return false;
} else {
return StringUtils.endsWithIgnoreCase(name, "." + type);
}
}
};
i++;
}
FileUtils fileUtils = new FileUtils();
Collection<File> files = fileUtils.listFiles(storage, filter, -1);
return (List<File>) files;
}
@Override
protected void onPostExecute(List<File> images) {
if (images != null && !images.isEmpty()) {
// Create the list of acceptable images
for(File file : images)
{
fileListItems.add(new FileListItem(file.getAbsolutePath()));
}
Collections.sort(fileListItems);
_fileListItems = fileListItems.toArray(new FileListItem[images.size()]);
ArrayAdapter<FileListItem> adapter = new ArrayAdapter<FileListItem>(MainActivity.this,
android.R.layout.simple_list_item_1, android.R.id.text1, _fileListItems);
_fileListView.setAdapter(adapter);
} else {
// Display warning that no disks exist
}
}
}
private static FileListItem[] getFileList(String directoryPath)
{
ArrayList<FileListItem> fileListItems = new ArrayList<FileListItem>();
@ -203,54 +368,56 @@ public class MainActivity extends Activity
_fileListView.addHeaderView(header, null, false);
_fileListView.setOnItemClickListener(
new OnItemClickListener()
{
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
//Remove one to compensate for header
position = position - 1;
FileListItem fileListItem = _fileListItems[position];
if(fileListItem.isParentDirectory())
{
File currentDirectoryFile = new File(getCurrentDirectory());
File parentDirectoryFile = currentDirectoryFile.getParentFile();
if(parentDirectoryFile == null) return;
setCurrentDirectory(currentDirectoryFile.getParentFile().getAbsolutePath());
updateFileListView();
}
else if(fileListItem.isDirectory())
{
setCurrentDirectory(fileListItem.getPath());
updateFileListView();
}
else
{
try
{
if(IsLoadableExecutableFileName(fileListItem.getPath()))
{
NativeInterop.loadElf(fileListItem.getPath());
}
else
{
NativeInterop.bootDiskImage(fileListItem.getPath());
}
}
catch(Exception ex)
{
displaySimpleMessage("Error", ex.getMessage());
return;
}
//TODO: Catch errors that might happen while loading files
Intent intent = new Intent(getApplicationContext(), EmulatorActivity.class);
startActivity(intent);
}
}
}
);
// _fileListView.setOnItemClickListener(
// new OnItemClickListener()
// {
// @Override
// public void onItemClick(AdapterView<?> parent, View view, int position, long id)
// {
// //Remove one to compensate for header
// position = position - 1;
//
// FileListItem fileListItem = _fileListItems[position];
// if(fileListItem.isParentDirectory())
// {
// File currentDirectoryFile = new File(getCurrentDirectory());
// File parentDirectoryFile = currentDirectoryFile.getParentFile();
// if(parentDirectoryFile == null) return;
// setCurrentDirectory(currentDirectoryFile.getParentFile().getAbsolutePath());
// updateFileListView();
// }
// else if(fileListItem.isDirectory())
// {
// setCurrentDirectory(fileListItem.getPath());
// updateFileListView();
// }
// else
// {
// try
// {
// if(IsLoadableExecutableFileName(fileListItem.getPath()))
// {
// NativeInterop.loadElf(fileListItem.getPath());
// }
// else
// {
// NativeInterop.bootDiskImage(fileListItem.getPath());
// }
// }
// catch(Exception ex)
// {
// displaySimpleMessage("Error", ex.getMessage());
// return;
// }
// //TODO: Catch errors that might happen while loading files
// Intent intent = new Intent(getApplicationContext(), EmulatorActivity.class);
// startActivity(intent);
// }
// }
// }
// );
fileListItems = new ArrayList<FileListItem>();
}
private void updateFileListView()

View File

@ -45,6 +45,17 @@ public class SettingsActivity extends PreferenceActivity
checkBoxPref.setChecked(SettingsManager.getPreferenceBoolean(checkBoxPref.getKey()));
}
}
Preference button = (Preference)getPreferenceManager().findPreference("ui.clearfolder");
if (button != null) {
button.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference arg0) {
MainActivity.resetDirectory();
return true;
}
});
}
}
@Override

Binary file not shown.

Binary file not shown.

View File

@ -3,5 +3,16 @@
<string name="app_name">Play!</string>
<string name="main_menu_settings">Settings</string>
<string name="main_menu_about">About</string>
<string name="main_menu_exit">Exit</string>
<string name="main_menu_exit">Exit</string>
<string-array name="disks">
<item>iso</item>
<item>bin</item>
<item>cso</item>
<item>isz</item>
</string-array>
<string-array name="elves">
<item>elf</item>
</string-array>
</resources>

View File

@ -11,4 +11,10 @@
android:summary="Show virtual pad on screen."
android:persistent="false"
/>
<Preference
android:key="ui.clearfolder"
android:title="Reset Folder"
android:summary="Clear stored default folder."
android:persistent="false"
/>
</PreferenceScreen>