Android: Scan on background thread and show progress

This commit is contained in:
Connor McLaughlin
2020-10-24 15:46:08 +10:00
parent 5084c90e08
commit e22c7608e3
9 changed files with 314 additions and 17 deletions

View File

@ -55,7 +55,7 @@ public class AndroidHostInterface {
public static native int getControllerAxisCode(String controllerType, String axisName);
public native void refreshGameList(boolean invalidateCache, boolean invalidateDatabase);
public native void refreshGameList(boolean invalidateCache, boolean invalidateDatabase, AndroidProgressCallback progressCallback);
public native GameListEntry[] getGameListEntries();

View File

@ -0,0 +1,140 @@
package com.github.stenzek.duckstation;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.util.Log;
import androidx.appcompat.app.AlertDialog;
public class AndroidProgressCallback {
private Activity mContext;
private ProgressDialog mDialog;
public AndroidProgressCallback(Activity context) {
mContext = context;
mDialog = new ProgressDialog(context);
mDialog.setMessage("Please wait...");
mDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mDialog.setIndeterminate(false);
mDialog.setMax(100);
mDialog.setProgress(0);
mDialog.show();
}
public void dismiss() {
mDialog.dismiss();
}
public void setTitle(String text) {
mContext.runOnUiThread(() -> {
mDialog.setTitle(text);
});
}
public void setStatusText(String text) {
mContext.runOnUiThread(() -> {
mDialog.setMessage(text);
});
}
public void setProgressRange(int range) {
mContext.runOnUiThread(() -> {
mDialog.setMax(range);
});
}
public void setProgressValue(int value) {
mContext.runOnUiThread(() -> {
mDialog.setProgress(value);
});
}
public void modalError(String message) {
Object lock = new Object();
mContext.runOnUiThread(() -> {
new AlertDialog.Builder(mContext)
.setTitle("Error")
.setMessage(message)
.setPositiveButton("OK", (dialog, button) -> {
dialog.dismiss();
})
.setOnDismissListener((dialogInterface) -> {
synchronized (lock) {
lock.notify();
}
})
.create()
.show();
});
synchronized (lock) {
try {
lock.wait();
} catch (InterruptedException e) {
}
}
}
public void modalInformation(String message) {
Object lock = new Object();
mContext.runOnUiThread(() -> {
new AlertDialog.Builder(mContext)
.setTitle("Information")
.setMessage(message)
.setPositiveButton("OK", (dialog, button) -> {
dialog.dismiss();
})
.setOnDismissListener((dialogInterface) -> {
synchronized (lock) {
lock.notify();
}
})
.create()
.show();
});
synchronized (lock) {
try {
lock.wait();
} catch (InterruptedException e) {
}
}
}
private class ConfirmationResult {
public boolean result = false;
}
public boolean modalConfirmation(String message) {
ConfirmationResult result = new ConfirmationResult();
mContext.runOnUiThread(() -> {
new AlertDialog.Builder(mContext)
.setTitle("Confirmation")
.setMessage(message)
.setPositiveButton("Yes", (dialog, button) -> {
result.result = true;
dialog.dismiss();
})
.setNegativeButton("No", (dialog, button) -> {
result.result = false;
dialog.dismiss();
})
.setOnDismissListener((dialogInterface) -> {
synchronized (result) {
result.notify();
}
})
.create()
.show();
});
synchronized (result) {
try {
result.wait();
} catch (InterruptedException e) {
}
}
return result.result;
}
}

View File

@ -3,6 +3,7 @@ package com.github.stenzek.duckstation;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.util.ArraySet;
import android.view.LayoutInflater;
import android.view.View;
@ -17,11 +18,11 @@ import java.util.Comparator;
import java.util.Set;
public class GameList {
private Context mContext;
private Activity mContext;
private GameListEntry[] mEntries;
private ListViewAdapter mAdapter;
public GameList(Context context) {
public GameList(Activity context) {
mContext = context;
mAdapter = new ListViewAdapter();
mEntries = new GameListEntry[0];
@ -35,12 +36,20 @@ public class GameList {
}
public void refresh(boolean invalidateCache, boolean invalidateDatabase) {
public void refresh(boolean invalidateCache, boolean invalidateDatabase, Activity parentActivity) {
// Search and get entries from native code
AndroidHostInterface.getInstance().refreshGameList(invalidateCache, invalidateDatabase);
mEntries = AndroidHostInterface.getInstance().getGameListEntries();
Arrays.sort(mEntries, new GameListEntryComparator());
mAdapter.notifyDataSetChanged();
AndroidProgressCallback progressCallback = new AndroidProgressCallback(mContext);
AsyncTask.execute(() -> {
AndroidHostInterface.getInstance().refreshGameList(invalidateCache, invalidateDatabase, progressCallback);
GameListEntry[] newEntries = AndroidHostInterface.getInstance().getGameListEntries();
Arrays.sort(newEntries, new GameListEntryComparator());
mContext.runOnUiThread(() -> {
progressCallback.dismiss();
mEntries = newEntries;
mAdapter.notifyDataSetChanged();
});
});
}
public int getEntryCount() {

View File

@ -127,7 +127,7 @@ public class MainActivity extends AppCompatActivity {
throw new RuntimeException("Failed to create host interface");
}
mGameList.refresh(false, false);
mGameList.refresh(false, false, this);
}
private void startAddGameDirectory() {
@ -163,9 +163,9 @@ public class MainActivity extends AppCompatActivity {
} else if (id == R.id.action_add_game_directory) {
startAddGameDirectory();
} else if (id == R.id.action_scan_for_new_games) {
mGameList.refresh(false, false);
mGameList.refresh(false, false, this);
} else if (id == R.id.action_rescan_all_games) {
mGameList.refresh(true, true);
mGameList.refresh(true, true, this);
} else if (id == R.id.action_import_bios) {
importBIOSImage();
} else if (id == R.id.action_settings) {
@ -210,7 +210,7 @@ public class MainActivity extends AppCompatActivity {
editor.putStringSet("GameList/RecursivePaths", currentValues);
editor.apply();
Log.i("MainActivity", "Added path '" + path + "' to game list search directories");
mGameList.refresh(false, false);
mGameList.refresh(false, false, this);
}
break;