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: | 605 / 559 |
Referenced in: | [show references] |