Android Informing application through different process non-activity class - java

I'm currently developing an app which requires some adb commands
First i have a seperate module in application Module1, and there is com.mordred.xyz.Main class in there
public class Main {
public static void main(String[] args) {
System.out.println("mordred main class is instantiated");
// rest of code
}
}
I'm instantiating that Main class (com.mordred.xyz.Main) via adb (adb shell dalvikvm -cp com.mordred.MyApplication com.mordred.xyz.Main)
and i have an MainActivity in my application (com.mordred.MyApplication.MainActivity)
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// MainActivity rest of code
}
}
so the question is How can i inform the application.MainActivity that the "Main class is instantiated through adb" even if application is closed?
I tried to Context.sendIntent but it requires Context object, and also i cannot pass Context object from MainActivity nor other object (because i want Main class can be instantiated even if application is not running)
i dont want to use hidden apis (IActivityManager has broadcastIntent method but that class is hidden system api)
What can i do for it?
UPDATE:
eureka, probably i found a way,
i will set a hardcoded path in Main class and create a dummy file in there, and then will give a readable and writable permissions to everyone via File.setReadable() and then when Main class is instantiated, it will write something like "Main: 1" into that file, and then i will add a check into application's MainActivity class that will check that file if its "Main: 1" or not, ("Main: 1" means that the Main class is instantiated otherwise "Main: 0" means vice versa)

Ok i found a cleaner and nicer way to do it, yeah its reflection hack :P
here is the function that i made to send Intents globally which can be called from everywhere
i tested it and it works good, and also note that: it is for >Marshmallow, (because of main broadcastIntent() method's parameter types)
public void sendGlobalIntent(Intent intent,String[] requiredPermissions) {
try {
Class<?> cActivityManagerNative = Class
.forName("android.app.ActivityManagerNative");
Method mGetDefault = cActivityManagerNative.getMethod("getDefault");
mGetDefault.setAccessible(true);
Object oActivityManagerNative = mGetDefault.invoke(null);
Method[] methods = cActivityManagerNative.getMethods();
Method m = null;
for (Method method : methods) {
if (m.getName().equals("broadcastIntent")) {
m = method;
}
}
if (m == null) {
return;
}
m.setAccessible(true);
m.invoke(oActivityManagerNative, null, intent, null, null, 0, null,
null, requiredPermissions, -1, null, true, false, android.os.Process.myUid() / 100000);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}

Related

Jumping to another class using a JButton

I have the below code where I made a simple GUI. I would like Button2 to navigate to class 'Project2', which should start another piece of code. Just to note, in its current state, 'Project2' has no GUI, though I intend to add one soon. Anyway, this 'code jump' which I used by adding: String[] args = {};
Project2.main(args);
is not working, as the IDE says 'IOException must be caught or thrown'. I know how this works, though I am not sure how to implement it in the program.
Thanks in advance!
You can try to use dynamic class loading for your program. Below you can find lambda, which calls main method from com.stackoverflow.ExternalCaller class.
If you do not like to use lambda, you can create a simple anonymous class.
button.addActionListener(s -> {
try {
Class<?> externalCaller = Class.forName("com.stackoverflow.ExternalCaller");
Method main = externalCaller.getDeclaredMethod("main", new Class[]{String[].class});
main.invoke(null, new Object[]{new String[0]});
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
});
ExternalCaller class in its turn looks something like that:
package com.stackoverflow;
public class ExternalCaller {
public static void main(String args[]) {
System.out.println("Hello World");
}
}
In result once you click on the button you will get Hello World output in console.
If you would like to work with external jars etc. please look on Process class. Quick example:
Process proc = Runtime.getRuntime().exec("java -jar External.jar");
Or even more on fork/exec. You can read From Runtime.exec() to ProcessBuilder for more details.
Hope this will help. Good luck.
In most of the IDE's, when you right-click on the Button2 in the Design(GUI) pane, you can travel through:
Events -> Actions -> actionPerformed().
And write this code in the selected method to switch classes:
this.setVisible(false); //turns off the visibility of the current class
outputClass out = new outputClass(); //creating the object of the class you want to redirect to
out.setVisible(true);//turns on the visibility of the class you want to redirect to

Unable to use #spring annotations when class object is new

Actually i am having a spring main class as follows.
ClassLoader loader = null;
try {
loader = URLClassLoader.newInstance(new URL[]{new
File(plugins + "/" + pluginName + "/" + pluginName +
".jar").toURI().toURL()}, getClass().getClassLoader());
} catch (MalformedURLException e) {
e.printStackTrace();
}
Class<?> clazz = null;
try {
clazz = Class.forName("com.sample.Specific", true, loader);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Method method = null;
try {
method = clazz.getMethod("run",new Class[]{});
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
method.invoke(clazz.newinstance,new Object[]{});
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
Specific Class is follow :
package com.sample
#Service
public class Specific {
#Autowired
private FD fd;
public void run(){
fd.init();
}
}
#Autowired FD comes to be null. Can anyone give me some solution as i also know new operator will not work for #autowired. As i am loading class with new instance then only it becomes null. Can anyone guide me in this thing
Spring has its own way to provide you new objects. As long as you're consistent using #Autowired and #Component/#Service/#Repository/#Controller there should be no problem
And since all "business" object instantiation is handled by Spring you should never use new. If you have no other way of getting an instance (something I realy doubt about it) you can use ApplicationContext.getBean() but as I said, in most cases this is not required (and this is also a bad practice)
If you need several instances of a class instead of injecting them (by using #Autowired) you can inject a Provider<T>
UPDATE
Since the class is known at runtime you need to inject an ApplicationContext and use it to get the bean:
public class TheClassWhereYouAreCreatingTheObject {
#Autowired
private ApplicationContext context; // You definitely need this
public void theMethodWhereYouAreCreatingTheObject() {
Class<?> clazz = ... // getting the object class
Object instance = context.getBean(clazz); // getting and instance trough Spring
// If you know that kind of object you will get cast it at call its methods
((Specific) instance).run();
// If you know anything about the class you will have to use reflection
Method method = clazz.getMethod("run", new Class[]{});
method.invoke(instance, new Object[]{});
}
}
Add Specific Service bean inside your main class. As long as the service is inside one your component scan packages then you shall be fine. Do not use new operator.
#Autowired
private Specific specific;
If you want to take advantage of autowiring then I think we have to think from spring terms.
you can use Beanutils to create a new instance and play with reflections supporting spring features.
Please go through below methods:
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/BeanUtils.html

How does it work that the method run() is called when the plugin is loaded?

In ImageJ , The Interface Plugin has a methods run() like this:
package ij.plugin;
/** Plugins that acquire images or display windows should
implement this interface. Plugins that process images
should implement the PlugInFilter interface. */
public interface PlugIn {
/** This method is called when the plugin is loaded.
'arg', which may be blank, is the argument specified
for this plugin in IJ_Props.txt. */
public void run(String arg);
}
why the run() method can be automatically called when the Plugin is loaded?
the run() method can be automatically called when the Plugin is loaded?
There is nothing automatic about it. There is a line of code in imagej library which says:
thePlugIn.run(arg);
The full snippet is this (from here):
/** Runs the specified plugin and returns a reference to it. */
public static Object runPlugIn(String commandName, String className, String arg) {
if (arg==null) arg = "";
if (IJ.debugMode)
IJ.log("runPlugIn: "+className+argument(arg));
// Load using custom classloader if this is a user
// plugin and we are not running as an applet
if (!className.startsWith("ij.") && applet==null)
return runUserPlugIn(commandName, className, arg, false);
Object thePlugIn=null;
try {
Class c = Class.forName(className);
thePlugIn = c.newInstance();
if (thePlugIn instanceof PlugIn)
((PlugIn)thePlugIn).run(arg);
else
new PlugInFilterRunner(thePlugIn, commandName, arg);
}
catch (ClassNotFoundException e) {
if (IJ.getApplet()==null)
log("Plugin or class not found: \"" + className + "\"\n(" + e+")");
}
catch (InstantiationException e) {log("Unable to load plugin (ins)");}
catch (IllegalAccessException e) {log("Unable to load plugin, possibly \nbecause it is not public.");}
redirectErrorMessages = false;
return thePlugIn;
}

Using reflection to customize private field of superclass

I am running into a problem trying to modify the behavior of my superclass' private fields from the sub-class (The superclass wasn't designed to be extended and I can't change that).
Basically, what I have is :
public class OrthoCanvas {
private OrthoView xy, xz, zy;
public class OrthoView { ... }
}
And I want to do something like that :
public class CustomOrthoCanvas extends OrthoCanvas {
public CustomOrthoCanvas {
// Sets superclass xy, xz, zy to instances of CustomOrthoView
// This seem to work fine (I'm using reflection to change the fields)
}
public class CustomOrthoView extends OrthoView { ... }
}
As I said, the reflection seems to work (I'm building CustomOrthoView). But, for the moment, I didn't override any method, and my constructor is just super(whatever), and a Sysout to check what I'm doing. Yet, the original behavior of OrthoView just disappeared, and nothing is working.
Did I make a mistake in my code or is this something more related to my specific case ?
Thanks a lot
Edit : I've just thought that it would be easier if I showed you how I used reflection, so there it is :
Field fieldXY = null;
Field fieldXZ = null;
Field fieldZY = null;
try {
System.out.println(this.getClass().getSuperclass().getName());
fieldXY = Class.forName(this.getClass().getSuperclass().getName()).getDeclaredField("xy");
fieldXZ = Class.forName(this.getClass().getSuperclass().getName()).getDeclaredField("xz");
fieldZY = Class.forName(this.getClass().getSuperclass().getName()).getDeclaredField("zy");
} catch (NoSuchFieldException e) {
System.out.println("-- No such field --");
System.out.println(e.getMessage());
} catch (SecurityException e) {
System.out.println("-- Security failure --");
System.out.println(e.getMessage());
} catch (ClassNotFoundException e) {
System.out.println("-- Class not found --");
System.out.println(e.getMessage());
}
fieldXY.setAccessible(true);
fieldXZ.setAccessible(true);
fieldZY.setAccessible(true);
try {
fieldXY.set(this, new CustomOrthoView(this, DimensionId.Z));
fieldXZ.set(this, new CustomOrthoView(this, DimensionId.Y));
fieldZY.set(this, new CustomOrthoView(this, DimensionId.X));
} catch (IllegalArgumentException e) {
System.out.println("-- Illegal argument --");
System.out.println(e.getMessage());
} catch (IllegalAccessException e) {
System.out.println("-- Illegal access --");
System.out.println(e.getMessage());
}
Edit2 : This is a simplified behavior of the superclass :
public class Orthoviewer {
// This class creates a canvas to display an image
public class OrthoCanvas {
// This class represents how an image is displayed
// It implements listeners (to navigate through the image for
// example), and ways to refresh the image
public class OrthoView extends JPanel {
// This class displays one part of the image (one plane)
// To represent a 3D point by the intersection of the three corresponding planes
// It has an attribute which indicates its dimension
// (X is for ZY plane, Y for XZ plane etc)
// It overrides the method paintComponent to draw itself
public class ImageCache implements Runnable {
// This handles the image to display on the corresponding plane
}
}
}
}

Event handling with Java Reflection

Ok so, this is quite confusing to explain. I will try my best.
Inspired by the Bukkit Event System where you can make voids an event handler by just using #EventHandler.
Example:
#EventHandler
public void aRandomName(PlayerMoveEvent ev) {
}
As you can see, the name of the method doesn't matter. Which event is passed on is determined by the event argument type.
All events extend the Event class.
I have made up some code which I think would work, except for one thing.
public List<Object> eventContainers;
public void fireEvent(Event e) {
Method[] methods;
for (Object o : eventContainers) {
Object[] classes = o.getClass().getClasses();
for (Object clss : classes) {
methods = clss.getClass().getMethods();
for (Method m : methods) {
if (m.getAnnotation(EventHandler.class) != null) {
try {
Class[] requiredTypes = m.getParameterTypes();
for(Class cl : requiredTypes) {
if(e.equals(cl)) {
m.invoke(clss, e);
}
}
} catch (IllegalAccessException ex) {
} catch (IllegalArgumentException ex) {
} catch (InvocationTargetException ex) {
}
}
}
}
}
}
What my code does:
Loops through all the classes in eventContainers, looks for methods that have the #EventHandler annotation and sends the specified event to that method. However, I want to see what kind of event the given event in fireEvent(Event e) is, and then look at the methods who require an event parameter of that kind. How would I do that? I figure that
Class[] requiredTypes = m.getParameterTypes();
for(Class cl : requiredTypes) {
if(e.equals(cl)) {
m.invoke(clss, e);
}
}
will not work.
Ultimately I want to be able to pass on events to plugins. Like this:
EventManager.fireEvent(new PlayerMoveEvent(player));
Which will be sent to all plugins and the plugins that have
#EventHandler
public void aVoid(PlayerMoveEvent e) {
//stuff
}
If you have any questions, I will try to explain it better. Thanks in advance for your help!
Your code uses e.equals(cl), which is comparing an instance of Event with an instance of Class (the class of an instance of Event) - this will never return true. What you want to do instead is:
if(e.getClass().equals(cl)) {
m.invoke(clss, e);
}
Alternatively, if you want methods annotated with #EventHandler to handle all subclasses of the class that their method signature defines (i.e. a method like handle(Event e) would be called with PlayerMoveEvents as well as all other events), then you want:
if(cl.isAssignableFrom(e.getClass())) {
m.invoke(clss, e);
}
See the Class Javadoc here for more information.
Note that I think there are a few other problems in you code. For example, Method.invoke should be called with an instance of the class that contains a method that is annotated with #EventHandler. It is a little unclear from your code, but I believe this should therefore be:
m.invoke(o, e);
Also, by calling o.getClass().getClasses(), you are iterating over the classes defined in the class of o - you probably want to iterate over the methods of the class of o directly, i.e.:
for (Method m : o.getClass().getMethods()) {
if (m.getAnnotation(EventHandler.class) != null) {
Class[] requiredTypes = m.getParameterTypes();
if (requiredTypes.length == 1 && requiredTypes[0].isAssignableFrom(e.getClass()) {
m.invoke(o, e);
}
}
}
You can get the parameter types from a Method using method.getGenericParameterTypes(), so:
m.invoke(clss, m.getGenericParameterTypes()[0].class.cast(e));
Not sure if that's what you want.
Assuming the EventHandler annotated method only has one parameter
Method[] methods = YourClass.class.getDeclaredMethods();
Object yourInstance = null; // get it
Event e = null; // get it
for (Method method : methods) {
EventHandler handler = method.getAnnotation(EventHandler.class);
if (handler != null) {
Class<?>[] parameterTypes = method.getParameterTypes();
// you're going to need different logic if you have more than one parameter
if (parameterTypes.length == 1 && parameterTypes[0].isAssignableFrom(e.getClass())) {
method.invoke(yourInstance, e);
}
}
}
I've not included any exception handling.
Get all the methods of event handler candidate classes and iterate over them. If a method has the #EventHandler annotation, get its parameter type list. If it only has one parameter and that type is assignable from your event type e.getClass(), then invoke it passing in your event.
I have now modified the code to a working event system!!!!!! :D thanks so much andersschuller!
public void fireEvent(Event e) {
Method[] methods;
for (Object o : eventContainers) {
methods = o.getClass().getMethods();
for (Method m : methods) {
if (m.getAnnotation(EventHandler.class) != null) {
try {
if (m.getParameterTypes()[0].isAssignableFrom(e.getClass())) {
m.invoke(o, e);
}
} catch (IllegalAccessException ex) {
} catch (IllegalArgumentException ex) {
} catch (InvocationTargetException ex) {
}
}
}
}
}
I kept all answers in mind, thanks all!

Categories

Resources