How change button clicklistener outside activity in android?

352 views Asked by At

I have an apk that contains classes.dex. I dont't have apk source code. I have loaded an activity from dex file(LoginActivity) and implemented onClicklistener for button1 in LoginActivity. I succeeded to load dex file and started activity from dex file via this code:

DexClassLoader dex = new DexClassLoader(dexInternalStoragePath.getAbsolutePath(), mAppContext.getCacheDir().getPath(), null, loader);    
toasterClass = dex.loadClass("com.example.myapplication.ui.login.LoginActivity");
Intent intent = new Intent();
intent.setClass(getApplicationContext(),toasterClass);
setContentView(View.inflate(getApplicationContext(), R.layout.activity_login, null));
Button mAddTaskButton = (Button) findViewById(R.id.button2);
mAddTaskButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                AlertDialog aldlg = new AlertDialog.Builder(gLoginActivity.this).create();
                aldlg.setTitle("Login");
                aldlg.setMessage("You pressed Login Button");
                aldlg.setButton(AlertDialog.BUTTON_NEUTRAL, "OK",
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.dismiss();
                            }
                        });
                aldlg.show();
            }
        });
startActivity(intent);

but when I clicked button2, it didn't show alertdialog. I think android is preventing to change onClicklistener outside from activity. Is it correct? Any help how to implement this?

1

There are 1 answers

0
Artem Viter On BEST ANSWER

When you use code:

Button mAddTaskButton = (Button) findViewById(R.id.button2)

it means that you try to find view in your current Activity instance (same thing as this.findViewById)- not from com.example.myapplication.ui.login.LoginActivity

I have two ideas to solve your problem:

  1. Using Application/Activity method registerActivityLifecycleCallbacks (link for activity ). This callback has method onActivityCreated which provides instance of created activity. In this method you can get Activity's name by calling to activity.getComponentName().getClassName() (link to getComponentName method and to ComponentName class description ). If activity provided by onActivityCreated method is com.example.myapplication.ui.login.LoginActivity then you can add OnClickListene to button like in your code snippet(just use reference to activity to get Button):
Button mAddTaskButton = (Button) activity.findViewById(R.id.button2);
mAddTaskButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                      ...
            }
        });

Be careful with ActivityLifecycleCallback because it attaches to application life-cycle (not activity) and don't capture Activity's content from callback to avoid memory links.

  1. Another solution - you can try to create "stub" activity with name com.example.myapplication.ui.login.LoginActivity then extend it like: public class MyLoginActivity extends LoginActivity. Then you can override MyLoginActivity's onCreate method and do what you want (I mean add your code for button onClick listener). But you don't need to build in this "stub" LoginActivity to application (apk), you should add it as compile only dependency. I don know how do it with a class but I know other solution: you can put LoginActivity to separate module or library(aar/jar) and add the library(module) as compileOnly dependency to your gradle file (like here)