forked from recloudstream/cloudstream
Converted Pluginmanager to kotlin
This commit is contained in:
parent
b208b4e9ae
commit
b42c0b905b
2 changed files with 88 additions and 91 deletions
|
@ -1,24 +1,24 @@
|
|||
package com.lagradost.cloudstream3.plugins;
|
||||
package com.lagradost.cloudstream3.plugins
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
|
||||
public abstract class Plugin {
|
||||
public Plugin() {}
|
||||
import android.content.Context
|
||||
import android.content.res.Resources
|
||||
import kotlin.Throws
|
||||
|
||||
abstract class Plugin {
|
||||
/**
|
||||
* Called when your Plugin is loaded
|
||||
* @param context Context
|
||||
*/
|
||||
public void load(Context context) throws Throwable {}
|
||||
|
||||
public static class Manifest {
|
||||
public String name;
|
||||
public String pluginClassName;
|
||||
@Throws(Throwable::class)
|
||||
open fun load(context: Context?) {
|
||||
}
|
||||
|
||||
public Resources resources;
|
||||
public boolean needsResources = false;
|
||||
class Manifest {
|
||||
var name: String? = null
|
||||
var pluginClassName: String? = null
|
||||
}
|
||||
|
||||
public String __filename;
|
||||
var resources: Resources? = null
|
||||
var needsResources = false
|
||||
var __filename: String? = null
|
||||
}
|
|
@ -1,108 +1,105 @@
|
|||
package com.lagradost.cloudstream3.plugins;
|
||||
package com.lagradost.cloudstream3.plugins
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.AssetManager;
|
||||
import android.content.res.Resources;
|
||||
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.*
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
import android.os.Environment;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
import dalvik.system.PathClassLoader;
|
||||
|
||||
|
||||
public class PluginManager {
|
||||
public static final String PLUGINS_PATH = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Cloudstream3/plugins";
|
||||
|
||||
public static final Map<String, Plugin> plugins = new LinkedHashMap<>();
|
||||
public static final Map<PathClassLoader, Plugin> classLoaders = new HashMap<>();
|
||||
public static final Map<File, Object> failedToLoad = new LinkedHashMap<>();
|
||||
|
||||
public static boolean loadedPlugins = false;
|
||||
|
||||
private static final Gson gson = new Gson();
|
||||
|
||||
public static void loadAllPlugins(Context context) {
|
||||
File dir = new File(PLUGINS_PATH);
|
||||
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) {
|
||||
println("LOAD PLUGINS")
|
||||
val dir = File(PLUGINS_PATH)
|
||||
if (!dir.exists()) {
|
||||
boolean res = dir.mkdirs();
|
||||
val res = dir.mkdirs()
|
||||
if (!res) {
|
||||
//logger.error("Failed to create directories!", null);
|
||||
return;
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
File[] sortedPlugins = dir.listFiles();
|
||||
val sortedPlugins = dir.listFiles()
|
||||
// Always sort plugins alphabetically for reproducible results
|
||||
Arrays.sort(sortedPlugins, Comparator.comparing(File::getName));
|
||||
|
||||
for (File f : sortedPlugins) {
|
||||
String name = f.getName();
|
||||
if (name.endsWith(".zip")) {
|
||||
PluginManager.loadPlugin(context, f);
|
||||
} else if (!name.equals("oat")) { // Some roms create this
|
||||
if (f.isDirectory()) {
|
||||
//Utils.showToast(String.format("Found directory %s in your plugins folder. DO NOT EXTRACT PLUGIN ZIPS!", name), true);
|
||||
} else if (name.equals("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);
|
||||
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);
|
||||
}
|
||||
//rmrf(f);
|
||||
// rmrf(f);
|
||||
}
|
||||
}
|
||||
loadedPlugins = true;
|
||||
|
||||
loadedPlugins = true
|
||||
//if (!PluginManager.failedToLoad.isEmpty())
|
||||
//Utils.showToast("Some plugins failed to load.");
|
||||
//Utils.showToast("Some plugins failed to load.");
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "JavaReflectionMemberAccess", "unchecked" })
|
||||
public static void loadPlugin(Context context, File file) {
|
||||
String fileName = file.getName().replace(".zip", "");
|
||||
private fun loadPlugin(context: Context, file: File) {
|
||||
val fileName = file.nameWithoutExtension
|
||||
//logger.info("Loading plugin: " + fileName);
|
||||
try {
|
||||
PathClassLoader loader = new PathClassLoader(file.getAbsolutePath(), context.getClassLoader());
|
||||
|
||||
Plugin.Manifest manifest;
|
||||
|
||||
try (InputStream stream = loader.getResourceAsStream("manifest.json")) {
|
||||
val loader = PathClassLoader(file.absolutePath, context.classLoader)
|
||||
var manifest: Plugin.Manifest
|
||||
loader.getResourceAsStream("manifest.json").use { stream ->
|
||||
if (stream == null) {
|
||||
failedToLoad.put(file, "No manifest found");
|
||||
failedToLoad[file] = "No manifest found"
|
||||
//logger.error("Failed to load plugin " + fileName + ": No manifest found", null);
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
try (InputStreamReader reader = new InputStreamReader(stream)) {
|
||||
manifest = gson.fromJson(reader, Plugin.Manifest.class);
|
||||
InputStreamReader(stream).use { reader ->
|
||||
manifest = gson.fromJson(
|
||||
reader,
|
||||
Plugin.Manifest::class.java
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
String name = manifest.name;
|
||||
|
||||
Class pluginClass = (Class<? extends Plugin>) loader.loadClass(manifest.pluginClassName);
|
||||
|
||||
Plugin pluginInstance = (Plugin)pluginClass.newInstance();
|
||||
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
|
||||
if (plugins.containsKey(name)) {
|
||||
//logger.error("Plugin with name " + name + " already exists", null);
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
pluginInstance.__filename = fileName;
|
||||
pluginInstance.__filename = fileName
|
||||
if (pluginInstance.needsResources) {
|
||||
// based on https://stackoverflow.com/questions/7483568/dynamic-resource-loading-from-other-apk
|
||||
AssetManager assets = AssetManager.class.newInstance();
|
||||
Method addAssetPath = AssetManager.class.getMethod("addAssetPath", String.class);
|
||||
addAssetPath.invoke(assets, file.getAbsolutePath());
|
||||
pluginInstance.resources = new Resources(assets, context.getResources().getDisplayMetrics(), context.getResources().getConfiguration());
|
||||
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
|
||||
)
|
||||
}
|
||||
plugins.put(name, pluginInstance);
|
||||
classLoaders.put(loader, pluginInstance);
|
||||
pluginInstance.load(context);
|
||||
} catch (Throwable e) {
|
||||
failedToLoad.put(file, e);
|
||||
plugins[name] = pluginInstance
|
||||
classLoaders[loader] = pluginInstance
|
||||
pluginInstance.load(context)
|
||||
} catch (e: Throwable) {
|
||||
failedToLoad[file] = e
|
||||
e.printStackTrace()
|
||||
//logger.error("Failed to load plugin " + fileName + ":\n", e);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue