[Xposed General] elesbb:
Okay guys.

I have seen a lot of posts where people need to trigger an action inside their own app from the xposed class they hooked. Sometimes (quite often) there is no context object to obtain where we could usually send a broadcast or start a service or even maybe an activity from our own apps we wrote.

This guide will allow me to show you how this is possible without the use of a context object. I have used this myself in multiple modules and it works quite wonderfully. I am going to provide as much code as possible without being too specific, that is where you will need your own intuition to figure out some simple things.

Now for the guide :)

First, obviously, we need to create a new xposed module. That's another thread found here. For the duration of this guide, I am going to assume you have read that. If you have not, stop reading this, and click that link and go read that please :) Its fun!

Alright, our module has been created, all manifest declarations established all jars imported. Sweet.

Now we are looking at an empty class file that implements the IXPosedHookLoadPackage.

Next, we need to create a class that extends Service. You can either create a nested class inside the Xposed class, or, my personal choice, create an entirely new class inside your package. ***(Don't forget to add this service to your manifest!!!)

Next, we need to create a boot receiver that will start our newly created service when our device gets booted so its already up and running. (Google that if you don't know how to do that.) here is a great read on how to do this.

Now, go back to your service class (either nested or its own file) and create the "onCreate" method. (If not done already)

Inside the onCreate method of your service, we will need to create a file inside the apps files directory. You can do this in the constructor as well if you please. I have the code below showing how to create your new file.

@Override
public void onCreate() {
super.onCreate();

File myCommands = new File(this.getFilesDir(), "commands");

}

Yes its that

Now that we have our file object created, we need to actually create the file as follows:

if(!myCommands.exists()) { //Make sure the file doesn't already exist first.

try {
myCommands.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

However, there are some things we need to do to allow the xposed hooked method permissions to read them, which are simple and as follows.

myCommands.setReadable(true, false);
myCommands.setWritable(true, false);

We need to use the method "setReadable" and "setWriteable" to set the files permission. The first boolean argument sets the file writeable or readable, the second boolean argument restricts it to the owner only, which since we used false, means that everyone can read and write to this file.

So, now lets take a look at our entire onCreate method thus far:

@Override
public void onCreate() {
super.onCreate();

File myCommands = new File(this.getFilesDir(), "commands");

if(!myCommands.exists()) {

try {
myCommands.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

myCommands.setReadable(true, false);
myCommands.setWritable(true, false);
}

Pretty simple. Now, we need to actually do something with this file. This is where the magic begins to happen ;)

After our file is created, we need to create what is called a FileObserver. The following code explains how to do that.

FileObserver myActionsObserver = new FileObserver(myCommands.getAbsolutePath()) {

@Override
public void onEvent(int event, String path) {
// This is where things are done. Every time you open, write to, close etc a file. This method is executed.

}

};

Now our file observer is created. However, it is doing nothing. As of now, it does not even listen for file changes. I want to further define what to do on a file change first before I start receiving the changes.

The "onEvent(int event, String path)" method is what we will be defining.

The "event" argument determines what type of event was acted upon the file. For a full explanation, click here. The "CONSTANTS" table shows the different types of events acted upon a file. For this guide, I will be using the constant "CLOSE_WRITE".

So inside the onEvent method we should have this:

@Override
public void onEvent(int event, String path) {
// This is where things are done. Every time you open, write to, close etc a file. This method is executed.
if(event == FileObserver.CLOSE_WRITE) {
//This is where we are notified that something has happened.
//This is where we can communicate from the xposed hooked method to our own app where we can do whatever we need to do :)

}
}

Now we are notified of the "CLOSE_WRITE" action onto our file. The next step would be to read the text file for our actual command. For instance, we need to start up an activity. So, for the instance of this guide, I will use the command "startActivity".

Once our "onEvent" method is executed and we see that its action was CLOSE_WRITE, we are going to read the file for the action. This is simple, I really don't feel like I should/have to go into this, but I will to make the guide full.

Here we are going to read the file, I am using a BufferedReader for this.

try {
BufferedReader br = new BufferedReader(new FileReader(myCommands));
String action = br.readLine();
br.close();
} catch(Exception e) {
e.printStackTrace();
}

Now we got a string object of the contents of the file to determine the necessary actions to take. Don't forget to change the myCommands file to final :)

Now that we have all that setup, we can finally start receiving actions for the file. We simply do this by calling the "startWatching" method of FileObserver as follows.

myActionsObserver.startWatching();

Now, whenever that file is written to, we will get notified of it in our service :)

So now that our service is setup, we need to setup our xposed hooked method to write to the file.

I am going to make something up that prolly doesn't exist in android source, but its just an example method that I am going to hook :)

The only thing to note when creating the file is that we need to hard code the file's path.

@Override
protected void afterHookedMethod(MethodHookParam param) {

boolean status = (Boolean)XposedHelpers.getObjectField(param.thisObject, "status");

if(status) {
File myCommand = new File(Environment.getDataDirectory() + <your package name here>, "commands");

FileWriter fw = new FileWriter(myCommands);
fw.write("startActivity");
fw.close();
}

Now we have written to our file and our service will receive the action.

That about sums it up :) You can also do the reverse, you can create a FileObserver inside your xposed hooked method, and use your own activity or service to write to it and then have the xposed hooked method do some actions regarding the command being written to the file.

Please hit thanks and donate if I helped you out! Don't hesitate to ask questions either!

Thanks!