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

时间:2014-10-21 13:11:37

标签: java android jar import external

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

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

要清楚,我不想在编译后将jar添加到主项目中。

编辑:我尝试过以下链接,似乎加载了我所说的类文件。但是我正在努力为动态加载的Class定义构造函数参数。

android-custom-class-loading-sample

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 ,类java.lang.String,类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();
}

3 个答案:

答案 0 :(得分:4)

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

  1. 使用dx工具转换文件
  2. 使用aapt cmd,将这些classes.dex添加到您的jar文件中。
  3. 现在这个包含dalvik格式文件的jar可以加载到我们的项目中。
  4. Here是一个解释完成它的程序的帖子。

答案 1 :(得分:1)

有实现这一目标的步骤。

  1. 您必须将JAR文件的副本复制到应用程序的私有内部存储中。

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

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

  2. This可以使用DexClassLoader动态加载JAR文件。

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

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

    请查看此链接以获取详细的代码和实施。

    How to load a jar file at runtime

    Android: How to dynamically load classes from a JAR fil E'

    希望这有帮助!!

答案 2 :(得分:0)

您应该尝试使用服务API - java.util.ServiceLoader

您可以在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,尽管我已经更改了包名称,使它们稍微不那么烦人了。