143 lines
No EOL
5.6 KiB
Kotlin
143 lines
No EOL
5.6 KiB
Kotlin
package ani.dantotsu.addons
|
|
|
|
import android.content.Context
|
|
import android.content.pm.PackageInfo
|
|
import android.content.pm.PackageManager
|
|
import android.os.Build
|
|
import androidx.core.content.pm.PackageInfoCompat
|
|
import ani.dantotsu.addons.download.DownloadAddon
|
|
import ani.dantotsu.addons.download.DownloadAddonApi
|
|
import ani.dantotsu.addons.download.DownloadAddonManager
|
|
import ani.dantotsu.addons.download.DownloadLoadResult
|
|
import ani.dantotsu.addons.torrent.TorrentAddon
|
|
import ani.dantotsu.addons.torrent.TorrentAddonApi
|
|
import ani.dantotsu.addons.torrent.TorrentAddonManager
|
|
import ani.dantotsu.addons.torrent.TorrentLoadResult
|
|
import ani.dantotsu.media.AddonType
|
|
import ani.dantotsu.util.Logger
|
|
import dalvik.system.PathClassLoader
|
|
import eu.kanade.tachiyomi.extension.util.ExtensionLoader
|
|
import eu.kanade.tachiyomi.util.system.getApplicationIcon
|
|
|
|
class AddonLoader {
|
|
companion object {
|
|
fun loadExtension(
|
|
context: Context,
|
|
packageName: String,
|
|
className: String,
|
|
type: AddonType
|
|
): LoadResult? {
|
|
val pkgManager = context.packageManager
|
|
|
|
val installedPkgs = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
|
pkgManager.getInstalledPackages(PackageManager.PackageInfoFlags.of(ExtensionLoader.PACKAGE_FLAGS.toLong()))
|
|
} else {
|
|
pkgManager.getInstalledPackages(ExtensionLoader.PACKAGE_FLAGS)
|
|
}
|
|
|
|
val extPkgs = installedPkgs.filter {
|
|
isPackageAnExtension(
|
|
packageName,
|
|
it
|
|
)
|
|
}
|
|
|
|
if (extPkgs.isEmpty()) return null
|
|
if (extPkgs.size > 1) throw IllegalStateException("Multiple extensions with the same package name found")
|
|
|
|
val pkgName = extPkgs.first().packageName
|
|
val pkgInfo = extPkgs.first()
|
|
|
|
val appInfo = try {
|
|
pkgManager.getApplicationInfo(pkgName, PackageManager.GET_META_DATA)
|
|
} catch (error: PackageManager.NameNotFoundException) {
|
|
// Unlikely, but the package may have been uninstalled at this point
|
|
Logger.log(error)
|
|
throw error
|
|
}
|
|
|
|
val extName =
|
|
pkgManager.getApplicationLabel(appInfo).toString().substringAfter("Dantotsu: ")
|
|
val versionName = pkgInfo.versionName
|
|
val versionCode = PackageInfoCompat.getLongVersionCode(pkgInfo)
|
|
|
|
if (versionName.isNullOrEmpty()) {
|
|
Logger.log("Missing versionName for extension $extName")
|
|
throw IllegalStateException("Missing versionName for extension $extName")
|
|
}
|
|
val classLoader =
|
|
PathClassLoader(appInfo.sourceDir, appInfo.nativeLibraryDir, context.classLoader)
|
|
val loadedClass = try {
|
|
Class.forName(className, false, classLoader)
|
|
} catch (e: ClassNotFoundException) {
|
|
Logger.log("Extension load error: $extName ($className)")
|
|
Logger.log(e)
|
|
throw e
|
|
} catch (e: NoClassDefFoundError) {
|
|
Logger.log("Extension load error: $extName ($className)")
|
|
Logger.log(e)
|
|
throw e
|
|
} catch (e: Exception) {
|
|
Logger.log("Extension load error: $extName ($className)")
|
|
Logger.log(e)
|
|
throw e
|
|
}
|
|
val instance = loadedClass.getDeclaredConstructor().newInstance()
|
|
|
|
return when (type) {
|
|
AddonType.TORRENT -> {
|
|
val extension = instance as? TorrentAddonApi
|
|
?: throw IllegalStateException("Extension is not a TorrentAddonApi")
|
|
TorrentLoadResult.Success(
|
|
TorrentAddon.Installed(
|
|
name = extName,
|
|
pkgName = pkgName,
|
|
versionName = versionName,
|
|
versionCode = versionCode,
|
|
extension = extension,
|
|
icon = context.getApplicationIcon(pkgName),
|
|
)
|
|
)
|
|
}
|
|
|
|
AddonType.DOWNLOAD -> {
|
|
val extension = instance as? DownloadAddonApi
|
|
?: throw IllegalStateException("Extension is not a DownloadAddonApi")
|
|
DownloadLoadResult.Success(
|
|
DownloadAddon.Installed(
|
|
name = extName,
|
|
pkgName = pkgName,
|
|
versionName = versionName,
|
|
versionCode = versionCode,
|
|
extension = extension,
|
|
icon = context.getApplicationIcon(pkgName),
|
|
)
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
fun loadFromPkgName(context: Context, packageName: String, type: AddonType): LoadResult? {
|
|
return when (type) {
|
|
AddonType.TORRENT -> loadExtension(
|
|
context,
|
|
packageName,
|
|
TorrentAddonManager.TORRENT_CLASS,
|
|
type
|
|
)
|
|
|
|
AddonType.DOWNLOAD -> loadExtension(
|
|
context,
|
|
packageName,
|
|
DownloadAddonManager.DOWNLOAD_CLASS,
|
|
type
|
|
)
|
|
}
|
|
}
|
|
|
|
private fun isPackageAnExtension(type: String, pkgInfo: PackageInfo): Boolean {
|
|
return pkgInfo.packageName.equals(type)
|
|
}
|
|
}
|
|
|
|
} |