I'm using the Xposed module to analyze an android app, and I'm trying to hook a constructor that's declared as private, but it's unable to find the class. Is it because the constructor is private or is there another issue? The constructor is: private CalendarContractCompat() {}. My hook code is:
findAndHookConstructor("com.android.calendar.CalendarContractCompat", lpparam.classLoader, new XC_MethodHook() {
Thanks in advance!
According to xposed bridge source (https://github.com/rovo89/XposedBridge/blob/art/app/src/main/java/de/robv/android/xposed/XposedHelpers.java), findAndHookConstructor calls getDeclaredConstructor and set its result to be accessible. That means the function should work on any constructor, public or not.
Can you hook a public method of the same class?
Related
I have the classes created, I'm trying to
FilePostProcessFactory PostProcessFactory = new FilePostProcessFactory();
FilePostProcess filePostProcess = PostProcessFactory.getFilePostProcessName(fileName);
filePostProcess.getFileConfig(fileId, postProcessInstructions);
This method: getFileConfig is giving me an error: is not public in packageName'. Cannot be accessed from outside package
I was reading this:
https://www.javatpoint.com/factory-method-design-pattern
and they have implemented there that the abstract void getRate(); can be accessed from another class outside of the package.
What am I missing?
Thank you
Change the package of a class from which you're calling it to be the same as the package of the target class, then the error will dissappear. You could also use reflection, and call setAccesible(true) on the method reference, then invoke it.
Try declaring the class public or do what Krzysztof mentioned.
I ended up renaming the class: public abstract class myClassName{...}
That fixed it
I need to write a test for this class. I need to verify that when the size of the list is exactly 2 then the modelService.save is called. Is it also possible to get to the object productModel?
I don't know where to start.
public class SoldMaterialPrepareInterceptor implements PrepareInterceptor<SoldMaterialModel> {
#Resource
private ModelService modelService;
#Override
public void onPrepare(SoldMaterialModel soldMaterialModel, InterceptorContext interceptorContext) throws InterceptorException {
setSAPSubstance(soldMaterialModel);
}
private void setSAPSubstance(SoldMaterialModel soldMaterialModel) {
ProductModel productModel = soldMaterialModel.getBaseProduct();
Set superCatagoriesList = [....]// gets the list somehow
if (superCatagoriesList.size() == 2) {
productModel.setSupercategories(superCatagoriesList);
modelService.save(productModel);
}
}
}
It is not a problem that the modelService field is private, it is a class field for which private access modifier is usually expected. You need to check the invocation of its save() method, which in turn cannot be private, otherwise it would not be possible to call it from the interceptor class.
As for the test, assuming the superCatagoriesList (which is actually a Set and not a List and also should be generic) gets its content directly or indirectly (e.g. through productModel) from the soldMaterialModel parameter, your task is to write a test, which populates soldMaterialModel with such values so that superCatagoriesList.size() will be 2, and then you can verify that the modelService.save() method was called exactly once with e.g. something like
Mockito.verify(modelService).save(any(ProductModel.class));
I found that when it is difficult to test a method most often there is a design problem of the code I am testing. I suggest a minor to refactoring first: move setSAPSubstance to SoldMaterialModel class and make it public. That is where that method needs to be (see feature envy). Of course modelService.save(productModel); will stay in the interceptor and it will be called only if needed.
Then you will only have to test the two public methods
Is that the whole class? Then I think I see the issue. There are no non-private ways to set the ModelService. When the whole app runs, the dependency injection framework uses reflection to set the ModelService. When you run the test, you don't have anyway to inject a mock. You have a few options.
You can add a constructor to SoldMaterialPrepareInterceptor which takes the ModelService as a parameter. Then you can use that in your test. You would probably also have to add a no-argument constructor because that's how your dependency injection framework creates it. Better yet, you could figure out how to configure the framework to use the new constructor that takes the ModelService.
public class SoldMaterialPrepareInterceptor {
// Public constructor if needed for dependency injection
public SoldMaterialPrepareInterceptor () { }
// If just used for test use protected or package private
// If used with dependency injection, use public.
protected SoldMaterialPrepareInterceptor(ModelService modelService){
this.modelService = modelService
}
The test class is usually in the same package as the actual class, so package private or protected scope is enough. Then the test looks something like this (Assuming Mockito and Junit. Logically, Spock and other frameworks would be similar):
ModelService modelService = Mockito.mock(ModelService.class);
SoldMaterialPrepareInterceptor interceptor = new SoldMaterialPrepareInterceptor(modelService);
// setup SoldMaterialModel and InterceptorContext
interceptor.onPrepare(soldMaterialModel, interceptorContext);
Mockito.verify(modelService, Mockito.times(0)).save(soldMaterialModel);
android.os.Handler class has a hide constructor --> void Handler(boolean async),
I just want to call this method by reflection,but in vain...
here is my code:
Class clazz = Class.forName("android.os.Handler");
Constructor construct = clazz.getConstructor(boolean.class);
//Constructor construct = clazz.getDeclaredConstructor(boolean.class);
construct.setAccessible(true);
boolean[] ailments = new boolean[]{true};
Handler handler = (Handler) construct.newInstance(ailments);
the error message is:
java.lang.NoSuchMethodException: android.os.Handler.<init>(boolean)
at java.lang.Class.getConstructor0(Class.java:3082)
at java.lang.Class.getConstructor(Class.java:1825)....
I try to iterate the clazz.getConstructors() returns Constructor array, and log their ParamsType, just find Looper,Callback ...
why it can't log out 'boolean'?
public More ...Handler(boolean async) {
this(null, async);
}
I have resolved this problem by importing the framework.jar instead of android.jar in android/sdk/platforms/android+versioncode/
adk had cut down the #hide api and internal classes to generate the android.jar,we can't use these resources unless we use framework.jar for developing.
see this project,it provided complete classes which included #hide api and internal classes.
android-hidden-api
I think you just need to call construct.newInstance(true) instead of passing the boolean as an array
I am trying to include EventBus in my application.
I followed http://tomaszdziurko.pl/2012/01/google-guava-eventbus-easy-elegant-publisher-subscriber-cases/ link.
I am getting compile errors:
I've added the guava-16.0.1.jar to the project.
But the register fucntion isn't working.
Any idea what am I missing here?
You're trying to call methods on members from the class, which is not possible. Those need to go inside a method (like a constructor or initializer).
Example code:
public class EventBusTest {
private final EventBus eventBus = new EventBus("test");
private final MultipleListener multiListener = new MultipleListener();
public void init() {
eventBus.register(multiListener);
}
}
Also, this question may be of use to help you understand Classes vs Objects
I am trying to write a web service that listens for SPML requests. I am using the spml version 2 toolkit.
I am using Jdeveloper to create this web serivce.
I create a method like this: public Response execute(Request req)
When I try and create a web service with jdeveloper...I get the following error:
ExecutionMode does not have a no-arg constructor.
Does anybody know how to fix this..?? An example of this would be greatly appreciated.
Thanks,
Brian
You need to add a default (no-arg) constructor to the ExecutionMode class.
public class ExecutionMode {
public ExecutionMode() {
// initialization code here
}
// other class code
}
Presumably you have a class called ExecutionMode? The compiler is looking for a no argument constructor, ie. a constructor that takes no arguments:
class ExecutionMode{
....
public ExecutionMode(){...}
....
}
If you define a parameterized contructor then you should also define a default constructor if you use one because java wont provide default constructor if you define parameterized constructor.So you should define
public ExecutionMode()
{
//defination
}