Created
October 24, 2013 20:25
-
-
Save melix/7144379 to your computer and use it in GitHub Desktop.
Simple Groovy activity
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package me.champeau.groovydroid | |
import android.app.Activity | |
import android.os.Bundle | |
import android.util.Log | |
import android.view.Menu | |
import android.view.View | |
import android.widget.EditText | |
import com.android.dx.dex.DexFormat | |
import com.android.dx.dex.DexOptions | |
import com.android.dx.dex.cf.CfOptions | |
import com.android.dx.dex.cf.CfTranslator | |
import com.android.dx.dex.code.PositionList | |
import com.android.dx.dex.file.DexFile | |
import groovy.transform.CompileStatic | |
import org.codehaus.groovy.control.CompilerConfiguration | |
import org.codehaus.groovy.control.customizers.ASTTransformationCustomizer | |
@CompileStatic | |
class GroovyActivity extends Activity { | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState) | |
setContentView(R.layout.groovy_main) | |
} | |
@Override | |
public boolean onCreateOptionsMenu(Menu menu) { | |
// Inflate the menu; this adds items to the action bar if it is present. | |
menuInflater.inflate(R.menu.groovy, menu) | |
true | |
} | |
public void executeCode(View view) { | |
def resultView = (EditText) findViewById(R.id.resultView) | |
resultView.text = generateMessage() | |
} | |
String generateMessage() { | |
def dexOptions = new DexOptions() | |
dexOptions.targetApiLevel = DexFormat.API_NO_EXTENDED_OPCODES | |
def cfOptions = new CfOptions() | |
cfOptions.positionInfo = PositionList.LINES | |
cfOptions.localInfo = true | |
cfOptions.strictNameCheck = true | |
cfOptions.optimize = false | |
cfOptions.optimizeListFile = null | |
cfOptions.dontOptimizeListFile = null | |
cfOptions.statistics = false | |
def config = new CompilerConfiguration() | |
config.addCompilationCustomizers( | |
new ASTTransformationCustomizer(CompileStatic) | |
) | |
def bytecode | |
def className | |
config.bytecodePostprocessor = { String s, byte[] bytes -> | |
def classDefItem = CfTranslator.translate("${s}.class", bytes, cfOptions, dexOptions) | |
def df = new DexFile(dexOptions) | |
df.add(classDefItem) | |
byte[] result | |
try { | |
result = df.toDex(new OutputStreamWriter(new ByteArrayOutputStream()), false) | |
className = s | |
} catch (IOException e) { | |
Log.e("DalvikConversion", "Unable to convert to Dalvik", e) | |
result = bytes | |
} | |
bytecode = result | |
result | |
} | |
def gcl = new GroovyClassLoader(this.classLoader, config) | |
def code = (EditText) findViewById(R.id.editText) | |
try { | |
gcl.parseClass("${code.text}") | |
} catch (Throwable e) { | |
Log.e("Dynamic", "Dynamic loading failed but intercepted bytecode (${bytecode}))") | |
} | |
def droidClassLoader = | |
new GroovyDroidClassLoader(getApplicationContext().getDir("dynclasses", 0), this.classLoader) | |
Class<? extends Script> scriptClass = droidClassLoader.defineDynamic(className, bytecode) | |
Script script | |
try { | |
script = scriptClass.newInstance() | |
} catch (InstantiationException e) { | |
Log.e("Dynamic", "Unable to create script", e) | |
return e.message | |
} catch (IllegalAccessException e) { | |
Log.e("Dynamic", "Unable to create script", e) | |
return e.message | |
} catch (Throwable e) { | |
Log.e("Dynamic", "Unable to create script", e); | |
return e.message | |
} | |
"Result: ${script.run()}" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment