0
ServiceLoader
을 Android 시스템에 통합하여 플러그인 시스템을 통합하는 데 문제가 있습니다. externalStorage에 자산 폴더에서 복사Android의 ServiceLoader "클래스를 인스턴스화 할 수 없습니다"
public class StrategieClassLoader extends URLClassLoader {
private ClassLoader m_SystemClassLoader;
private static Set<String> m_SaveClasses = new HashSet<String>();
{
m_SaveClasses.add(ESpielsteinFarbe.class.getName());
m_SaveClasses.add(ISpielstein.class.getName());
m_SaveClasses.add(SpielsteinPosition.class.getName());
m_SaveClasses.add(ISpielzug.class.getName());
m_SaveClasses.add(IStrategie.class.getName());
m_SaveClasses.add(IStrategieFactory.class.getName());
m_SaveClasses.add(StrategieException.class.getName());
}
public StrategieClassLoader(URL[] p_Classpath, ClassLoader p_Parent) {
super(p_Classpath, p_Parent);
m_SystemClassLoader = getSystemClassLoader();
}
@Override
protected synchronized Class<?> loadClass(String p_ClassName, boolean p_Resolve)
throws ClassNotFoundException {
Class<?> l_Class = findLoadedClass(p_ClassName);
if (l_Class == null) {
if (isSystemClass(p_ClassName)) {
l_Class = super.loadClass(p_ClassName, p_Resolve);
} else {
try {
l_Class = findClass(p_ClassName);
} catch (ClassNotFoundException e) {
l_Class = super.loadClass(p_ClassName, p_Resolve);
}
}
}
if (p_Resolve) {
resolveClass(l_Class);
}
return l_Class;
}
private boolean isSystemClass(String p_ClassName) {
return (m_SaveClasses.contains(p_ClassName) || p_ClassName.startsWith("java.") || p_ClassName.startsWith("javax.") ||
p_ClassName.startsWith("com.sun."));
}
@Override
public URL getResource(String p_ResourceName) {
URL l_ResourceUrl = findResource(p_ResourceName);
if (l_ResourceUrl == null) {
l_ResourceUrl = super.getResource(p_ResourceName);
}
return l_ResourceUrl;
}
@Override
public Enumeration<URL> getResources(String p_ResourceName) throws IOException {
Enumeration<URL> l_LocalUrls = findResources(p_ResourceName);
Enumeration<URL> l_ParentUrls = null;
if (getParent() != null) {
l_ParentUrls = getParent().getResources(p_ResourceName);
}
final List<URL> l_Urls = new ArrayList<URL>();
if (l_LocalUrls != null) {
while (l_LocalUrls.hasMoreElements()) {
l_Urls.add(l_LocalUrls.nextElement());
}
}
if (l_ParentUrls != null) {
while (l_ParentUrls.hasMoreElements()) {
l_Urls.add(l_ParentUrls.nextElement());
}
}
return new Enumeration<URL>() {
Iterator<URL> l_UrlIterator = l_Urls.iterator();
public boolean hasMoreElements() {
return l_UrlIterator.hasNext();
}
public URL nextElement() {
return l_UrlIterator.next();
}
};
}
@Override
public InputStream getResourceAsStream(String p_ResourceName) {
URL l_ResourceUrl = getResource(p_ResourceName);
try {
return l_ResourceUrl != null ? l_ResourceUrl.openStream() : null;
} catch (IOException e) {
}
return null;
}
}
public static List<IStrategieFactory> load(String p_path)
{
List<IStrategieFactory> l_Facs = new ArrayList<IStrategieFactory>();
File l_PluginDir = new File(p_path);
for(File dir: l_PluginDir.listFiles())
{
if(dir.isDirectory())
{
File[] l_Jars = dir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File file, String name) {
// TODO Auto-generated method stub
return name.endsWith(".jar");
}
});
List<URL> l_Urls = new ArrayList<URL>();
for(File jar: l_Jars)
{
try {
l_Urls.add(jar.toURI().toURL());
} catch (MalformedURLException ex) {
ex.printStackTrace();
}
}
if(!l_Urls.isEmpty())
{
StrategieClassLoader l_ClassLoader = new StrategieClassLoader(l_Urls.toArray(new URL[ l_Urls.size() ]), Thread.currentThread().getContextClassLoader());
ServiceLoader<IStrategieFactory> loader = ServiceLoader.load(IStrategieFactory.class, l_ClassLoader);
for(IStrategieFactory fac : loader)
{
l_Facs.add(fac);
}
}
}
}
m_Factories = l_Facs;
return m_Factories;
}
}
jar 파일, 클래스는 모든 파일에 액세스 할 수 있지만 실행 후 충돌의
ServiceLoader<IStrategieFactory> loader = ServiceLoader.load(IStrategieFactory.class, l_ClassLoader);
13967-13967/dievierlustigen5.dhbw.de.a4wins E/AndroidRuntime: FATAL EXCEPTION: main
Process: dievierlustigen5.dhbw.de.a4wins, PID: 13967
java.util.ServiceConfigurationError: Couldn't instantiate class de.dhbw.fourwins.strategy.EasyStratFactory
at java.util.ServiceLoader$ServiceIterator.next(ServiceLoader.java:216)
at dievierlustigen5.dhbw.de.a4wins.strategy.StrategyLoader.load(StrategyLoader.java:78)
at dievierlustigen5.dhbw.de.a4wins.DifficultyActivity.onCreate(DifficultyActivity.java:43)
at android.app.Activity.performCreate(Activity.java:6877)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1136)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3208)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3351)
at android.app.ActivityThread.access$1100(ActivityThread.java:222)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1796)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7230)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.net.URL.getProtocol()' on a null object reference
at java.net.URLClassLoader.getPermissions(URLClassLoader.java:614)
at java.security.SecureClassLoader.getPD(SecureClassLoader.java:140)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:93)
at java.net.URLClassLoader.access$600(URLClassLoader.java:55)
at java.net.URLClassLoader$URLJarHandler.createClass(URLClassLoader.java:364)
at java.net.URLClassLoader$URLJarHandler.findClass(URLClassLoader.java:303)
at java.net.URLClassLoader.findClass(URLClassLoader.java:748)
at dievierlustigen5.dhbw.de.a4wins.strategy.StrategieClassLoader.loadClass(StrategieClassLoader.java:56)
at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
at java.util.ServiceLoader$ServiceIterator.next(ServiceLoader.java:214)
at dievierlustigen5.dhbw.de.a4wins.strategy.StrategyLoader.load(StrategyLoader.java:78)
at dievierlustigen5.dhbw.de.a4wins.DifficultyActivity.onCreate(DifficultyActivity.java:43)
at android.app.Activity.performCreate(Activity.java:6877)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1136)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3208)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3351)
at android.app.ActivityThread.access$1100(ActivityThread.java:222)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1796)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7230)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
어쩌면 사람이 오류를 해결하는 방법을 알아?
'ServiceLoader'를 사용하는 것이 안드로이드에 좋은 계획이라는 것에 회의적입니다. 즉, [이 개발자가 작동했습니다] (http://francistoth.github.io/blog/jekyll/update/2015/07/10/coding-an-android-dynamic-class-loader.html). – CommonsWare
매니페스트에 허가를 받았습니까? –
@ibtehaz 정확히 어떤 허가? WRITE_EXTERNAL_STORAGE 및 WRITE_INTERNAL_STORAGE를 나타냅니다. 매니페스트에 모두 설정되어 있습니다. 내가 .jar 파일을 assetfolder에서 외부 저장소 – IPrototypeI