1

Good day. The main amazing thing about the BeanShell is the idea that i can control what i want to be done dynamically from the server and i thought it would be amazing.

Although i never succeded in achieving that and seems no one else tried to start activity from the beanshell either.

Here how it goes. I simply want to pass the code from the server side to the Android,Android is going to evaluate that code within interpreter and run that.

The issue is that i am getting the exception from BeanShell no matter what i try.

The code from server side is the next.

   $response['method'] = "import my.some.name.*;"
        . "startActivity(new Intent(this,MyProfile.class))";

The code for Android is the next.

  try {
                String responseBody = response.body().string();
                JSONObject jsonObject = new JSONObject(responseBody);
                String method = jsonObject.optString("method");
                Interpreter interpreter = new Interpreter();
                try {
                    Object res = interpreter.eval(method);
                } catch (EvalError evalError) {
                    evalError.printStackTrace();
                }
            } catch (IOException e) {
                e.printStackTrace();
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

But i am getting the next exception from the BeanShell

Sourced file: inline evaluation of: ``import my.some.name.*;startActivity(new Intent(this,MyProfile.class));'' : Class: MyProfile not found in namespace : at Line: 1 : in file: inline evaluation of: ``import my.some.name.*;startActivity(new Intent(this,MyProfile.class));'' : MyProfile 

Any ideas what is going on?

Nick Cardoso
  • 20,807
  • 14
  • 73
  • 124
Volo Apps
  • 235
  • 1
  • 3
  • 12
  • "i thought it would be amazing" -- it is also very difficult to secure, possibly resulting in lawsuits or prison sentences. "Any ideas what is going on?" -- try using a fully-qualified class name for `MyProfile`. – CommonsWare Mar 23 '17 at 21:11
  • what about the law it is not as the public APIS available for that,what about the fully-qualified name that might damn work aye! did not thought of that! thanks will try – Volo Apps Mar 23 '17 at 21:45
  • ohhh HELL YEAH! we did it!!! – Volo Apps Mar 23 '17 at 22:01
  • There is definitely a legitimate use case for this specifically for Device as a Service as a way to mitigate certain abnormal issues in the field as needed. – Maxwell175 Feb 09 '21 at 15:53

2 Answers2

1

Just in case if anyone needs the same solution i am posting for everyone to know.

Here how it goes.

Firstly you need to know that whatever you are trying to do on the server side remember that the BeanShell actually does not know anything about the String code you are passing itself,as it is going to interpret it just like a code out of box so with the help of CommonWare hint about full name path i managed to get it working.

So first step to do is to initialize the Interpreter.

Basic initialization goes like this :

  String responseBody = response.body().string();
                JSONObject jsonObject = new JSONObject(responseBody);
                String method = jsonObject.optString("method");
                Interpreter interpreter = new Interpreter();

                try {
                    interpreter.set("context",getApplicationContext());
                    Object res = interpreter.eval(method);
                } catch (EvalError evalError) {
                    evalError.printStackTrace();
                }

Take a very attentive notice about the context as it was my main issue going back and forth as at the moment when i succeded to actually force BeanShell recognize my classes,the BeanShell started to throw Method not found exception about the startActivity() so by thinking logically we can assume that we would set the context as activity as the parent one for our remote methods and start evaluating everything from the context. So here how the remote code is looking.

$response['method'] = "import ink.va.activities;"
    . "import android.content.Intent;"
    . "import android.content.*;"
    . "context.startActivity(new android.content.Intent(context, my.package.name.MyProfile.class));";

The most important things to notice here.

• We are importing everything possible for BeanSherll to recognize our classes,even if they are Android-Build,no matter,still we need to import them.

• If you are going to use any class,then as CommonWare noticed out,you MUST specify the full path to that Class E.G my.package.name.MyProfile.class.

• As i was getting Command Not Found i started to think about the context.startActivity() as i have defined the context beforehand in BeanShell as my parent from which i am going to use methods and Woala,everything worked like a charm!

Volo Apps
  • 235
  • 1
  • 3
  • 12
0

Possible Problems

I don't know a lot about BeanShell, but there's a couple of issues here

  1. You can import a class (in a compiled language) at runtime
  2. You're trying to do the equivalent of Reflection (but aren't doing any)
  3. Security. No user would consent to you having control to open a screen on their app remotely

Presumably BeanShell is supposed to do the reflection under the covers, but in an case you won't be able to do the import.

Possible solutions

  1. The class/activity using the library should import everything (I'm not sure if a compiler will even retain this)
  2. You can use reflection directly, with things like "method from name". The downside is it's very limited what code you can send from the server unless you handle a myriad of cases.
  3. You could only send names/commands; to specific endpoints in your java app (this is what I recommend) and plan the actions you want ahead of time

    $response['method'] = "my.some.name.MyProfile";
    
    JSONObject jsonObject = new JSONObject(response.body().string());
    String nameParam = jsonObject.optString("method");
    Class<? extends Activity> clazz = Class.forName(nameParam); //wrap with try
    startActivity( new Intent(this, clazz) )
    
Community
  • 1
  • 1
Nick Cardoso
  • 20,807
  • 14
  • 73
  • 124
  • ohh...that was the main reason for me to use the BeanShell as in their example i saw the Toast being able to run but yet if i am going to do it beforehand ,there is no need at all in that case :( as ideally i want the notification panel to be inside the app where each click will be handled differently that is the main idealogy for me,thus i am trying to achieve that – Volo Apps Mar 23 '17 at 21:31
  • yet you'r comment was very clever one – Volo Apps Mar 23 '17 at 21:31