原来Android还可以这样通过反射,获取jar包属性及方法
1、写一个java类,生成Jar包
2、初始Jar的转换
3、创建一个android工程
4、复制Jar包
5、反射获取属性和方法
5、完整Demo
6、补充
摘要:在Android中可以动态加载,但无法像Java中那样方便动态加载jar
原因:Android的虚拟机(Dalvik VM)是不认识Java打出jar的byte code,需要通过dx工具来优化转换成Dalvik byte code才行。这一点在咱们Android项目打包的apk中可以看出:引入其他Jar的内容都被打包进了classes.dex。所以无法像java对jar文件直接进行的反射。所以要用android sdk 自带的dx.bat (位于\adt-bundle-windows-x86-20131030\sdk\build-tools下)进行 jar-->dex-->jar的过程。
步骤说明:
1.写一个java类,生成Jar包
publicclass Hello{
publicstatic String Hello(Strings) {
return s;
}
public String sayHello(){
return"HelloWorld";
}
}
使用Fatjar工具进行对java类生成jar文件
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目录下。
3.创建一个android工程
在activity中的oncreate方法中执行如下操作:
protectedvoid onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_reflect);
copyFileToInternalStorage ("utils-r1204.jar");
jarToReflect();
}
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();
}
}
}
}
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 <methods.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();
}
}
执行结果如图:
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 <methods.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();
}
}
}
7.补充:
1.不需要在本工程里面导出jar,自己新建一个Java工程导出来也行。
如果你觉得好,可以分享此公众号给你更多的人,原创不易。
------------华丽分割线--------------
长按二维码,关注公众号
原来Android还可以这样通过反射,获取jar包属性及方法相关推荐
- 使用反射获得jar包中的类、方法、参数、返回值类型,然后动态加载jar包运行方法
其实我的需求是在系统中 测试用户导入的jar包,所有网上找了很多解决方案,踩过很多坑,再加上以前搞c++的,对java不是很熟, 这里特意记录下,算是基本满足需求了 使用反射获得jar包中的类.方法. ...
- 【Android 插件化】Hook 插件化框架 ( 通过反射获取 “插件包“ 中的 Element[] dexElements )
Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...
- 在swt中获取jar包中的文件 uri is not hierarchical
uri is not hierarchical 学习了:http://blog.csdn.net/zdsdiablo/article/details/1519719 在swt中获取jar包中的文件: ...
- 获取jar包内部的资源文件
通常获取一个资源文件很简单,问题是对于jar包内的资源文件,可能会发生意外.假如这里有一个文件操作的类: public class FileLoader {public boolean exists( ...
- android jar 加入图片,Android动态加载外部jar包及jar包中图片等资源文件
Android动态加载外部jar包及jar包中图片等资源文件 Android应用程序由Java开发,因此Java中许多实用的特性,在Android中也有体现.动态加载Class,也就是外部jar包,在 ...
- 关于如何正确地在android项目中添加第三方jar包
在android项目中添加第三方jar包虽然不是一个很复杂的问题,但是确实给很多开发者带来了不小的困扰.我自己就曾经碰到过calss not found exception ...
- 获取jar包中的文件,及遍历jar包中的文件
获取jar包中的文件 ClassPathResource resource1 = new ClassPathResource("文件夹" + File.separator + &q ...
- Android利用Java反射获取用户手机的rom定制系统及版本,EMUI,MIUI,ColorOS,FunthouchOS等
Android利用Java反射获取用户手机的rom定制系统版本及版本号,EMUI,MIUI,ColorOS,FunthouchOS等 前言 正文 结语 前言 现在手机厂商都推出了自己的基于Androi ...
- java获取jar包中的文件资源
java获取jar包中的文件资源 一.问题示例 1.1 项目开发时 1.2 打包成jar后 二.解决方案 2.1 解决方法 2.2 实现 问题描述: 我们常常在代码中读取一些资源文件(比如图片,音 ...
- Java 覆盖 jar 包内的方法
背景 有时候在 java 开发过程中会遇到这样的场景,比如说我们需要用 jar 包里的方法,但是 jar 包里的方法又不能满足当前的业务逻辑需要,而想直接下载 jar 包源码修改的话又会很麻烦,这个时 ...
最新文章
- 知识点2-对二进制的运用
- 如何在SQL Server 2005中使用作业实现备份和特定删除
- Halcon资料:image,region,xld三者如何转化和保存
- on java 8 学习笔记 2022.2.16
- Courses hdu 1083(匹配)
- ocp linux 基础要点
- 15个著名的设计心理学原理以及在设计中的应用
- 15万个监控摄像头被黑,医院、学校、监狱都被看得一清二楚
- Xcode里-ObjC, -all_load, -force_load
- 网页版本的飞行日志分析平台是_一个轻便的实时日志收集平台wslog
- LeetCode Online Judge 题目C# 练习 - Search in Rotated Sorted Array II
- 如何更换清华源_树莓派中国软件源
- Qt 未找到文件:NMAKE
- js如何获取IP地址?教你4种方法
- 胡润:马云捐1000亿仍是中国首富,中国10亿美元俱乐部比美国多400人
- html实心向右三角形,css 如何在html页面上输出一个左三角形或右三角形呢?
- Population and carrying capacity 的第四个阶段:Negative feedback with delay. Overshoot and oscillation
- 【山无遮,海无拦】LeetCode题集 线性枚举之最值算法
- 几款有意思的html游戏推荐(在线云玩+源码)
- 编写程序,用户输入日期,计算该日期是这一年的第几天