stephanenicolas / afterburner

A library to help other librairies getting rid of boiler plate via byte code manipulation. Works on Android too.
Apache License 2.0
74 stars 9 forks source link

Is there a way to modify the android button method #4

Open XuNeal opened 9 years ago

XuNeal commented 9 years ago

I want to append some mark When the developer calls some method, like setOnClickListener, but I get a exception:javassist.NotFoundException: C:\Users\xyz\AppData\Local\Android\android-sdk\platforms\android-21\android.jar.

My code:

 AfterBurner afterBurner = new AfterBurner();

            ClassPool classPool = new ClassPool(ClassPool.getDefault());
            classPool.insertClassPath("C:\\Users\\xyz\\AppData\\Local\\Android\\android-sdk\\platforms\\android-21\\android.jar");
            afterBurner.addOrInsertMethod(new InsertableMethod(classPool.get(Button.class.getName())) {

                @Override
                public String getFullMethod() throws AfterBurnerImpossibleException {
                    return "public void mark() { ___BODY___ }";
                }

                @Override
                public String getBody() throws AfterBurnerImpossibleException {
                    String body = "android.util.Log.d(\"AfterBurner Demo\", \""
                            + "set click listener"
                            + " [\" + System.identityHashCode(this) + \"] \u27F3 "
                            + "\");";
                    return body;
                }

                @Override
                public String getTargetMethodName() throws AfterBurnerImpossibleException {
                    return "mark";
                }

                @Override
                public String getInsertionAfterMethod() {
                    return "setOnClickListener";
                }
            });
stephanenicolas commented 9 years ago

You should not do it this way. What you say actually is that you want to add some code after a call to setOnClickListener inside the mark method. And if the method mark doesn't exist, then create a new one.

For instance, it would need a class with a method like :

public void mark() { setOnClickMethod(); //the body you define would go here }

But I guess what you want is to log something is more :

It would give something like :

builder .insertIntoClass(classToInsertInto) .inMethodIfExists("setOnClickListener") .afterACallTo("setOnClickListener") .withBody(body) //here you log .elseCreateMethodIfNotExists(fullMethod) //here you must create a setOnClickListener method .doIt();

Or without a builder :

afterBurner.addOrInsertMethod(new InsertableMethod(classPool.get(Button.class.getName())) {

            @Override
            public String getFullMethod() throws

AfterBurnerImpossibleException { return "public void setOnclickListener() { _BODY_ }"; }

            @Override
            public String getBody() throws AfterBurnerImpossibleException {
                String body = "super.onClickListener($1);"
               + "android.util.Log.d(\"AfterBurner Demo\", \""

                        + "set click listener"
                        + " [\" + System.identityHashCode(this) +

\"] \u27F3 "

            @Override
            public String getTargetMethodName() throws

AfterBurnerImpossibleException { return "setOnClickListener"; }

            @Override
            public String getInsertionAfterMethod() {
                return "setOnClickListener";
            }
        });

That should work.

Stéphane

2015-01-17 19:07 GMT-05:00 XuNeal notifications@github.com:

I want to append some mark When the developer calls some method, like setOnClickListener, but I get a exception:javassist.NotFoundException: C:\Users\xyz\AppData\Local\Android\android-sdk\platforms\android-21\android.jar.

My code:

AfterBurner afterBurner = new AfterBurner();

        ClassPool classPool = new ClassPool(ClassPool.getDefault());
        classPool.insertClassPath("C:\\Users\\xyz\\AppData\\Local\\Android\\android-sdk\\platforms\\android-21\\android.jar");
        afterBurner.addOrInsertMethod(new InsertableMethod(classPool.get(Button.class.getName())) {

            @Override
            public String getFullMethod() throws AfterBurnerImpossibleException {
                return "public void mark() { ___BODY___ }";
            }

            @Override
            public String getBody() throws AfterBurnerImpossibleException {
                String body = "android.util.Log.d(\"AfterBurner Demo\", \""
                        + "set click listener"
                        + " [\" + System.identityHashCode(this) + \"] \u27F3 "
                        + "\");";
                return body;
            }

            @Override
            public String getTargetMethodName() throws AfterBurnerImpossibleException {
                return "mark";
            }

            @Override
            public String getInsertionAfterMethod() {
                return "setOnClickListener";
            }
        });

— Reply to this email directly or view it on GitHub https://github.com/stephanenicolas/afterburner/issues/4.

XuNeal commented 9 years ago

thanks for so long comment

what i really want to do is

  1. add a mark() method to the android.widget.Button
  2. modify the android.widget.Button.setOnclickListener method like this
void setOnClicklistener(OnClickListener listener) {
   // exist code
  mark();
}

And the frist problem is classPool.get(Button.class.getName()) throw javassist.NotFoundException. The Button is one of android framwork class, not my defined by me, I want to know is it possible to modify a class of android framework.

thanks