Allow multiple sources in each extension source apk (#761)

* Allow multiple sources in each extension source apk

Minor code cleanup

* Add runtime defined sources functionality

* Undo extensions library major version number bump
This commit is contained in:
Andy Bao 2017-04-27 14:15:55 -04:00 committed by inorichi
parent 8df3080e0d
commit b7b83305b2
2 changed files with 36 additions and 13 deletions

View File

@ -0,0 +1,12 @@
package eu.kanade.tachiyomi.source
/**
* A factory for creating sources at runtime.
*/
interface SourceFactory {
/**
* Create a new copy of the sources
* @return The created sources
*/
fun createSources(): List<Source>
}

View File

@ -74,7 +74,7 @@ open class SourceManager(private val context: Context) {
val map = file.inputStream().use { yaml.loadAs(it, Map::class.java) }
sources.add(YamlHttpSource(map))
} catch (e: Exception) {
Timber.e("Error loading source from file. Bad format?")
Timber.e("Error loading source from file. Bad format?", e)
}
}
}
@ -95,25 +95,29 @@ open class SourceManager(private val context: Context) {
val extName = pkgManager.getApplicationLabel(appInfo).toString()
.substringAfter("Tachiyomi: ")
val version = pkgInfo.versionName
var sourceClass = appInfo.metaData.getString(METADATA_SOURCE_CLASS)
if (sourceClass.startsWith(".")) {
sourceClass = pkgInfo.packageName + sourceClass
}
val sourceClasses = appInfo.metaData.getString(METADATA_SOURCE_CLASS)
.split(";")
.map {
val sourceClass = it.trim()
if(sourceClass.startsWith("."))
pkgInfo.packageName + sourceClass
else
sourceClass
}
val extension = Extension(extName, appInfo, version, sourceClass)
val extension = Extension(extName, appInfo, version, sourceClasses)
try {
val instance = loadExtension(extension)
sources.add(instance)
sources += loadExtension(extension)
} catch (e: Exception) {
Timber.e("Extension load error: $extName. Reason: ${e.message}")
Timber.e("Extension load error: $extName.", e)
} catch (e: LinkageError) {
Timber.e("Extension load error: $extName. Reason: ${e.message}")
Timber.e("Extension load error: $extName.", e)
}
}
return sources
}
private fun loadExtension(ext: Extension): Source {
private fun loadExtension(ext: Extension): List<Source> {
// Validate lib version
val majorLibVersion = ext.version.substringBefore('.').toInt()
if (majorLibVersion < LIB_VERSION_MIN || majorLibVersion > LIB_VERSION_MAX) {
@ -122,13 +126,20 @@ open class SourceManager(private val context: Context) {
}
val classLoader = PathClassLoader(ext.appInfo.sourceDir, null, context.classLoader)
return Class.forName(ext.sourceClass, false, classLoader).newInstance() as Source
return ext.sourceClasses.flatMap {
val obj = Class.forName(it, false, classLoader).newInstance()
when(obj) {
is Source -> listOf(obj)
is SourceFactory -> obj.createSources()
else -> throw Exception("Unknown source class type!")
}
}
}
class Extension(val name: String,
val appInfo: ApplicationInfo,
val version: String,
val sourceClass: String)
val sourceClasses: List<String>)
private companion object {
const val EXTENSION_FEATURE = "tachiyomi.extension"