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