Android: Fix reading custom covers with SAF

If GameFile.getCustomCoverPath returns a mangled URI, we need to
unmangle it before passing it to Picasso, since Picasso has no
concept of Dolphin's mangled URIs.
This commit is contained in:
JosJuice 2022-08-28 23:44:01 +02:00
parent 299aef945b
commit 40d6d615e2
5 changed files with 67 additions and 15 deletions

View File

@ -61,7 +61,7 @@ public class GameFileCache
String path = dolphinIni.getString(Settings.SECTION_INI_GENERAL,
SettingsFile.KEY_ISO_PATH_BASE + i, "");
if (path.startsWith("content://") ? ContentHandler.exists(path) : new File(path).exists())
if (ContentHandler.isContentUri(path) ? ContentHandler.exists(path) : new File(path).exists())
{
pathSet.add(path);
}

View File

@ -37,6 +37,11 @@ import java.util.function.Predicate;
public class ContentHandler
{
public static boolean isContentUri(@NonNull String pathOrUri)
{
return pathOrUri.startsWith("content://");
}
@Keep
public static int openFd(@NonNull String uri, @NonNull String mode)
{
@ -336,7 +341,7 @@ public class ContentHandler
* provider to use URIs without any % characters.
*/
@NonNull
private static Uri unmangle(@NonNull String uri) throws FileNotFoundException, SecurityException
public static Uri unmangle(@NonNull String uri) throws FileNotFoundException, SecurityException
{
int lastComponentEnd = getLastComponentEnd(uri);
int lastComponentStart = getLastComponentStart(uri, lastComponentEnd);

View File

@ -82,9 +82,16 @@ public final class FileBrowserHelper
return isPathEmptyOrValid(path.getStringGlobal());
}
/**
* Returns true if at least one of the following applies:
*
* 1. The input is empty.
* 2. The input is something which is not a content URI.
* 3. The input is a content URI that points to a file that exists and we're allowed to access.
*/
public static boolean isPathEmptyOrValid(String path)
{
return !path.startsWith("content://") || ContentHandler.exists(path);
return !ContentHandler.isContentUri(path) || ContentHandler.exists(path);
}
public static void runAfterExtensionCheck(Context context, Uri uri, Set<String> validExtensions,

View File

@ -18,6 +18,7 @@ import org.dolphinemu.dolphinemu.model.GameFile;
import org.dolphinemu.dolphinemu.viewholders.GameViewHolder;
import java.io.File;
import java.io.FileNotFoundException;
public class PicassoUtils
{
@ -54,12 +55,33 @@ public class PicassoUtils
gameViewHolder.textGameCaption.setVisibility(View.GONE);
}
String customCoverPath = gameFile.getCustomCoverPath();
Uri customCoverUri = null;
boolean customCoverExists = false;
if (ContentHandler.isContentUri(customCoverPath))
{
try
{
customCoverUri = ContentHandler.unmangle(customCoverPath);
customCoverExists = true;
}
catch (FileNotFoundException | SecurityException ignored)
{
// Let customCoverExists remain false
}
}
else
{
customCoverUri = Uri.parse(customCoverPath);
customCoverExists = new File(customCoverPath).exists();
}
Context context = imageView.getContext();
File cover = new File(gameFile.getCustomCoverPath());
if (cover.exists())
File cover;
if (customCoverExists)
{
Picasso.get()
.load(cover)
.load(customCoverUri)
.noFade()
.noPlaceholder()
.fit()

View File

@ -34,6 +34,7 @@ import org.dolphinemu.dolphinemu.services.SyncProgramsJobService;
import org.dolphinemu.dolphinemu.ui.platform.Platform;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
@ -155,26 +156,43 @@ public class TvUtil
}
/**
* Leanback lanucher requires a uri for poster art so we create a contentUri and
* Leanback launcher requires a uri for poster art so we create a contentUri and
* pass that to LEANBACK_PACKAGE
*/
public static Uri buildBanner(GameFile game, Context context)
{
Uri contentUri = null;
File cover;
try
{
File cover = new File(game.getCustomCoverPath());
if (cover.exists())
String customCoverPath = game.getCustomCoverPath();
if (ContentHandler.isContentUri(customCoverPath))
{
try
{
contentUri = ContentHandler.unmangle(customCoverPath);
}
catch (FileNotFoundException | SecurityException ignored)
{
// Let contentUri remain null
}
}
else
{
if ((cover = new File(customCoverPath)).exists())
{
contentUri = getUriForFile(context, getFileProvider(context), cover);
}
}
if (contentUri == null && (cover = new File(game.getCoverPath(context))).exists())
{
contentUri = getUriForFile(context, getFileProvider(context), cover);
}
else if ((cover = new File(game.getCoverPath(context))).exists())
{
contentUri = getUriForFile(context, getFileProvider(context), cover);
}
context.grantUriPermission(LEANBACK_PACKAGE, contentUri,
FLAG_GRANT_READ_URI_PERMISSION);
context.grantUriPermission(LEANBACK_PACKAGE, contentUri, FLAG_GRANT_READ_URI_PERMISSION);
}
catch (Exception e)
{