Buen día. Lo más sorprendente de BeanShell es la idea de que puedo controlar lo que quiero hacer dinámicamente desde el servidor y pensé que sería increíble.

Aunque nunca logré lograr eso y parece que nadie más intentó iniciar la actividad desde el shell tampoco.

Aquí cómo va. Simplemente quiero pasar el código del lado del servidor al Android, Android evaluará ese código dentro del intérprete y lo ejecutará.

El problema es que obtengo la excepción de BeanShell sin importar lo que intente.

El código del lado del servidor es el siguiente.

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

El código para Android es el siguiente.

  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();
            }
        }

Pero recibo la próxima excepción de 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 

¿Alguna idea de lo que está pasando?

0
Volo Apps 23 mar. 2017 a las 23:21

2 respuestas

La mejor respuesta

Por si acaso si alguien necesita la misma solución, estoy publicando para que todos lo sepan.

Así es como funciona.

En primer lugar, debe saber que, independientemente de lo que intente hacer en el lado del servidor, recuerde que BeanShell en realidad no sabe nada sobre el código de cadena que se pasa, ya que lo interpretará como un código fuera de la caja, así que con la ayuda de CommonWare sugiere la ruta del nombre completo que logré que funcione.

Entonces, el primer paso es inicializar el intérprete.

La inicialización básica es así:

  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();
                }

Preste mucha atención al context ya que era mi problema principal ir y venir, ya que en el momento en que logré forzar a BeanShell a reconocer mis clases, el BeanShell comenzó a lanzar Method not found excepción sobre el startActivity() así que al pensar lógicamente podemos suponer que estableceríamos el contexto como actividad como el padre para nuestros métodos remotos y comenzaríamos a evaluar todo desde context. Así que aquí se ve el código remoto.

$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));";

Las cosas más importantes a tener en cuenta aquí.

• Estamos importando todo lo posible para que BeanSherll reconozca nuestras clases, incluso si son Android-Build, no importa, aún tenemos que importarlas.

• Si va a utilizar cualquier clase, entonces, como CommonWare notó, DEBE especificar la ruta completa a esa Clase E.G my.package.name.MyProfile.class.

• Cuando estaba obteniendo Command Not Found comencé a pensar en el context.startActivity() ya que definí el context de antemano en BeanShell como mi padre desde el cual voy a usar métodos y Woala, todo funcionó ¡como un encanto!

0
Volo Apps 23 mar. 2017 a las 22:09

Posibles problemas

No sé mucho sobre BeanShell, pero hay un par de problemas aquí

  1. Puede importar una clase (en un lenguaje compilado) en tiempo de ejecución
  2. Estás intentando hacer el equivalente de Reflection (pero no están haciendo nada)
  3. Seguridad. Ningún usuario daría su consentimiento para que tengas control para abrir una pantalla en su aplicación de forma remota

Presumiblemente, se supone que BeanShell hace el reflejo debajo de las cubiertas, pero en un caso no podrá realizar la importación.

Posibles soluciones

  1. La clase / actividad que usa la biblioteca debería importar todo (no estoy seguro de si un compilador incluso retendrá esto)
  2. Puede usar la reflexión directamente, con cosas como "método del nombre". La desventaja es que es muy limitado el código que puede enviar desde el servidor a menos que maneje una gran cantidad de casos.
  3. Solo puedes enviar nombres / comandos; a puntos finales específicos en su aplicación Java (esto es lo que recomiendo) y planifique las acciones que desee con anticipación

    $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) )
    
0
Community 23 may. 2017 a las 12:17