From b7b83305b2b67dd8c19d447f28ea58d5d93aa339 Mon Sep 17 00:00:00 2001 From: Andy Bao Date: Thu, 27 Apr 2017 14:15:55 -0400 Subject: [PATCH] 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 --- .../kanade/tachiyomi/source/SourceFactory.kt | 12 ++++++ .../kanade/tachiyomi/source/SourceManager.kt | 37 ++++++++++++------- 2 files changed, 36 insertions(+), 13 deletions(-) create mode 100644 app/src/main/java/eu/kanade/tachiyomi/source/SourceFactory.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/SourceFactory.kt b/app/src/main/java/eu/kanade/tachiyomi/source/SourceFactory.kt new file mode 100644 index 000000000..d326c437a --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/source/SourceFactory.kt @@ -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 +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/SourceManager.kt b/app/src/main/java/eu/kanade/tachiyomi/source/SourceManager.kt index 925353e1c..0b31a27a3 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/SourceManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/SourceManager.kt @@ -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 { // 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) private companion object { const val EXTENSION_FEATURE = "tachiyomi.extension"