1 | import android.view.*; |
2 | import android.widget.*; |
3 | import android.content.Context; |
4 | |
5 | import android.os.AsyncTask; |
6 | import android.support.v4.app.Fragment; |
7 | import android.support.v4.app.FragmentActivity; |
8 | import android.support.v4.app.FragmentManager; |
9 | |
10 | import java.io.*; |
11 | import java.lang.reflect.Method; |
12 | import java.net.*; |
13 | |
14 | import dalvik.system.DexClassLoader; |
15 | |
16 | public class main {
|
17 | public static View main(final FragmentActivity context) {
|
18 | ScrollView sv = new ScrollView(context); |
19 | LinearLayout ll = new LinearLayout(context); |
20 | ll.setOrientation(LinearLayout.VERTICAL); |
21 | |
22 | LinearLayout line1 = new LinearLayout(context); |
23 | |
24 | TextView label = new TextView(context); |
25 | label.setText("Run which snippet ID?");
|
26 | line1.addView(label); |
27 | |
28 | final EditText tv = new EditText(context); |
29 | tv.setText("675");
|
30 | line1.addView(tv); |
31 | |
32 | Button btnGo = new Button(context); |
33 | btnGo.setText("Go");
|
34 | line1.addView(btnGo); |
35 | |
36 | ll.addView(line1); |
37 | |
38 | btnGo.setOnClickListener(new View.OnClickListener() {
|
39 | public void onClick(View v) {
|
40 | String snippetID = tv.getText().toString(); |
41 | String text = "Running: " + snippetID; |
42 | Toast.makeText(context, text, 2000).show(); |
43 | new DynamicRunner(context).run(snippetID); |
44 | } |
45 | }); |
46 | |
47 | sv.addView(ll); |
48 | return sv; |
49 | } |
50 | } |
51 | |
52 | class DynamicRunner {
|
53 | private static final String mainClassName = "main" /*"test"*/; |
54 | private static final String mainMethodName = "main" /*"run"*/; |
55 | |
56 | private final FragmentActivity activity; |
57 | |
58 | StringBuffer info = new StringBuffer(); |
59 | |
60 | public DynamicRunner(FragmentActivity activity) {
|
61 | this.activity = activity; |
62 | } |
63 | |
64 | public void run(String snippetID) {
|
65 | try {
|
66 | URL url = new URL( |
67 | /*"http://tinybrain.de/downloads/test.dex"*/ |
68 | "http://tinybrain.de:8080/dexcompile.php?id=" + snippetID); |
69 | new DownloadFilesTask().execute(url); |
70 | } catch (Throwable e) {
|
71 | showError(e); |
72 | } |
73 | } |
74 | static byte[] DEX_FILE_MAGIC = { 0x64, 0x65, 0x78, 0x0a, 0x30, 0x33, 0x35, 0x00 };
|
75 | |
76 | private Class<?> runDynamic(URL url) throws IOException, ClassNotFoundException {
|
77 | info.append("Loading dex: " + url.toString() + "\n");
|
78 | byte[] dexData = loadBinaryPage(url.openConnection()); |
79 | if (!isDex(dexData)) |
80 | throw new RuntimeException("Dex generation error: " + dexData.length + " bytes - " + new String(dexData, "UTF-8"));
|
81 | info.append("Dex data length: " + dexData.length + "\n");
|
82 | |
83 | File dexDir = activity.getDir("dex", Context.MODE_PRIVATE);
|
84 | File dexFile; |
85 | do {
|
86 | dexFile = new File(dexDir, System.currentTimeMillis() + ".dex"); |
87 | } while (dexFile.exists()); |
88 | |
89 | File dexOutputDir; |
90 | do {
|
91 | dexOutputDir = activity.getDir("dex-optimized-" + System.currentTimeMillis(), Context.MODE_PRIVATE);
|
92 | } while (dexOutputDir.list().length != 0); |
93 | |
94 | FileOutputStream fileOutputStream = new FileOutputStream(dexFile); |
95 | fileOutputStream.write(dexData); |
96 | fileOutputStream.close(); |
97 | |
98 | ClassLoader parentClassLoader = |
99 | //ClassLoader.getSystemClassLoader(); // does not find support jar |
100 | //getClass().getClassLoader(); // Let's try this... |
101 | getClass().getClassLoader().getParent(); // XXX ! |
102 | DexClassLoader classLoader = new DexClassLoader(dexFile.getAbsolutePath(), dexOutputDir.getAbsolutePath(), null, |
103 | parentClassLoader); |
104 | Class<?> theClass = classLoader.loadClass(mainClassName); |
105 | return theClass; |
106 | } |
107 | |
108 | private boolean isDex(byte[] dexData) {
|
109 | if (dexData.length < DEX_FILE_MAGIC.length) return false; |
110 | for (int i = 0; i < DEX_FILE_MAGIC.length; i++) |
111 | if (dexData[i] != DEX_FILE_MAGIC[i]) |
112 | return false; |
113 | return true; |
114 | } |
115 | |
116 | private void showError(Throwable e) {
|
117 | ScrollView scrollView = new ScrollView(activity); |
118 | |
119 | TextView errorView = new TextView(activity); |
120 | errorView.setText(info + "\n" + getStackTrace(e)); |
121 | scrollView.addView(errorView); |
122 | |
123 | activity.setContentView(scrollView); |
124 | } |
125 | |
126 | public static String getStackTrace(Throwable throwable) {
|
127 | StringWriter writer = new StringWriter(); |
128 | throwable.printStackTrace(new PrintWriter(writer)); |
129 | return writer.toString(); |
130 | } |
131 | |
132 | private class DownloadFilesTask extends AsyncTask<URL, Integer, Class<?>> {
|
133 | volatile Throwable error; |
134 | URL url; |
135 | |
136 | protected Class<?> doInBackground(URL... urls) {
|
137 | try {
|
138 | url = urls[0]; |
139 | return runDynamic(url); |
140 | } catch (Throwable e) {
|
141 | error = e; |
142 | return null; |
143 | } |
144 | } |
145 | |
146 | protected void onProgressUpdate(Integer... progress) {
|
147 | //setProgressPercent(progress[0]); |
148 | } |
149 | |
150 | protected void onPostExecute(Class<?> theClass) {
|
151 | try {
|
152 | if (error != null) |
153 | showError(error); |
154 | else if (theClass != null) {
|
155 | Method run = findMainMethod(theClass); |
156 | Object result = run.invoke(null, activity); |
157 | |
158 | if (result instanceof Fragment) {
|
159 | FragmentManager fm = activity.getSupportFragmentManager(); |
160 | android.support.v4.app.Fragment fragment = fm.findFragmentByTag("mainFragment");
|
161 | if (fragment == null) {
|
162 | android.support.v4.app.FragmentTransaction ft = fm.beginTransaction(); |
163 | fragment = (Fragment) result; |
164 | ft.add(android.R.id.content, fragment, "mainFragment"); |
165 | ft.commit(); |
166 | } |
167 | } else if (result instanceof View) {
|
168 | activity.setContentView((View) result); |
169 | } else |
170 | showError(new Throwable("Bad return value from " + url + ", expected View or Fragment: " + result));
|
171 | } else |
172 | showError(new Throwable("What?"));
|
173 | } catch (Throwable e) {
|
174 | showError(e); |
175 | } |
176 | } |
177 | } |
178 | |
179 | static Method findMainMethod(Class<?> theClass) {
|
180 | for (Method method : theClass.getMethods()) |
181 | if (method.getName().equals(mainMethodName) && method.getParameterTypes().length == 1) |
182 | return method; |
183 | throw new RuntimeException("Method " + mainMethodName + " with 1 paramter not found in " + theClass.getName());
|
184 | } |
185 | |
186 | public static byte[] loadBinaryPage(URLConnection con) throws IOException {
|
187 | //setHeaders(con); |
188 | ByteArrayOutputStream buf = new ByteArrayOutputStream(); |
189 | InputStream inputStream = con.getInputStream(); |
190 | while (true) {
|
191 | int ch = inputStream.read(); |
192 | if (ch < 0) |
193 | break; |
194 | buf.write(ch); |
195 | } |
196 | inputStream.close(); |
197 | return buf.toByteArray(); |
198 | } |
199 | |
200 | } |
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: | 851 / 814 |
| Referenced in: | [show references] |