2016-10-01 10 views
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)  

어쩌면 사람이 오류를 해결하는 방법을 알아?

+0

'ServiceLoader'를 사용하는 것이 안드로이드에 좋은 계획이라는 것에 회의적입니다. 즉, [이 개발자가 작동했습니다] (http://francistoth.github.io/blog/jekyll/update/2015/07/10/coding-an-android-dynamic-class-loader.html). – CommonsWare

+0

매니페스트에 허가를 받았습니까? –

+0

@ibtehaz 정확히 어떤 허가? WRITE_EXTERNAL_STORAGE 및 WRITE_INTERNAL_STORAGE를 나타냅니다. 매니페스트에 모두 설정되어 있습니다. 내가 .jar 파일을 assetfolder에서 외부 저장소 – IPrototypeI

답변

0

Android는 .dex 파일 만 읽을 수있는 다른 VM을 사용하기 때문에 Android 런타임을 사용하면 일반 .class 파일을로드 할 수 없습니다.

그래서 DexClassLoader를 사용해야합니다.