1、写一个java类,生成Jar

2、初始Jar的转换

3、创建一个android工程

4、复制Jar

5、反射获取属性和方法

5、完整Demo

6、补充

 

 

摘要:在Android中可以动态加载,但无法像Java中那样方便动态加载jar

原因:Android的虚拟机(Dalvik VM)是不认识Java打出jarbyte code,需要通过dx工具来优化转换成Dalvik byte code才行。这一点在咱们Android项目打包的apk中可以看出:引入其他Jar的内容都被打包进了classes.dex。所以无法像javajar文件直接进行的反射。所以要用android sdk 自带的dx.bat (位于\adt-bundle-windows-x86-20131030\sdk\build-tools下)进行 jar-->dex-->jar的过程。

步骤说明:

  1. 1.写一个java类,生成Jar包

publicclass Hello{

publicstatic String Hello(Strings) {

         return s;

}

public String sayHello(){

         return"HelloWorld";

}

}

使用Fatjar工具进行对java类生成jar文件

原来Android还可以这样通过反射,获取jar包属性及方法_第1张图片

  1. 2.初始Jar的转换

对于assets目录下一般存放的是大文件,它在随apk打包时,并不会被压缩。我们可以将我们要

转化后的jar(经历过jar-->dex-->jar)放在该目录下。

以我们的多屏互动jar包为例:下面是完成jar-->dex-->jar的过程

命令:dx --dex --output = utils-r1204.jar  utils.jar


Output输出为一个名叫“utils-r1204.jar”的文件,名字可以随便起,把这个输出jar文件放到工程的assets目录下。

  1. 3.创建一个android工程

在activity中的oncreate方法中执行如下操作:

    protectedvoid onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_reflect);

        copyFileToInternalStorage ("utils-r1204.jar");

        jarToReflect();

}

  1. 4.复制Jar包

对输出的utils-r1204.jar进入复制到internal storage(就是data/data/当前工程/files目录下)中去,主要是为了方便反射,就好像我们的db文件通常也要经过这种方式到internal storage中,(另外如果有SD卡,可以直接把utils-r1204.jar拷贝到SD卡,方法是一样的)

public void copyFileToInternalStorage(final String filename) {

        InputStream is = null;

        FileOutputStream fos = null;

File file = new File(getApplicationContext().getFilesDir(), filename);

//getFileDir()目录就是data/data/当前工程/files 目录

if (file.exists()) {

System.out.println("file is exist! cannot to copy again");

} else {

try {

is = getAssets().open(filename);

fos = new FileOutputStream(file);

                   int len = 0;

byte[] buffer = new byte[1024];

while ((len = is.read(buffer)) != -1) {

                        fos.write(buffer, 0, len);

                   }

} catch (Exception e) {

                   e.printStackTrace();

} finally {

try {

is.close();

fos.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

  1. 5.反射获取属性和方法

@SuppressLint("NewApi")

publicvoid jarToReflect(){

         Stringspath=getFilesDir()+"/utils-r1204.jar";

         final File path = new File(spath);

          DexClassLoader dexloader = new DexClassLoader(

path.getAbsolutePath(),

getFilesDir().toString(),

null,

getClassLoader());

          Class<?> libClazz = null;

         try {

              // Load the libraryclass from the class loader.

              libClazz= dexloader.loadClass("com.example.demo.Hello");

              Methodsm=libClazz.getMethod("startHello", new Class[]{String.class});

              Stringsinvoke = (String) sm.invoke(libClazz, new Object[]{"aaaa"});

              System.out.println("sinvoke ="+sinvoke);

             

              Constructor[]constructors = libClazz.getDeclaredConstructors();

              AccessibleObject.setAccessible(constructors,true);

              for (Constructor con :constructors) {

                   if (con.isAccessible()){

                       ObjectclassObject = con.newInstance();

                   Methodnsm = libClazz.getMethod("sayHello");

                       Stringresult = (String) nsm.invoke(classObject);

                       System.out.println("nsminvoke =" +result);

                   }

              }

              Method[]methods = libClazz.getMethods();         

for (int i = 0; i length; i++) {

               methods[i].setAccessible(true);//if the method is private,it must be use setAccessible

               System.out.println(methods[i].getName());

              }

              Field[] fields = libClazz.getFields();

             for (int i = 0; i < fields.length; i++) {

             fields[i].setAccessible(true);//if the field is private,it must be use setAccessible

                 System.out.println(fields[i].getName());

             }

        } catch (Exception e) {

             e.printStackTrace();

        }

   }

执行结果如图: 

原来Android还可以这样通过反射,获取jar包属性及方法_第2张图片

6.完整Demo

package com.example.test.voice.bat;

 

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.lang.reflect.Field;

import java.lang.reflect.Method;

import dalvik.system.DexClassLoader;

import android.os.Bundle;

import android.annotation.SuppressLint;

import android.app.Activity;

 

publicclass ReflectActivity extends Activity {

     @Override

     protectedvoid onCreate(BundlesavedInstanceState) {

         super.onCreate(savedInstanceState);

         setContentView(R.layout.activity_reflect);

         copyFileToInternalStorage("utils-r1204.jar");

         jarToReflect();

     }

 

     publicvoidcopyFileToInternalStorage(final String filename) {

         InputStreamis = null;

         FileOutputStreamfos = null;

         Filefile = newFile(getApplicationContext().getFilesDir(), filename);

         if (file.exists()) {

              System.out.println("file is exist! cannot to copy again");

         }else {

              try {

                   is= getAssets().open(filename);

                   fos= newFileOutputStream(file);

                   int len = 0;

                   byte[] buffer = newbyte[1024];

                   while ((len =is.read(buffer)) != -1) {

                       fos.write(buffer,0, len);

                   }

              }catch (Exception e) {

                   e.printStackTrace();

              }finally {

                   try {

                       is.close();

                       fos.close();

                   }catch (IOException e) {

                       e.printStackTrace();

                   }

              }

         }

     }

    

     publicvoid jarToReflect(){

         Stringspath=getFilesDir()+"/utils-r1204.jar";

//if use SD

// final File path = newFile(Environment.getExternalStorageDirectory().toString()+"/test.jar");

         final File path = new File(spath);

         DexClassLoader dexloader = new DexClassLoader(

path.getAbsolutePath(),

getFilesDir().toString(),

null,

getClassLoader());

         Class<?> libClazz = null;

         try {

              // Load the library class from the class loader.

              libClazz= dexloader.loadClass("com.example.demo.Hello");

             

              Methodsm=libClazz.getMethod("startHello", new Class[]{String.class});

              Stringsinvoke = (String) sm.invoke(libClazz, new Object[]{"aaaa"});

              System.out.println("sinvoke ="+sinvoke);

 

              Constructor[]constructors = libClazz.getDeclaredConstructors();

              AccessibleObject.setAccessible(constructors,true);

              for (Constructor con :constructors) {

                   if (con.isAccessible()){

                       ObjectclassObject = con.newInstance();

                       Methodnsm = libClazz.getMethod("sayHello");

                       Stringresult = (String) nsm.invoke(classObject);

                       System.out.println("nsminvoke =" +result);

                   }

              }

                      

              Method[]methods = libClazz.getMethods();         

              for (int i = 0; i length; i++) {

                   methods[i].setAccessible(true);//if the method is private,it must be use setAccessible

                   System.out.println(methods[i].getName());

              }

              Field[] fields = libClazz.getFields();

              for (int i = 0; i length; i++) {

                   fields[i].setAccessible(true);//if the field is private,it must be use setAccessible

                   System.out.println(fields[i].getName());

              }

         }catch (Exception e) {

              e.printStackTrace();

         }

     }

}

7.补充:

1.不需要在本工程里面导出jar,自己新建一个Java工程导出来也行。

如果你觉得好,可以分享此公众号给你更多的人,原创不易。

------------华丽分割线--------------

长按二维码,关注公众号原来Android还可以这样通过反射,获取jar包属性及方法_第3张图片

更多相关文章

  1. android的intent使用方法
  2. Android中集成第三方库的方法和问题
  3. 在Android设备上搭建Web服务器的方法
  4. Android setTag方法的key问题
  5. Android RSA与Java RSA加密不同标准产生问题的解决方法
  6. Android sdk manager不能更新下载缓慢的解决方法
  7. android截屏代码实现方法

随机推荐

  1. Android(安卓)代码获取手机屏幕分辨率的
  2. 全局窗口二
  3. 坚向的ViewPager,上下滑动的组件,android上
  4. Using cygwin with the Android(安卓)NDK
  5. andorid webview
  6. Android(安卓)APK反编译详解(附图)
  7. Android拍照
  8. Android两种计步器sensor
  9. Android点击通知栏返回正在运行的Activit
  10. Android与(Servlet)服务器交互