I am trying to get the app code and display it, for an example if button X starts a new activity then a textView displays the whole method
I reached only how can I display code in HTML format from this question
But is there is a way to get the code of my app out, I think that there are 2 ways
- An Internal one by getting it by the app itself
- An External one by reading the java file then filtering it and getting the text of the method
Is there are any ideas about that?
Thanks in advance
2 Answers
Answers 1
Let's start with a broader overview of the problem:
Display App code
Press X button
Open new activity with a textview which displays the method
The goal is to do the following:
- Viewing app method by extracting it and then building & running it.
There are some methods we can use to run Java/Android code dynamically. The way I would personally do it is DexClassLoader and with Reflection.
If you need more details, let me know. Here is what it'd do though:
- View app method
- Upon pressing X, launch intent with extra to new Activity
- Parse and compile code dynamically and then run it with DexClassLoader and Reflection
Sources:
Sample file loading Java method from TerminalIDE Android App
Answers 2
The above is not currently possible as mentioned by others is the comments. What i can suggest is shipping your application with the source code in the assets folder and using a helper function to extract a certain methods from the source at runtime (your second proposed approach). I have written example code but it is in pure java and needs to be ported to android (a few lines).
NB: You may need to reformat the code after extraction depending on your use case.
Hope it helps :)
The code for the helper method:
static String getTheCode(String classname ,String methodSignature ) throws FileNotFoundException { //**********************A few lines of code below need changing when porting ***********// // open file, your will be in the assets folder not in the home dir of user, don't forget the .java extension when porting File file = new File(System.getProperty("user.home") +"/"+ classname +".java"); // get the source, you can use FileInputReader or some reader supported by android Scanner scanner = new Scanner(file); String source = ""; while(scanner.hasNext()) { source += " "+ scanner.next(); } //**********************The above code needs changing when porting **********// // extract code using the method signature methodSignature = methodSignature.trim(); source = source.trim(); //appending { to differentiate from argument as it can be matched also if in the same file methodSignature = methodSignature+"{"; //making sure we find what we are looking for methodSignature = methodSignature.replaceAll("\\s*[(]\\s*", "("); methodSignature = methodSignature.replaceAll("\\s*[)]\\s*", ")"); methodSignature = methodSignature.replaceAll("\\s*[,]\\s*", ","); methodSignature = methodSignature.replaceAll("\\s+", " "); source =source.replaceAll("\\s*[(]\\s*", "("); source = source.replaceAll("\\s*[)]\\s*", ")"); source = source.replaceAll("\\s*[,]\\s*", ","); source = source.replaceAll("\\s+", " "); if(!source.contains(methodSignature)) return null; // trimming all text b4 method signature source = source.substring(source.indexOf(methodSignature)); //getting last index, a methods ends when there are matching pairs of these {} int lastIndex = 0; int rightBraceCount = 0; int leftBraceCount = 0; char [] remainingSource = source.toCharArray(); for (int i = 0; i < remainingSource.length ; i++ ) { if(remainingSource[i] == '}'){ rightBraceCount++; if(rightBraceCount == leftBraceCount){ lastIndex = (i + 1); break; } }else if(remainingSource[i] == '{'){ leftBraceCount++; } } return source.substring(0 ,lastIndex); }
Example usage (getTheCode methods is static and in a class called GetTheCode):
public static void main(String... s) throws FileNotFoundException { System.out.println(GetTheCode.getTheCode("Main", "private static void shoutOut()")); System.out.println(GetTheCode.getTheCode("Main", "private static void shoutOut(String word)")); }
Output:
private static void shoutOut(){ // nothing to here } private static void shoutOut(String word){ // nothing to here }
NB: When starting your new activity create a method eg
private void myStartActivty(){ Intent intent = new Intent(MyActivity.this, AnotherActivity.class); startActivity(intent); }
Then in your onClick:
@Override public void onClick(View v) { myStartActivity(); myTextView.setText(GetTheCode.getTheCode("MyActivity","private void myStartActivity()")); }
Update: Ported the Code for android:
import android.content.Context; import java.io.IOException; import java.util.Scanner; public class GetTheCode { static String getTheCode(Context context, String classname , String methodSignature ) { Scanner scanner = null; String source = ""; try { scanner = new Scanner(context.getAssets().open(classname+".java")); while(scanner.hasNext()) { source += " "+ scanner.next(); } } catch (IOException e) { e.printStackTrace(); return null; } scanner.close(); // extract code using the method signature methodSignature = methodSignature.trim(); source = source.trim(); //appending { to differentiate from argument as it can be matched also if in the same file methodSignature = methodSignature+"{"; //making sure we find what we are looking for methodSignature = methodSignature.replaceAll("\\s*[(]\\s*", "("); methodSignature = methodSignature.replaceAll("\\s*[)]\\s*", ")"); methodSignature = methodSignature.replaceAll("\\s*[,]\\s*", ","); methodSignature = methodSignature.replaceAll("\\s+", " "); source =source.replaceAll("\\s*[(]\\s*", "("); source = source.replaceAll("\\s*[)]\\s*", ")"); source = source.replaceAll("\\s*[,]\\s*", ","); source = source.replaceAll("\\s+", " "); if(!source.contains(methodSignature)) return null; // trimming all text b4 method signature source = source.substring(source.indexOf(methodSignature)); //getting last index, a methods ends when there are matching pairs of these {} int lastIndex = 0; int rightBraceCount = 0; int leftBraceCount = 0; char [] remainingSource = source.toCharArray(); for (int i = 0; i < remainingSource.length ; i++ ) { if(remainingSource[i] == '}'){ rightBraceCount++; if(rightBraceCount == leftBraceCount){ lastIndex = (i + 1); break; } }else if(remainingSource[i] == '{'){ leftBraceCount++; } } return source.substring(0,lastIndex); } }
Usage:
// the method now takes in context as the first parameter, the line below was in an Activity Log.d("tag",GetTheCode.getTheCode(this,"MapsActivity","protected void onCreate(Bundle savedInstanceState)"));
0 comments:
Post a Comment