Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

200
LINES

< > BotCompany Repo | #1000424 // Boot code v1 for JavaX/Android (pre-transpilation, archived)

JavaX source code - run with: x30.jar

import android.view.*;
import android.widget.*;
import android.content.Context;

import android.os.AsyncTask;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;

import java.io.*;
import java.lang.reflect.Method;
import java.net.*;

import dalvik.system.DexClassLoader;

public class main {
  public static View main(final FragmentActivity context) {
    ScrollView sv = new ScrollView(context);
    LinearLayout ll = new LinearLayout(context);
    ll.setOrientation(LinearLayout.VERTICAL);
    
    LinearLayout line1 = new LinearLayout(context);
    
    TextView label = new TextView(context);
    label.setText("Run which snippet ID?");
    line1.addView(label);
    
    final EditText tv = new EditText(context);
    tv.setText("675");
    line1.addView(tv);
    
    Button btnGo = new Button(context);
    btnGo.setText("Go");
    line1.addView(btnGo);
    
    ll.addView(line1);
    
    btnGo.setOnClickListener(new View.OnClickListener() {
      public void onClick(View v) {
        String snippetID = tv.getText().toString();
        String text = "Running: " + snippetID;
        Toast.makeText(context, text, 2000).show();
        new DynamicRunner(context).run(snippetID);
      }
    });

    sv.addView(ll);
    return sv;
  }
}

class DynamicRunner {
  private static final String mainClassName = "main" /*"test"*/;
  private static final String mainMethodName = "main" /*"run"*/;

  private final FragmentActivity activity;

  StringBuffer info = new StringBuffer();

  public DynamicRunner(FragmentActivity activity) {
    this.activity = activity;
  }

  public void run(String snippetID) {
    try {
      URL url = new URL(
                    /*"http://tinybrain.de/downloads/test.dex"*/
        "http://tinybrain.de:8080/dexcompile.php?id=" + snippetID);
      new DownloadFilesTask().execute(url);
    } catch (Throwable e) {
      showError(e);
    }
  }
  static byte[] DEX_FILE_MAGIC = { 0x64, 0x65, 0x78, 0x0a, 0x30, 0x33, 0x35, 0x00 };

  private Class<?> runDynamic(URL url) throws IOException, ClassNotFoundException {
    info.append("Loading dex: " + url.toString() + "\n");
    byte[] dexData = loadBinaryPage(url.openConnection());
    if (!isDex(dexData))
      throw new RuntimeException("Dex generation error: " + dexData.length + " bytes - " + new String(dexData, "UTF-8"));
    info.append("Dex data length: " + dexData.length + "\n");
    
    File dexDir = activity.getDir("dex", Context.MODE_PRIVATE);
    File dexFile;
    do {
      dexFile = new File(dexDir, System.currentTimeMillis() + ".dex");
    } while (dexFile.exists());
    
    File dexOutputDir;
    do {
      dexOutputDir = activity.getDir("dex-optimized-" + System.currentTimeMillis(), Context.MODE_PRIVATE);
    } while (dexOutputDir.list().length != 0);

    FileOutputStream fileOutputStream = new FileOutputStream(dexFile);
    fileOutputStream.write(dexData);
    fileOutputStream.close();

    ClassLoader parentClassLoader =
      //ClassLoader.getSystemClassLoader(); // does not find support jar
      //getClass().getClassLoader(); // Let's try this...
      getClass().getClassLoader().getParent(); // XXX !
    DexClassLoader classLoader = new DexClassLoader(dexFile.getAbsolutePath(), dexOutputDir.getAbsolutePath(), null,
      parentClassLoader);
    Class<?> theClass = classLoader.loadClass(mainClassName);
    return theClass;
  }

  private boolean isDex(byte[] dexData) {
    if (dexData.length < DEX_FILE_MAGIC.length) return false;
    for (int i = 0; i < DEX_FILE_MAGIC.length; i++)
      if (dexData[i] != DEX_FILE_MAGIC[i])
        return false;
    return true;
  }

  private void showError(Throwable e) {
    ScrollView scrollView = new ScrollView(activity);

    TextView errorView = new TextView(activity);
    errorView.setText(info + "\n" + getStackTrace(e));
    scrollView.addView(errorView);

    activity.setContentView(scrollView);
  }

  public static String getStackTrace(Throwable throwable) {
    StringWriter writer = new StringWriter();
    throwable.printStackTrace(new PrintWriter(writer));
    return writer.toString();
  }

  private class DownloadFilesTask extends AsyncTask<URL, Integer, Class<?>> {
    volatile Throwable error;
    URL url;

    protected Class<?> doInBackground(URL... urls) {
      try {
        url = urls[0];
        return runDynamic(url);
      } catch (Throwable e) {
        error = e;
        return null;
      }
    }

    protected void onProgressUpdate(Integer... progress) {
      //setProgressPercent(progress[0]);
    }

    protected void onPostExecute(Class<?> theClass) {
      try {
        if (error != null)
          showError(error);
        else if (theClass != null) {
          Method run = findMainMethod(theClass);
          Object result = run.invoke(null, activity);

          if (result instanceof Fragment) {
            FragmentManager fm = activity.getSupportFragmentManager();
            android.support.v4.app.Fragment fragment = fm.findFragmentByTag("mainFragment");
            if (fragment == null) {
              android.support.v4.app.FragmentTransaction ft = fm.beginTransaction();
              fragment = (Fragment) result;
              ft.add(android.R.id.content, fragment, "mainFragment");
              ft.commit();
            }
          } else if (result instanceof View) {
            activity.setContentView((View) result);
          } else
            showError(new Throwable("Bad return value from " + url + ", expected View or Fragment: " + result));
        } else
          showError(new Throwable("What?"));
      } catch (Throwable e) {
        showError(e);
      }
    }
  }

  static Method findMainMethod(Class<?> theClass) {
    for (Method method : theClass.getMethods())
      if (method.getName().equals(mainMethodName) && method.getParameterTypes().length == 1)
        return method;
    throw new RuntimeException("Method " + mainMethodName + " with 1 paramter not found in " + theClass.getName());
  }

  public static byte[] loadBinaryPage(URLConnection con) throws IOException {
    //setHeaders(con);
    ByteArrayOutputStream buf = new ByteArrayOutputStream();
    InputStream inputStream = con.getInputStream();
    while (true) {
      int ch = inputStream.read();
      if (ch < 0)
        break;
      buf.write(ch);
    }
    inputStream.close();
    return buf.toByteArray();
  }

}

Author comment

Began life as a copy of #676

download  show line numbers  debug dex  old transpilations   

Travelled to 13 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt

No comments. add comment

Snippet ID: #1000424
Snippet name: Boot code v1 for JavaX/Android (pre-transpilation, archived)
Eternal ID of this version: #1000424/1
Text MD5: fdd2be32cae5ad7a0b5c60c6b6dd1bed
Author: stefan
Category: javax
Type: JavaX source code
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2015-08-05 16:23:01
Source code size: 6636 bytes / 200 lines
Pitched / IR pitched: No / Yes
Views / Downloads: 606 / 559
Referenced in: #3000190 - Answer for stefanreich(>> t 20 questions)
#3000382 - Answer for ferdie (>> t = 1, f = 0)
#3000383 - Answer for funkoverflow (>> t=1, f=0 okay)