AquaStream/app/src/main/java/com/lagradost/cloudstream3/plugins/PluginManager.kt

105 lines
4.4 KiB
Kotlin
Raw Normal View History

2022-08-06 15:48:00 +00:00
package com.lagradost.cloudstream3.plugins
import android.content.Context
import dalvik.system.PathClassLoader
import com.google.gson.Gson
import com.lagradost.cloudstream3.plugins.PluginManager
import android.content.res.AssetManager
import android.content.res.Resources
import android.os.Environment
import java.io.File
import java.io.InputStreamReader
import java.util.*
object PluginManager {
private val PLUGINS_PATH =
Environment.getExternalStorageDirectory().absolutePath + "/Cloudstream3/plugins"
private val plugins: MutableMap<String, Plugin> =
LinkedHashMap<String, Plugin>()
private val classLoaders: MutableMap<PathClassLoader, Plugin> =
HashMap<PathClassLoader, Plugin>()
private val failedToLoad: MutableMap<File, Any> = LinkedHashMap()
var loadedPlugins = false
private val gson = Gson()
fun loadAllPlugins(context: Context) {
val dir = File(PLUGINS_PATH)
2022-08-04 10:51:11 +00:00
if (!dir.exists()) {
2022-08-06 15:48:00 +00:00
val res = dir.mkdirs()
2022-08-04 10:51:11 +00:00
if (!res) {
//logger.error("Failed to create directories!", null);
2022-08-06 15:48:00 +00:00
return
2022-08-04 10:51:11 +00:00
}
}
2022-08-06 15:48:00 +00:00
val sortedPlugins = dir.listFiles()
2022-08-04 10:51:11 +00:00
// Always sort plugins alphabetically for reproducible results
2022-08-06 15:48:00 +00:00
sortedPlugins?.sortedBy { it.name }?.forEach { file ->
val name = file.name
if (file.extension == "zip" || file.extension == "cs3") {
loadPlugin(context, file)
} else if (name != "oat") { // Some roms create this
if (file.isDirectory) {
// Utils.showToast(String.format("Found directory %s in your plugins folder. DO NOT EXTRACT PLUGIN ZIPS!", name), true);
} else if (name == "classes.dex" || name.endsWith(".json")) {
// Utils.showToast(String.format("Found extracted plugin file %s in your plugins folder. DO NOT EXTRACT PLUGIN ZIPS!", name), true);
2022-08-04 10:51:11 +00:00
}
2022-08-06 15:48:00 +00:00
// rmrf(f);
2022-08-04 10:51:11 +00:00
}
}
2022-08-06 15:48:00 +00:00
loadedPlugins = true
2022-08-04 10:51:11 +00:00
//if (!PluginManager.failedToLoad.isEmpty())
2022-08-06 15:48:00 +00:00
//Utils.showToast("Some plugins failed to load.");
2022-08-04 10:51:11 +00:00
}
2022-08-06 18:27:56 +00:00
fun loadPlugin(context: Context, file: File) {
2022-08-06 15:48:00 +00:00
val fileName = file.nameWithoutExtension
2022-08-04 10:51:11 +00:00
//logger.info("Loading plugin: " + fileName);
try {
2022-08-06 15:48:00 +00:00
val loader = PathClassLoader(file.absolutePath, context.classLoader)
var manifest: Plugin.Manifest
loader.getResourceAsStream("manifest.json").use { stream ->
2022-08-04 10:51:11 +00:00
if (stream == null) {
2022-08-06 15:48:00 +00:00
failedToLoad[file] = "No manifest found"
2022-08-04 10:51:11 +00:00
//logger.error("Failed to load plugin " + fileName + ": No manifest found", null);
2022-08-06 15:48:00 +00:00
return
2022-08-04 10:51:11 +00:00
}
2022-08-06 15:48:00 +00:00
InputStreamReader(stream).use { reader ->
manifest = gson.fromJson(
reader,
Plugin.Manifest::class.java
)
2022-08-04 10:51:11 +00:00
}
}
2022-08-06 15:48:00 +00:00
val name: String = manifest.name ?: "NO NAME"
val pluginClass: Class<*> =
loader.loadClass(manifest.pluginClassName) as Class<out Plugin?>
val pluginInstance: Plugin =
pluginClass.newInstance() as Plugin
2022-08-04 10:51:11 +00:00
if (plugins.containsKey(name)) {
//logger.error("Plugin with name " + name + " already exists", null);
2022-08-06 15:48:00 +00:00
return
2022-08-04 10:51:11 +00:00
}
2022-08-06 15:48:00 +00:00
pluginInstance.__filename = fileName
2022-08-04 10:51:11 +00:00
if (pluginInstance.needsResources) {
// based on https://stackoverflow.com/questions/7483568/dynamic-resource-loading-from-other-apk
2022-08-06 15:48:00 +00:00
val assets = AssetManager::class.java.newInstance()
val addAssetPath =
AssetManager::class.java.getMethod("addAssetPath", String::class.java)
addAssetPath.invoke(assets, file.absolutePath)
pluginInstance.resources = Resources(
assets,
context.resources.displayMetrics,
context.resources.configuration
)
2022-08-04 10:51:11 +00:00
}
2022-08-06 15:48:00 +00:00
plugins[name] = pluginInstance
classLoaders[loader] = pluginInstance
pluginInstance.load(context)
} catch (e: Throwable) {
failedToLoad[file] = e
e.printStackTrace()
2022-08-04 10:51:11 +00:00
//logger.error("Failed to load plugin " + fileName + ":\n", e);
}
}
}