I am trying to use reflection instead of including a jar file. I want to do this to reduce my apk size when I am not using the jar code...but if I include the code, I must include the jar. That being said, I am trying to grasp reflection and not doing well.
I have this code to see the methods available (and it works):
//initialize method params
Class[] paramInitialize = new Class[2];
paramInitialize[0] = Activity.class;
paramInitialize[1] = String.class;
try {
Logger.i(DEBUG_TAG, "try statement");
Class <?> tremorVideoCls = Class.forName("com.tremorvideo.sdk.android.videoad.TremorVideo");
Class <?> tremorSettingsCls = Class.forName("com.tremorvideo.sdk.android.videoad.Settings");
Object object = tremorVideoCls.newInstance();
String apkName = this.getPackageManager().getApplicationInfo(this.getPackageName(), 0).sourceDir;
loader = new dalvik.system.PathClassLoader(apkName, ClassLoader.getSystemClassLoader());
tremorVideoCls = loader.loadClass("com.tremorvideo.sdk.android.videoad.TremorVideo");
Method m[] = tremorVideoCls.getMethods();
Method declaredM[] = tremorVideoCls.getDeclaredMethods();
for (int i = 0; i < m.length; i++) {
Logger.i(DEBUG_TAG, "getMethods is " + m[i].toString());
}
Field []field = tremorSettingsCls.getFields();
for (int i = 0; i < field.length; i++) {
Logger.i(DEBUG_TAG, "getFields is " + field[i].toString());
}
Method tremorInitialize = tremorVideoCls.getMethod("initialize", paramInitialize);
Logger.i(DEBUG_TAG, "tremorInitialize is " + tremorInitialize.toGenericString());
// tremorInitialize.invoke(object, this, ACCUWX.TREMOR_ADSPACE_TEST);
} catch (ClassNotFoundException e) {
} catch (NoSuchMethodException x) {
...
BUT, I get a logcat error throwing an exception:
08-06 11:48:51.134: W/System.err(11688): java.lang.NoSuchMethodException: initialize [class android.app.Activity, class java.lang.String]
Here is the logcat printing out that method:
08-06 11:48:51.118: I/Flagship/MainActivity(11688): getMethods is public static void com.tremorvideo.sdk.android.videoad.TremorVideo.initialize(android.content.Context,java.lang.String)
I'm not sure what do try next...any help greatly appreciated.
If the method which you are trying to invoke is
public static void com.tremorvideo.sdk.android.videoad.TremorVideo.initialize(android.content.Context,java.lang.String)
and the error is
08-06 11:48:51.134: W/System.err(11688): java.lang.NoSuchMethodException: initialize [class android.app.Activity, class java.lang.String]
It clearly indicates that the method expects android.content.Context but what you are passing android.app.Activity
In the call
tremorInitialize.invoke(object, this, ACCUWX.TREMOR_ADSPACE_TEST);
instead of passing this you should pass an instance of android.content.Context.
Hope this helps!!!
The issue is not the invocation of the method but the call to retreiving the method.
Because the Class[] is initialized with Activity.class, a method with the signature
void initialize(Activity activity, String string) is searched for.
This method doesn't exist.
So it should be
paramInitialize[0] = Context.class;
to find the method
initialize(Contex ctxt, String arg).
Related
I've tried using a variable to invoke a java method, using method.invoke(), as suggested in this example. But it seems there should be an object or something as a parameter in method.invoke(). I've tried using null, but the method didn't get invoked. My code is as follows:
String ACTION = "cart";
Method method = SolverService.class.getDeclaredMethod("Method" + ACTION);
method.invoke(null);
I've got a method as:
public void Methodcart(){
Toast.makeText(this,"Method called",Toast.LENGTH_LONG).show();
}
PS: I HAVE TO make this method.invoke() work. Otherwise, I need to write a very long list of switch-case statements.I've gone through the documentation but couldn't understand much about the object instance i might need to use here as I'm new to android app developing.
You can try something similar to the code shown below (Java Reflection) -
Suppose I have a class ClassWithMethods.java with the methods I want to invoke in some other class as shown below -
public class ClassWithMethods {
private int counter;
public void printIt(){
System.out.println("printIt() no param");
}
public void printItString(String temp){
System.out.println("printIt() with param String : " + temp);
}
}
Now I also have another class TestApp.java which will invoke methods of the ClassWithMethods class at runtime using Java Reflection -
public class TestApp {
public static void main(String[] args) {
//no paramater
Class noparams[] = {};
//String parameter
Class[] paramString = new Class[1];
paramString[0] = String.class;
//int parameter
Class[] paramInt = new Class[1];
paramInt[0] = Integer.TYPE;
try{
//load the ClassWithMethods at runtime
Class cls = Class.forName("com.myapps.ClassWithMethods");
Object obj = cls.newInstance();
//call the printIt method
Method method = cls.getDeclaredMethod("printIt", noparams);
method.invoke(obj, null);
//call the printItString method, pass a String param
method = cls.getDeclaredMethod("printItString", paramString);
method.invoke(obj, new String("someString"));
}catch(Exception ex){
ex.printStackTrace();
}
}
I am using Java Reflection in my current project (since you mentioned you are using Android Studio) to get Battery Capacity of device from PowerProfile class which is internal to the Android OS.
public double getBatteryCapacity() {
Object mPowerProfile = null;
try {
mPowerProfile = Class.forName("com.android.internal.os.PowerProfile")
.getConstructor(Context.class)
.newInstance(getContext());
} catch (Exception e) {
e.printStackTrace();
}
try {
// get access to method named "getAveragePower()" in the class "PowerProfile"
Method getAveragePower = Class.forName("com.android.internal.os.PowerProfile").getMethod("getAveragePower", String.class);
//Get total battery capacity in mAh.
double batteryCapacity = (Double) getAveragePower.invoke(mPowerProfile, "battery.capacity");
return batteryCapacity;
} catch (Exception e) {
e.printStackTrace();
}
return 0.0;
}
Here is a screenshot of how the actual method structure looks like in the PowerProfile class -
I am trying to write a test case for checkRegistry method, which is a private method, I am using PowerMock-EasyMock-Juint to realize this.
Now to test this methods I want to suppress the calls to super calls methods
eg:
intigration = super.getParam("integritycheck");
I dont want the call to go to superClass method, but at the same time I want the variable integration to be set. How do I realize this?
The difficulty is
super.getParam("integritycheck"); and
sTmpOverride = super.getParam("RESPONSE_OVERRIDE"); will return different results.
Method that I am trying to write unit test.
private String checkRegistry()
{
String intigration = "";
String sresponse = "";
try
{
try
{
intigration = super.getParam("integritycheck");
sresponse = CustomImpl.getParam("responseWrite");
**Some Business Logic**
sTmpOverride = super.getParam("RESPONSE_OVERRIDE");
if (sTmpOverride == null) {
this._bRespOverride = true;
} else {
this._bRespOverride = sTmpOverride.trim().equalsIgnoreCase(
"true");
}
sTmpOverride = super.getParam("ERROR_OVERRIDE");
if (sTmpOverride == null) {
this._bErrOverride = true;
} else {
this._bErrOverride = sTmpOverride.trim().equalsIgnoreCase(
"true");
}
**Some Business Logic**
Logging.info("integritycheck : " + intigration );
Logging.info("responseWrite : " + sresponse );
super.track("Error Directory : " + sErrorPath);
}
}
catch (Exception ex)
{
_result= false;
}
return _result;
}
I am struck on using the below method
suppress(method(CustomRegisterChecker.class, "getParam"));
where CustomRegisterChecker.class is the super class.
UPDATE1:
//Here I am creating a mock for the super class
CustomRegisterChecker customRegisterMock=createMock(AbstractListener.class);
//I am supresssing the calls made to the super class and giving my own response
expect(abstractListenerMock.getParam("integritycheck ")).andReturn(null);
expect(abstractListenerMock.getParam("responseWrite")).andReturn(null);
But How do I invoke and test the method. I tried using Reflection API. BUT that does not work. it just simply run the program, supressing the super class methods does not happen here.
I am new to Java reflection. I tried to call one method of my DAO Class using reflection, and I got the below mentioned error of illegal argument exception. Below is my code. My method contains two arguments: one is Dossier bean object and another is sessionfactory object. I got this error when I invoke my method. I searched lot on net but did not find the proper solution.
public String getDossierDetail(HttpSession session,DoerDAO doerDao,SessionFactory sessionFactory,String requestedUser) throws ClassNotFoundException{
log.info("(getDossierDetail)Execution starts");
ReviewerOne reviewer = new ReviewerOne();
String message = "";
DoerDAO doerDaoInt = new DoerDAO();
try{
List<Dossier> dossierDetail = (List<Dossier>) session.getAttribute(ObjectConstant.dossierDetailBean);
System.out.println("dossierDetail: "+dossierDetail.size()+"product nm: "+dossierDetail.get(0).getProductName()+"requested User: "+requestedUser);
Method method = DoerDAO.class.getDeclaredMethod(requestedUser,Dossier.class,SessionFactory.class);
method.invoke(dossierDetail.get(0), sessionFactory);
}catch(Exception e){
e.printStackTrace();
log.error("(getDossierDetail)Error is: ",e);
message = e.getLocalizedMessage();
}
return message;
}
my requestedUser value is :: getReviewerOneDetail.
/** DoerDao method ********/
public void getReviewerOneDetail(Dossier dossierBean,SessionFactory sessionFactory){
log.info("(getReviewerOneDetail)Execution starts.");
try{
System.out.println("in reviewer one detail....");
}catch(Exception e){
e.printStackTrace();
log.error("(getReviewerOneDetail)Error is: ",e);
}
}
Short version: You are missing the first argument in your call to invoke.
Long version: You are calling
Method method = DoerDAO.class.getDeclaredMethod(requestedUser,
Dossier.class,
SessionFactory.class);
Let's say that the value of requestedUser is getReviewerOneDetail, then you'd look up the method
getReviewerOneDetail(Dossier arg0, SessionFactory arg1)
Next you call
method.invoke(dossierDetail.get(0), sessionFactory);
The JavaDoc states that invoke gets as first parameter the instance(!) of the class to call the method on and as second, third, ... parameters the actual parameters for your invocation.
So, what you actually trying to call in your code, is
dossierDetail.get(0).getReviewerOneDetail(sessionFactory);
which does neither match the method signature (1 parameter vs. 2 parameters), nor the instance type on which the method is called (Dossier instead of DoerDAO).
Because you acquire the Method from the DoerDAO class, I guess what you intended to write there, was actually:
method.invoke(doerDao, dossierDetail.get(0), sessionFactory);
This would translate to
doerDao.getReviewerOneDetail(dossierDetail.get(0), sessionFactory);
I'm trying to dynamically add Jar's to my programs classpath at run time using THIS method i found since it seems like it worked for a lot of people. When using addPlugin() it throws a NoSuchMethodException (commented in the code below).
Can someone please tell me what I'm missing in order to get this working? I'm not too familiar with this and I've tried looking it up before.
public final class PluginLoader {
private static final Class[] _PARAMS = new Class[] {URL.class};
public static void addPlugin(File plugin) throws PluginException {
URLClassLoader plLoader = (URLClassLoader)ClassLoader.getSystemClassLoader();
Class plClass = URLClassLoader.class;
try {
Method m = plClass.getDeclaredMethod("addPlugin", _PARAMS); //ERROR HERE
m.setAccessible(true);
m.invoke(plLoader, new Object[] {plugin.toURI().toURL()});
} catch (Exception ex) {
ex.printStackTrace();
throw new PluginException("ERROR: Could not add plugin '" + plugin.getName() + "' to System ClassLoader");
}
}
}
Usage:
PluginLoader.addPlugin(new File("../path/to/jar.jar"));
Constructor<?> cs = ClassLoader.getSystemClassLoader().loadClass("my.main.class.Main").getConstructor(String.class);
Change:
Method m = plClass.getDeclaredMethod("addPlugin", _PARAMS);
to:
Method m = plClass.getDeclaredMethod("addURL", _PARAMS);
in my application the follwoing code is used. Can some one give a detailed explanation for the code that is highlighted?
I understood that in first highlighted block java reflection is used in invoking the method handle_validation..but need the detailed explanation.
Then in second highlighted block RemoteException is thrown..
My exact question is why they used reflection to call EngineHandlerIF and then why they are using RMI in this EngineHandlerIF to invoke the definition of method in EngineHandler?
private static EngineHandlerIF init() {
ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[] { "validation.xml" });
String[] beans = ctx.getBeanDefinitionNames();
for (String string : beans) {
logger.info(string);
}
EngineHandlerIF engine = (EngineHandlerIF) ctx.getBean("engine");
return engine;
}
private Object callEngineMethod(MiddlewareMessage mmsg) {
Object resultObj;
try {
**String methodName = "handle_validation";
Method method = EngineHandlerIF.class.getDeclaredMethod(methodName, MiddlewareMessage.class);
method.setAccessible(true);
resultObj = method.invoke(engine, new Object[] { mmsg });**
} catch (Exception e) {
logger.error("sendMessage Exception: ", e);
return new Boolean(false);
}
return resultObj;
}
EngineHandlerIF:
----------------
**public abstract String handle_validation(MiddlewareMessage mmsg) throws RemoteException;**
EngineHandler:
--------------
public String handle_validation(MiddlewareMessage mmsg) throws Exception {
//some code
}
I understood that in first highlighted block java reflection is used
in invoking the method handle_validation..but need the detailed
explanation.
That's pretty much it. The only other bit is the
method.setAccessible(true);
which makes the method accessible to the caller (e.g. from private to public), thus allowing you to call it. However the above method does appear to be public already. Perhaps this is some legacy following a refactor ?
Note that this isn't RMI (remote method invocation), but rather reflection. The only RMI I can see here is the handle_validation() method possibly throwing a RemoteException.
Maybe someone had just discovered the hammer of a reflection so everything, including method that were already public, started looking like a nut.
It is garbage: throw it away. Just call the method directly.