5

I need to have a jar file located in a main/assets directory within an Android project. It is important the jar file is located there.

With my main Android project is there a way to reference this jar file in my code and to use its classes?

To be clear I don't want to add the jar to the main project once compiled.

EDIT: I have tried the link below and it seems to load the Class file I've stated. But I'm strugging how to define constructor arguments for the dynamically loaded Class.

android-custom-class-loading-sample

EDIT2

Nearly there. I've confirmed the class is loaded from my classes.jar. I'm stuck instantiating it though.

On the licenseValidatorClazz.getConstructor line I get the error below. I'm guessing I'm missing something from my Interface file?

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();
        }

I have an Interface which contains the functions to pass to the loaded class.

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();
}
zeroprobe
  • 580
  • 1
  • 8
  • 19

3 Answers3

4

TO use an external jar to be associated with your application and use it during runtime, it needs to be in dalvik format since normal jars cannot work under dalvikVM.

  1. Convert your files using the dx tool
  2. using aapt cmd , add those classes.dex to your jar file.
  3. Now this jar which contains files in dalvik format can be loaded into our project.

Here is a post which explains the procedure to accomplish it.

Community
  • 1
  • 1
BDRSuite
  • 1,594
  • 1
  • 10
  • 15
  • Managed to use the DX tool. I think I would be OK with a simple class. But I'm trying to move part of the Android LVL library into a jar. Seems to be quite tricky. – zeroprobe Oct 21 '14 at 22:07
1

There are steps to accomplish this.

  1. You have to make a copy of your JAR file into the private internal storage of your aplication.

    1. Using the dx tool inside the android folder, you have to generate a classes.dex file associated with the JAR file. The dx tool will be at the location /android-sdks/build-tools/19.0.1 (this file is needed by the Dalvik VM, simply jar can not be read by the dalvik VM))

    2. Using the aapt tool command which is also inside the same location, you have to add the classes.dex to the JAR file.

This JAR file could be loaded dynamically using DexClassLoader.

If you are making a JAR from any one your own library, you have to do this steps (1-4) every time when there is a change in your library source code. So you can automate this steps by creating a shell script(in Mac/Linux/Ubuntu) or batch scripts(in Windows). You can refere this link to understand how to write shell scripts.

Note : One situation for implementing this method is, when it is impossible to add the JAR files directly to the build path of core project and need to be loaded dynamically at run time. In normal cases the JAR files could be added to the build path.

please check this link for the detailed code and implementation.

How to load a jar file at runtime

Android: How to dynamically load classes from a JAR file?

Hope this helps!!

Community
  • 1
  • 1
Blackhat002
  • 598
  • 4
  • 12
0

You should try out the Services API - java.util.ServiceLoader

You define a service interface and its implementations in your jar.

 package com.my.project;
 public interface MyService { ... }
 public class MyServiceBarImpl implements MyService { ... }
 public class MyServiceFooImpl implements MyService { ... }

Then you define the services contained within the jar file in the META-INF/services/ directory. For instance, in the file 'META-INF/services/com.my.project.MyService', you list the provider classes.

# Known MyService providers.
com.my.project.MyServiceBarImpl  # The original implementation for handling "bar"s.
com.my.project.MyServiceFooImpl  # A later implementation for "foo"s.

Then, in your main codebase, you can instantiate a MyService instance with the ServiceLoader:

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
}

These examples are taken more-or-less straight from the API, although I've changed the package names to make them slightly less annoying to read.

Steve K
  • 4,863
  • 2
  • 32
  • 41