Skip to content

Commit

Permalink
[FM] Generate APKS/XAPK icon
Browse files Browse the repository at this point in the history
First look for `icon.png`. If it's not present, load icon from the base APK.
The latter operation can be very expensive. In a directory full of XAPK files,
it may take several seconds to load all the icons properly for the first time.

Signed-off-by: Muntashir Al-Islam <[email protected]>
  • Loading branch information
MuntashirAkon committed Nov 17, 2024
1 parent 576f37a commit e42e885
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -80,21 +80,29 @@ public ImageLoader.ImageFetcherResult fetchImage(@NonNull String tag) {
return new ImageLoader.ImageFetcherResult(tag, getThumbnail(bitmap, size, true),
false, true, defaultImage);
}
} else if (ContentType.APK.getMimeType().equals(mimeType)) {
Bitmap bitmap = FmIcons.generateApkIcon(mFmItem.path);
if (bitmap != null) {
return new ImageLoader.ImageFetcherResult(tag, getThumbnail(bitmap, size, true),
false, true, defaultImage);
}
} else if (ContentType2.APKM.getMimeType().equals(mimeType)) {
Bitmap bitmap = FmIcons.getApkmIcon(mFmItem.path);
if (bitmap != null) {
return new ImageLoader.ImageFetcherResult(tag, getThumbnail(bitmap, size, true),
false, true, defaultImage);
}
}
// Others
if (FmIcons.isAudio(drawableRes)) {
if (FmIcons.isApk(drawableRes)) {
if (ContentType.APK.getMimeType().equals(mimeType)) {
Bitmap bitmap = FmIcons.generateApkIcon(mFmItem.path);
if (bitmap != null) {
return new ImageLoader.ImageFetcherResult(tag, getThumbnail(bitmap, size, true),
false, true, defaultImage);
}
} else if (ContentType2.APKM.getMimeType().equals(mimeType)) {
Bitmap bitmap = FmIcons.getApkmIcon(mFmItem.path);
if (bitmap != null) {
return new ImageLoader.ImageFetcherResult(tag, getThumbnail(bitmap, size, true),
false, true, defaultImage);
}
} else {
Bitmap bitmap = FmIcons.getApksIcon(mFmItem.path);
if (bitmap != null) {
return new ImageLoader.ImageFetcherResult(tag, getThumbnail(bitmap, size, true),
false, true, defaultImage);
}
}
} else if (FmIcons.isAudio(drawableRes)) {
try {
Bitmap bitmap = ThumbnailUtilsCompat.createAudioThumbnail(ContextUtils.getContext(), FmProvider.getContentUri(mFmItem.path), size, null);
return new ImageLoader.ImageFetcherResult(tag, bitmap, false, true, defaultImage);
Expand Down Expand Up @@ -166,7 +174,6 @@ public ImageLoader.ImageFetcherResult fetchImage(@NonNull String tag) {
new ImageLoader.DefaultImageDrawableRes("drawable_" + drawableRes, drawableRes, padding));
}
}
// TODO: 24/5/23 Check XAPK, APKS, APKM icons
return new ImageLoader.ImageFetcherResult(tag, null, defaultImage);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
import java.util.zip.ZipFile;

import io.github.muntashirakon.AppManager.R;
import io.github.muntashirakon.AppManager.apk.ApkFile;
import io.github.muntashirakon.AppManager.apk.UriApkSource;
import io.github.muntashirakon.AppManager.self.filecache.FileCache;
import io.github.muntashirakon.AppManager.utils.ContextUtils;
import io.github.muntashirakon.AppManager.utils.FileUtils;
Expand Down Expand Up @@ -269,6 +271,10 @@ public static int getDrawableFromType(@Nullable String mimeType) {
return drawable != null ? drawable : DRAWABLE_GENERIC;
}

public static boolean isApk(@DrawableRes int drawable) {
return drawable == DRAWABLE_APK;
}

public static boolean isImage(@DrawableRes int drawable) {
return drawable == DRAWABLE_IMAGE;
}
Expand Down Expand Up @@ -390,22 +396,12 @@ public static Bitmap generateApkIcon(@NonNull Path path) {
return null;
}
try {
PackageManager pm = ContextUtils.getContext().getPackageManager();
String f = file.first.getAbsolutePath();
PackageInfo packageInfo = pm.getPackageArchiveInfo(f, 0);
if (packageInfo != null) {
ApplicationInfo info = packageInfo.applicationInfo;
info.sourceDir = info.publicSourceDir = f;
if (info.icon != 0) {
return UIUtils.getBitmapFromDrawable(info.loadIcon(pm));
}
}
return getApkIcon(file.first);
} finally {
if (file.second) {
file.first.delete();
}
}
return null;
}

@Nullable
Expand All @@ -429,6 +425,48 @@ public static Bitmap getApkmIcon(@NonNull Path path) {
return null;
}

@Nullable
public static Bitmap getApksIcon(@NonNull Path path) {
Pair<File, Boolean> file = getUsableFile(path);
if (file == null) {
return null;
}
try (ZipFile zipFile = new ZipFile(file.first)) {
ZipEntry iconEntry = zipFile.getEntry("icon.png");
if (iconEntry != null) {
return BitmapFactory.decodeStream(zipFile.getInputStream(iconEntry));
}
// Load as ApkFile
UriApkSource apkSource = new UriApkSource(Uri.fromFile(file.first), path.getType());
try (ApkFile apkFile = apkSource.resolve()) {
ApkFile.Entry baseEntry = apkFile.getBaseEntry();
return getApkIcon(baseEntry.getFile(false));
}
} catch (IOException | ApkFile.ApkFileException e) {
e.printStackTrace();
} finally {
if (file.second) {
file.first.delete();
}
}
return null;
}

@Nullable
private static Bitmap getApkIcon(@NonNull File apkFile) {
PackageManager pm = ContextUtils.getContext().getPackageManager();
String f = apkFile.getAbsolutePath();
PackageInfo packageInfo = pm.getPackageArchiveInfo(f, 0);
if (packageInfo != null) {
ApplicationInfo info = packageInfo.applicationInfo;
info.sourceDir = info.publicSourceDir = f;
if (info.icon != 0) {
return UIUtils.getBitmapFromDrawable(info.loadIcon(pm));
}
}
return null;
}

@Nullable
private static Pair<File, Boolean> getUsableFile(@NonNull Path path) {
File f = path.getFile();
Expand Down

0 comments on commit e42e885

Please sign in to comment.