Java 如何将jar文件保持在外部,但仍在我的Android项目中使用它的类?

Java 如何将jar文件保持在外部,但仍在我的Android项目中使用它的类?,java,android,jar,import,external,Java,Android,Jar,Import,External,我需要在Android项目的main/assets目录中有一个jar文件。jar文件位于那里是很重要的 在我的主要Android项目中,有没有办法在我的代码中引用这个jar文件并使用它的类 明确地说,我不想在编译之后将jar添加到主项目中 编辑:我尝试了下面的链接,它似乎加载了我所说的类文件。但我正在研究如何为动态加载的类定义构造函数参数 EDIT2 快到了。我已经确认该类是从我的classes.jar加载的。不过,我被困在实例化它的过程中 在licenseValidatorClazz.get

我需要在Android项目的main/assets目录中有一个jar文件。jar文件位于那里是很重要的

在我的主要Android项目中,有没有办法在我的代码中引用这个jar文件并使用它的类

明确地说,我不想在编译之后将jar添加到主项目中

编辑:我尝试了下面的链接,它似乎加载了我所说的类文件。但我正在研究如何为动态加载的类定义构造函数参数

EDIT2

快到了。我已经确认该类是从我的classes.jar加载的。不过,我被困在实例化它的过程中

在licenseValidatorClazz.getConstructor行中,我得到以下错误。我猜我的接口文件中遗漏了什么

java.lang.NoSuchMethodException:[interface com.google.android.vending.licensing.Policy,interface com.google.android.vending.licensing.DeviceLimiter,interface com.google.android.vending.licensing.LicenseCheckerCallback,int,class java.lang.String,class java.lang.String]

    public Class licenseValidatorClazz = null;
    public LicenseValidator validator;

    ...

    // Initialize the class loader with the secondary dex file.
    DexClassLoader cl = new DexClassLoader(dexInternalStoragePath.getAbsolutePath(),
    optimizedDexOutputPath.getAbsolutePath(),
    null,
    mContext.getClassLoader());

        try {
            // Load the library class from the class loader.
            licenseValidatorClazz = cl.loadClass("com.google.android.vending.licensing.LicenseValidator");

            validator = (LicenseValidator) licenseValidatorClazz.getConstructor(Policy.class,DeviceLimiter.class,LicenseCheckerCallback.class,int.class,String.class,String.class).newInstance(ddd, new NullDeviceLimiter(),
                    callback, generateNonce(), mPackageName, mVersionCode);

        } catch (Exception exception) {
            // Handle exception gracefully here.
            exception.printStackTrace();
        }
我有一个接口,其中包含传递给加载类的函数

public interface LicenseValidator
{
    public LicenseCheckerCallback getCallback();
    public int getNonce();
    public String getPackageName();
    public void verify(PublicKey publicKey, int responseCode, String signedData, String signature);
    public void handleResponse(int response, ResponseData rawData);
    public void handleApplicationError(int code);
    public void handleInvalidResponse();
}

要使用与应用程序关联的外部jar并在运行时使用它,它需要采用dalvik格式,因为普通jar不能在dalvikVM下工作

  • 使用dx工具转换文件
  • 使用aapt cmd,将那些classes.dex添加到jar文件中
  • 现在这个包含dalvik格式文件的jar可以加载到我们的项目中

  • 这篇文章解释了实现它的过程。

    您应该尝试一下服务API-

    您可以在jar中定义服务接口及其实现

     package com.my.project;
     public interface MyService { ... }
     public class MyServiceBarImpl implements MyService { ... }
     public class MyServiceFooImpl implements MyService { ... }
    
    然后在META-INF/services/目录中定义jar文件中包含的服务。例如,在文件“META-INF/services/com.my.project.MyService”中,您列出了提供者类

    # Known MyService providers.
    com.my.project.MyServiceBarImpl  # The original implementation for handling "bar"s.
    com.my.project.MyServiceFooImpl  # A later implementation for "foo"s.
    
    然后,在主代码库中,可以使用ServiceLoader实例化MyService实例:

    for (MyService service : ServiceLoader.load(MyService.class)) {
        //Perform some test to determine which is the right MyServiceImpl
        //and then do something with the MyService instance
    }
    

    这些示例或多或少都是直接从API中获取的,不过我已经更改了包名,使它们稍微不那么烦人。

    有一些步骤可以实现这一点

  • 您必须将JAR文件复制到应用程序的私有内部存储器中

  • 使用android文件夹中的dx工具,您必须生成一个与JAR文件关联的classes.dex文件。dx工具将位于/android sdks/build tools/19.0.1(Dalvik VM需要此文件,只是Dalvik VM无法读取jar))

  • 使用同样位于同一位置的aapt工具命令,您必须将classes.dex添加到JAR文件中

  • 可以使用DexClassLoader动态加载JAR文件

    如果您要从您自己的库中的任何一个创建一个JAR,那么每次库源代码发生更改时都必须执行此步骤(1-4)。因此,您可以通过创建shell脚本(在Mac/Linux/Ubuntu中)或批处理脚本(在Windows中)来自动化这些步骤。您可以参考此链接了解如何编写shell脚本

    注意:实现此方法的一种情况是,无法将JAR文件直接添加到核心项目的构建路径,并且需要在运行时动态加载。在正常情况下,可以将JAR文件添加到构建路径中

    有关详细代码和实现,请查看此链接

    e


    希望这有帮助

    你使用的是哪种构建工具?我使用的是Android Studio。我设法使用了DX工具。我想我可以上一节简单的课。但我正试图将Android LVL库的一部分移动到一个罐子中。看起来很棘手。