[General Questions and Answers] hollowww:
I bought an Android powered E-Ink reader (Meebook M6, Android 11, No Play Services) and found that it's builtin reader app could set the cover of the book I'm currently reading as the "idle screen" (e-ink don't use battery when static).

It does it by simply setting the wallpaper to the picture and I found I could also do it with the builtin gallery (Gallery2) with the "Set as wallpaper" option.

So I want to see if I could also use this feature from another reader app.

I first just tried to use WallpaperManager.getInstance(context).setStream(myStream)​

I added the android.permission.SET_WALLPAPER permission in the manifest.

The WallpaperManager I received was a DisabledWallPaperManager, both isWallpaperSupported() and isSetWallpaperAllowed() returns false and throws an exception when trying to use any set* method. I also tried the deprecated context.setWallpaper(myBitmap) which doesn't crash but don't do anything.

I then tried pulling and reversing the Launcher apk, both the Gallery and Reader seemed to be embedded in it ?​

By decompiling it with decompiler.com I found this :

public static void saveBook(Context context, Bitmap bitmap) {
save(bitmap, new File("/data/haoqing/bookStandby.png"), Bitmap.CompressFormat.PNG, true); // this file has -rw------- 1 system system permissions
FunctionUtil.setStandbyWallpaper(context, "/data/haoqing/bookStandby.png", false);
}

public static void setStandbyWallpaper(Context context, String str, boolean z) {
Intent intent = new Intent("com.haoqing.action.SET_WALLPAPER");
intent.setPackage("com.android.settings");
intent.putExtra("tip", z);
intent.putExtra("filePath", str);
intent.putExtra("flagBitmap", 0);
context.sendBroadcast(intent);
}

I have no control over the intent handler so I need to work around it 😞

I tried to reproduce it in my Kotlin app

val intent = Intent().apply {
action = "com.haoqing.action.SET_WALLPAPER"
setPackage("com.android.settings")
putExtra("tip", true) // Show "Wallpaper Set / Failed" Toast
putExtra("filePath", it.absolutePath) // /storage/emulated/0/Android/data/moe.hollow.sumiyomi.debug/files/covers/032ca94da5aee1b094d38d9858b802c9
putExtra("flagBitmap", 0) // 0..4 value to say which wallpaper set, idle screen seems to be 0
}
try {
context.sendBroadcast(intent)
} catch (e: Exception) {
Log.e("Sumiyomi", e.toString())
}

A fail toast appears logcat shows :

08-03 10:21:20.574 4342 4620 E BitmapFactory: Unable to decode stream: java.io.FileNotFoundException: /storage/emulated/0/Android/data/moe.hollow.sumiyomi.debug/files/covers/032ca94da5aee1b094d38d9858b802c9: open failed: EACCES (Permission denied)

So I tried with this intent :

val uri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider", it)
val intent = Intent().apply {
action = "com.haoqing.action.SET_WALLPAPER"
data = uri
setPackage("com.android.settings")
putExtra("filePath", it.absolutePath)
putExtra("flagBitmap", 0)
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
context.grantUriPermission("com.android.settings", data, Intent.FLAG_GRANT_READ_URI_PERMISSION)
}

Which also gives a permissions error.

I tried passing the Uri as filePath which just crashes the VM(?) and uri.toString gives a File Not Found...

I read since SDK 19 you can't send paths via intents to read a file so I don't know where to look now, is there something I did wrong with the intent ? Or should I search for another method ?