Android: Show a message when adding a folder with no games

To catch people who try to use unsupported formats.
This commit is contained in:
JosJuice 2020-11-08 23:01:59 +01:00
parent 399ede37a6
commit 73855168f3
7 changed files with 69 additions and 23 deletions

View File

@ -15,12 +15,15 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import org.dolphinemu.dolphinemu.BuildConfig;
import org.dolphinemu.dolphinemu.NativeLibrary;
import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.features.settings.model.BooleanSetting;
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;
import org.dolphinemu.dolphinemu.model.GameFileCache;
import org.dolphinemu.dolphinemu.services.GameFileCacheService;
import org.dolphinemu.dolphinemu.utils.AfterDirectoryInitializationRunner;
import org.dolphinemu.dolphinemu.utils.ContentHandler;
import org.dolphinemu.dolphinemu.utils.FileBrowserHelper;
import java.util.Arrays;
import java.util.Set;
public final class MainPresenter
@ -123,9 +126,21 @@ public final class MainPresenter
public void onDirectorySelected(Intent result)
{
ContentResolver contentResolver = mContext.getContentResolver();
Uri uri = result.getData();
boolean recursive = BooleanSetting.MAIN_RECURSIVE_ISO_PATHS.getBooleanGlobal();
String[] childNames = ContentHandler.getChildNames(uri, recursive);
if (Arrays.stream(childNames).noneMatch((name) ->
FileBrowserHelper.GAME_EXTENSIONS.contains(FileBrowserHelper.getExtension(name))))
{
AlertDialog.Builder builder = new AlertDialog.Builder(mContext, R.style.DolphinDialogBase);
builder.setMessage(mContext.getString(R.string.wrong_file_extension_in_directory,
FileBrowserHelper.setToSortedDelimitedString(FileBrowserHelper.GAME_EXTENSIONS)));
builder.setPositiveButton(R.string.ok, null);
builder.show();
}
ContentResolver contentResolver = mContext.getContentResolver();
Uri canonicalizedUri = contentResolver.canonicalize(uri);
if (canonicalizedUri != null)
uri = canonicalizedUri;

View File

@ -14,6 +14,7 @@ import androidx.annotation.Keep;
import org.dolphinemu.dolphinemu.DolphinApplication;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
/*
@ -166,26 +167,52 @@ public class ContentHandler
}
@NonNull @Keep
public static String[] getChildNames(@NonNull String uri)
public static String[] getChildNames(@NonNull String uri, boolean recursive)
{
try
{
Uri unmangledUri = unmangle(uri);
String documentId = DocumentsContract.getDocumentId(treeToDocument(unmangledUri));
Uri childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(unmangledUri, documentId);
return getChildNames(unmangle(uri), recursive);
}
catch (Exception ignored)
{
}
final String[] projection = new String[]{Document.COLUMN_DISPLAY_NAME};
return new String[0];
}
@NonNull
public static String[] getChildNames(@NonNull Uri uri, boolean recursive)
{
ArrayList<String> result = new ArrayList<>();
getChildNames(uri, DocumentsContract.getDocumentId(treeToDocument(uri)), recursive, result);
return result.toArray(new String[0]);
}
private static void getChildNames(@NonNull Uri uri, @NonNull String documentId, boolean recursive,
List<String> resultOut)
{
try
{
Uri childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(uri, documentId);
final String[] projection = recursive ? new String[]{Document.COLUMN_DISPLAY_NAME,
Document.COLUMN_MIME_TYPE, Document.COLUMN_DOCUMENT_ID} :
new String[]{Document.COLUMN_DISPLAY_NAME};
try (Cursor cursor = getContentResolver().query(childrenUri, projection, null, null, null))
{
if (cursor != null)
{
String[] result = new String[cursor.getCount()];
for (int i = 0; i < result.length; i++)
while (cursor.moveToNext())
{
cursor.moveToNext();
result[i] = cursor.getString(0);
if (recursive && Document.MIME_TYPE_DIR.equals(cursor.getString(1)))
{
getChildNames(uri, cursor.getString(2), recursive, resultOut);
}
else
{
resultOut.add(cursor.getString(0));
}
}
return result;
}
}
}
@ -196,8 +223,6 @@ public class ContentHandler
catch (Exception ignored)
{
}
return new String[0];
}
@NonNull

View File

@ -102,10 +102,8 @@ public final class FileBrowserHelper
int messageId = validExtensions.size() == 1 ?
R.string.wrong_file_extension_single : R.string.wrong_file_extension_multiple;
ArrayList<String> extensionsList = new ArrayList<>(validExtensions);
Collections.sort(extensionsList);
message = context.getString(messageId, extension, join(", ", extensionsList));
message = context.getString(messageId, extension,
setToSortedDelimitedString(validExtensions));
}
new AlertDialog.Builder(context, R.style.DolphinDialogBase)
@ -117,7 +115,7 @@ public final class FileBrowserHelper
}
@Nullable
private static String getExtension(@Nullable String fileName)
public static String getExtension(@Nullable String fileName)
{
if (fileName == null)
return null;
@ -126,6 +124,13 @@ public final class FileBrowserHelper
return dotIndex != -1 ? fileName.substring(dotIndex + 1) : null;
}
public static String setToSortedDelimitedString(Set<String> set)
{
ArrayList<String> list = new ArrayList<>(set);
Collections.sort(list);
return join(", ", list);
}
// TODO: Replace this with String.join once we can use Java 8
private static String join(CharSequence delimiter, Iterable<? extends CharSequence> elements)
{

View File

@ -438,6 +438,7 @@ It can efficiently compress both junk data and encrypted Wii data.
<string name="no_file_extension">The selected file does not appear to have a file name extension.\n\nContinue anyway?</string>
<string name="wrong_file_extension_single">The selected file has the file name extension \"%1$s\", but \"%2$s\" was expected.\n\nContinue anyway?</string>
<string name="wrong_file_extension_multiple">The selected file has the file name extension \"%1$s\", but one of these extensions was expected: %2$s\n\nContinue anyway?</string>
<string name="wrong_file_extension_in_directory">No compatible files were found in the selected location.\n\nThe supported formats are: %1$s</string>
<string name="unavailable_paths">Dolphin does not have permission to access one or more configured paths. Would you like to fix this before starting?</string>
<!-- Misc -->

View File

@ -124,9 +124,9 @@ std::string GetAndroidContentDisplayName(const std::string& uri)
std::vector<std::string> GetAndroidContentChildNames(const std::string& uri)
{
JNIEnv* env = IDCache::GetEnvForThread();
jobject children =
env->CallStaticObjectMethod(IDCache::GetContentHandlerClass(),
IDCache::GetContentHandlerGetChildNames(), ToJString(env, uri));
jobject children = env->CallStaticObjectMethod(IDCache::GetContentHandlerClass(),
IDCache::GetContentHandlerGetChildNames(),
ToJString(env, uri), false);
return JStringArrayToVector(env, reinterpret_cast<jobjectArray>(children));
}

View File

@ -35,7 +35,7 @@ jlong GetAndroidContentSizeAndIsDirectory(const std::string& uri);
// An empty string will be returned for files which do not exist.
std::string GetAndroidContentDisplayName(const std::string& uri);
// Returns the display names of all children of a directory.
// Returns the display names of all children of a directory, non-recursively.
std::vector<std::string> GetAndroidContentChildNames(const std::string& uri);
int GetNetworkIpAddress();

View File

@ -330,7 +330,7 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved)
s_content_handler_get_display_name = env->GetStaticMethodID(
s_content_handler_class, "getDisplayName", "(Ljava/lang/String;)Ljava/lang/String;");
s_content_handler_get_child_names = env->GetStaticMethodID(
s_content_handler_class, "getChildNames", "(Ljava/lang/String;)[Ljava/lang/String;");
s_content_handler_class, "getChildNames", "(Ljava/lang/String;Z)[Ljava/lang/String;");
const jclass network_helper_class =
env->FindClass("org/dolphinemu/dolphinemu/utils/NetworkHelper");