mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-11-17 17:39:19 +01:00
Update extension loader
This commit is contained in:
parent
7425478a55
commit
03967b67cf
@ -80,78 +80,58 @@ open class SourceManager(private val context: Context) {
|
|||||||
return sources
|
return sources
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createExtensionSources(): List<HttpSource> {
|
private fun createExtensionSources(): List<Source> {
|
||||||
val pkgManager = context.packageManager
|
val pkgManager = context.packageManager
|
||||||
val flags = PackageManager.GET_CONFIGURATIONS or PackageManager.GET_SIGNATURES
|
val flags = PackageManager.GET_CONFIGURATIONS or PackageManager.GET_SIGNATURES
|
||||||
val installedPkgs = pkgManager.getInstalledPackages(flags)
|
val installedPkgs = pkgManager.getInstalledPackages(flags)
|
||||||
val extPkgs = installedPkgs.filter { it.reqFeatures.orEmpty().any { it.name == FEATURE } }
|
val extPkgs = installedPkgs.filter { it.reqFeatures.orEmpty().any { it.name == EXTENSION_FEATURE } }
|
||||||
|
|
||||||
val sources = mutableListOf<HttpSource>()
|
val sources = mutableListOf<Source>()
|
||||||
for (pkgInfo in extPkgs) {
|
for (pkgInfo in extPkgs) {
|
||||||
val appInfo = pkgManager.getApplicationInfo(pkgInfo.packageName,
|
val appInfo = pkgManager.getApplicationInfo(pkgInfo.packageName,
|
||||||
PackageManager.GET_META_DATA) ?: continue
|
PackageManager.GET_META_DATA) ?: continue
|
||||||
|
|
||||||
|
val extName = pkgManager.getApplicationLabel(appInfo).toString()
|
||||||
val data = appInfo.metaData
|
.substringAfter("Tachiyomi: ")
|
||||||
val extName = data.getString(NAME)
|
val version = pkgInfo.versionName
|
||||||
val version = data.getInt(VERSION)
|
var sourceClass = appInfo.metaData.getString(METADATA_SOURCE_CLASS)
|
||||||
val sourceClass = extendClassName(data.getString(SOURCE), pkgInfo.packageName)
|
if (sourceClass.startsWith(".")) {
|
||||||
|
sourceClass = pkgInfo.packageName + sourceClass
|
||||||
val ext = Extension(extName, appInfo, version, sourceClass)
|
|
||||||
if (!validateExtension(ext)) {
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val instance = loadExtension(ext, pkgManager)
|
val extension = Extension(extName, appInfo, version, sourceClass)
|
||||||
if (instance == null) {
|
try {
|
||||||
Timber.e("Extension error: failed to instance $extName")
|
val instance = loadExtension(extension)
|
||||||
continue
|
sources.add(instance)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Timber.e("Extension load error: $extName. Reason: ${e.message}")
|
||||||
|
} catch (e: LinkageError) {
|
||||||
|
Timber.e("Extension load error: $extName. Reason: ${e.message}")
|
||||||
}
|
}
|
||||||
sources.add(instance)
|
|
||||||
}
|
}
|
||||||
return sources
|
return sources
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun validateExtension(ext: Extension): Boolean {
|
private fun loadExtension(ext: Extension): Source {
|
||||||
if (ext.version < LIB_VERSION_MIN || ext.version > LIB_VERSION_MAX) {
|
// Validate lib version
|
||||||
Timber.e("Extension error: ${ext.name} has version ${ext.version}, while only versions "
|
val majorLibVersion = ext.version.substringBefore('.').toInt()
|
||||||
|
if (majorLibVersion < LIB_VERSION_MIN || majorLibVersion > LIB_VERSION_MAX) {
|
||||||
|
throw Exception("Lib version is $majorLibVersion, while only versions "
|
||||||
+ "$LIB_VERSION_MIN to $LIB_VERSION_MAX are allowed")
|
+ "$LIB_VERSION_MIN to $LIB_VERSION_MAX are allowed")
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadExtension(ext: Extension, pkgManager: PackageManager): HttpSource? {
|
val classLoader = PathClassLoader(ext.appInfo.sourceDir, null, context.classLoader)
|
||||||
return try {
|
return Class.forName(ext.sourceClass, false, classLoader).newInstance() as Source
|
||||||
val classLoader = PathClassLoader(ext.appInfo.sourceDir, null, context.classLoader)
|
|
||||||
val resources = pkgManager.getResourcesForApplication(ext.appInfo)
|
|
||||||
|
|
||||||
Class.forName(ext.sourceClass, false, classLoader).newInstance() as? HttpSource
|
|
||||||
} catch (e: Exception) {
|
|
||||||
null
|
|
||||||
} catch (e: LinkageError) {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun extendClassName(className: String, packageName: String): String {
|
|
||||||
return if (className.startsWith(".")) {
|
|
||||||
packageName + className
|
|
||||||
} else {
|
|
||||||
className
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Extension(val name: String,
|
class Extension(val name: String,
|
||||||
val appInfo: ApplicationInfo,
|
val appInfo: ApplicationInfo,
|
||||||
val version: Int,
|
val version: String,
|
||||||
val sourceClass: String)
|
val sourceClass: String)
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
const val FEATURE = "tachiyomi.extension"
|
const val EXTENSION_FEATURE = "tachiyomi.extension"
|
||||||
const val NAME = "tachiyomi.extension.name"
|
const val METADATA_SOURCE_CLASS = "tachiyomi.extension.class"
|
||||||
const val VERSION = "tachiyomi.extension.version"
|
|
||||||
const val SOURCE = "tachiyomi.extension.source"
|
|
||||||
const val LIB_VERSION_MIN = 1
|
const val LIB_VERSION_MIN = 1
|
||||||
const val LIB_VERSION_MAX = 1
|
const val LIB_VERSION_MAX = 1
|
||||||
}
|
}
|
||||||
|
@ -25,12 +25,12 @@ abstract class HttpSource : CatalogueSource {
|
|||||||
/**
|
/**
|
||||||
* Network service.
|
* Network service.
|
||||||
*/
|
*/
|
||||||
val network: NetworkHelper by injectLazy()
|
protected val network: NetworkHelper by injectLazy()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Preferences helper.
|
* Preferences helper.
|
||||||
*/
|
*/
|
||||||
val preferences: PreferencesHelper by injectLazy()
|
protected val preferences: PreferencesHelper by injectLazy()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base url of the website without the trailing slash, like: http://mysite.com
|
* Base url of the website without the trailing slash, like: http://mysite.com
|
||||||
|
Loading…
Reference in New Issue
Block a user