6
6
import android .net .Uri ;
7
7
import android .os .Bundle ;
8
8
import android .os .Environment ;
9
+ import android .os .Handler ;
10
+ import android .os .Looper ;
9
11
import android .util .Base64 ;
10
12
import android .util .Log ;
11
13
import android .view .View ;
16
18
import android .webkit .WebSettings ;
17
19
import android .webkit .WebView ;
18
20
import android .webkit .WebViewClient ;
21
+ import android .widget .Toast ;
19
22
20
23
import com .samsung .microbit .BuildConfig ;
21
24
import com .samsung .microbit .R ;
25
+ import com .samsung .microbit .utils .FileUtils ;
22
26
import com .samsung .microbit .utils .ProjectsHelper ;
23
27
24
28
import java .io .File ;
@@ -40,10 +44,11 @@ public class MakeCodeWebView extends Activity implements View.OnClickListener {
40
44
public static String makecodeUrl = "https://makecode.microbit.org/?androidapp=" + BuildConfig .VERSION_CODE ;
41
45
public static Activity activityHandle = null ;
42
46
43
- Uri hexToFlash ;
47
+ boolean projectDownload = false ;
44
48
45
49
private static final int REQUEST_CODE_SAVEDATA = 1 ;
46
50
private static final int REQUEST_CODE_CHOOSE_FILE = 2 ;
51
+ private static final int REQUEST_CODE_FLASH = 3 ;
47
52
private byte [] dataToSave = null ;
48
53
private ValueCallback <Uri []> onShowFileChooser_filePathCallback ;
49
54
@@ -81,15 +86,9 @@ protected void onCreate(Bundle savedInstanceState) {
81
86
webSettings .setBuiltInZoomControls (true );
82
87
webSettings .setDisplayZoomControls (false );
83
88
webSettings .setDomStorageEnabled (true );
84
- webView .setWebContentsDebuggingEnabled (true );
89
+ WebView .setWebContentsDebuggingEnabled (false );
85
90
86
91
webView .addJavascriptInterface (new JavaScriptInterface (this ), "AndroidFunction" );
87
- webView .evaluateJavascript ("javascript:(function f() { document.getElementsByClassName(\" brand\" )[0].addEventListener(\" click\" , function(e) { AndroidFunction.returnToHome(); e.preventDefault(); return false; }) })()" , new ValueCallback <String >() {
88
- @ Override
89
- public void onReceiveValue (String s ) {
90
- Log .d (TAG , s );
91
- }
92
- });
93
92
94
93
webView .setWebViewClient (new WebViewClient () {
95
94
@ Override
@@ -104,6 +103,13 @@ public void onLoadResource(WebView view, String url) {
104
103
super .onLoadResource (view , url );
105
104
Log .v (TAG , "onLoadResource(" + url + ");" );
106
105
}
106
+
107
+ @ Override
108
+ public void onPageFinished (WebView view , String url ) {
109
+ super .onPageFinished (view , url );
110
+ Log .v (TAG , "onPageFinished(" + url + ");" );
111
+ onPageFinishedJS ( view , url );
112
+ }
107
113
}); //setWebViewClient
108
114
109
115
webView .setWebChromeClient (new WebChromeClient () {
@@ -194,40 +200,49 @@ public void onReceiveValue(String s) {
194
200
else if ( !hexName .isEmpty ()) {
195
201
hexToWrite = getProjectFile (hexName );
196
202
197
- /*
198
- // Append n to file until it doesn't exist
199
- int i = 0;
200
-
201
- while (hexToWrite.exists()) {
202
- hexName = hexName.replaceAll("-?\\d*\\.","-" + i + ".");
203
- hexToWrite = getProjectFile( hexName);
204
- i++;
203
+ // // Replace existing file rather than creating *-n.hex
204
+ // // Append n to file until it doesn't exist
205
+ // int i = 0;
206
+ //
207
+ // while (hexToWrite.exists()) {
208
+ // hexName = hexName.replaceAll("-?\\d*\\.","-" + i + ".");
209
+ // hexToWrite = getProjectFile( hexName);
210
+ // i++;
211
+ // }
212
+
213
+ if ( !FileUtils .writeBytesToFile ( hexToWrite , decode )) {
214
+ ProjectsHelper .importToProjectsToast (
215
+ ProjectsHelper .enumImportResult .WriteFailed , MakeCodeWebView .this );
216
+ return ;
205
217
}
206
- */
207
- // Replace existing file rather than creating *-n.hex
208
- if (hexToWrite .exists ()) {
209
- hexToWrite .delete ();
210
- }
211
-
212
- // Create file
213
- hexToWrite .createNewFile ();
214
- outputStream = new FileOutputStream (hexToWrite );
215
- outputStream .write (decode );
216
- outputStream .flush ();
217
218
218
- // Get file path
219
- hexToFlash = Uri . fromFile ( hexToWrite ) ;
219
+ boolean download = projectDownload ;
220
+ projectDownload = false ;
220
221
221
- openProjectActivity ();
222
+ if ( download ) {
223
+ openProjectActivity ( hexToWrite );
224
+ } else {
225
+ Toast .makeText ( MakeCodeWebView .this ,
226
+ "Saved to FLASH page" , Toast .LENGTH_LONG ).show ();
227
+ }
222
228
}
223
- } catch (IOException e ) {
229
+ } catch ( Exception e ) {
224
230
e .printStackTrace ();
225
231
}
226
232
}
227
233
}); // setDownloadListener
228
234
229
235
//Check parameters Before load
230
236
Intent intent = getIntent ();
237
+
238
+ boolean importExtra = intent .getBooleanExtra ("import" , false );
239
+ if ( importExtra ) {
240
+ importInitialise ();
241
+ } else {
242
+ importHex = null ;
243
+ importName = null ;
244
+ }
245
+
231
246
webView .loadUrl (makecodeUrl );
232
247
} // onCreate
233
248
@@ -244,27 +259,22 @@ private void saveData( String name, String mimetype, byte[] data) {
244
259
protected void onActivityResult (int requestCode , int resultCode , Intent data ) {
245
260
super .onActivityResult (requestCode , resultCode , data );
246
261
247
- if ( requestCode == REQUEST_CODE_SAVEDATA ) {
262
+ if ( requestCode == REQUEST_CODE_FLASH ) {
263
+ if ( resultCode != RESULT_OK ) {
264
+ return ;
265
+ }
266
+ } else if ( requestCode == REQUEST_CODE_SAVEDATA ) {
248
267
if ( resultCode != RESULT_OK ) {
249
268
dataToSave = null ;
250
269
return ;
251
270
}
252
- OutputStream os = null ;
253
- try {
254
- os = getContentResolver ().openOutputStream ( data .getData ());
255
- if ( dataToSave != null && dataToSave .length > 0 ) {
256
- os .write (dataToSave , 0 , dataToSave .length );
271
+ if ( dataToSave != null && dataToSave .length > 0 ) {
272
+ Uri uri = data .getData ();
273
+ if ( !FileUtils .writeBytesToUri ( uri , dataToSave , this )) {
274
+ Toast .makeText (this , "Could not save file" , Toast .LENGTH_LONG ).show ();
257
275
}
258
- } catch (IOException e ) {
259
- e .printStackTrace ();
260
- } finally {
261
- try {
262
- dataToSave = null ;
263
- if ( os != null ) {
264
- os .close ();
265
- }
266
- } catch (IOException e ) { }
267
276
}
277
+ dataToSave = null ;
268
278
} else if (requestCode == REQUEST_CODE_CHOOSE_FILE ) {
269
279
if ( resultCode != RESULT_OK ) {
270
280
onShowFileChooser_filePathCallback .onReceiveValue ( null );
@@ -295,27 +305,169 @@ public void onClick(final View v) {
295
305
}
296
306
}
297
307
298
- void openProjectActivity () {
308
+ public final static String ACTION_FLASH = "com.samsung.microbit.ACTION_FLASH" ;
309
+
310
+ void openProjectActivity ( File hexToWrite ) {
299
311
Intent i = new Intent (this , ProjectActivity .class );
300
- i .setData (hexToFlash );
301
- startActivity (i );
312
+ i .setAction ( ACTION_FLASH );
313
+ i .putExtra ("path" , hexToWrite .getAbsolutePath ());
314
+ startActivityForResult ( i , REQUEST_CODE_FLASH );
315
+ }
316
+
317
+ public static String importHex = null ;
318
+ public static String importName = null ;
319
+ private boolean importPosting = false ;
320
+ Handler importHandler = null ;
321
+
322
+ private void importInitialise () {
323
+ if ( importHex != null ) {
324
+ importHex = importHex .replaceAll ("\r \n " , "\\ \\ n" );
325
+ importHex = importHex .replaceAll ("\r " , "\\ \\ n" );
326
+ importHex = importHex .replaceAll ("\n " , "\\ \\ n" );
327
+
328
+ //TODO - does MakeCode signal when ready?
329
+ Looper looper = Looper .getMainLooper ();
330
+ importHandler = new Handler (looper );
331
+ importHandler .postDelayed (importCallback , 2000 );
332
+ }
333
+ }
334
+ private final Runnable importCallback = new Runnable () {
335
+ @ Override
336
+ public void run () {
337
+ if ( importHex != null ) {
338
+ importPostMessage ();
339
+ importHandler .postDelayed ( importCallback , 1000 );
340
+ } else {
341
+ importHandler .removeCallbacks ( importCallback );
342
+ importHandler = null ;
343
+ }
344
+ }
345
+ };
346
+
347
+ public void importPostMessage () {
348
+ Log .d (TAG , "importPostMessage" );
349
+
350
+ if ( importHex == null ) {
351
+ return ;
352
+ }
353
+ if ( importPosting ) {
354
+ return ;
355
+ }
356
+ if ( webView == null ) {
357
+ return ;
358
+ }
359
+ if ( importName == null || importName .isEmpty ()) {
360
+ importName = "import.hex" ;
361
+ }
362
+
363
+ importPosting = true ;
364
+
365
+ StringBuilder sb = new StringBuilder ();
366
+ String nl = "\n " ;
367
+ sb .append ( "javascript:(" );
368
+ sb .append (nl ).append ("function f() {" );
369
+ sb .append (nl ).append ( "var ret = 'OK'" );
370
+ sb .append (nl ).append ( "try {" );
371
+ sb .append (nl ).append ( "var loading = document.getElementById('loading')" );
372
+ sb .append (nl ).append ( "if ( loading && loading.parentElement) {" );
373
+ sb .append (nl ).append ( "ret = 'loading'" );
374
+ sb .append (nl ).append ( "} else {" );
375
+ sb .append (nl ).append ( "var name = '" ).append (importName ).append ("'" );
376
+ sb .append (nl ).append ( "var hex = '" ).append (importHex ).append ("'" );
377
+ sb .append (nl ).append ( "var msg = {" );
378
+ sb .append (nl ).append ( "type: 'importfile'," );
379
+ sb .append (nl ).append ( "filename: name," );
380
+ sb .append (nl ).append ( "parts: [ hex ]" );
381
+ sb .append (nl ).append ( "}" );
382
+ sb .append (nl ).append ( "window.postMessage( msg, '*')" );
383
+ sb .append (nl ).append ( "}" );
384
+ sb .append (nl ).append ( "} catch( err) {" );
385
+ sb .append (nl ).append ( "ret = err.message" );
386
+ sb .append (nl ).append ( "}" );
387
+ sb .append (nl ).append ( "return ret" );
388
+ sb .append (nl ).append ("}" );
389
+ sb .append (nl ).append (")()" );
390
+
391
+ webView .evaluateJavascript ( sb .toString (), new ValueCallback <String >() {
392
+ @ Override
393
+ public void onReceiveValue (String s ) {
394
+ Log .i (TAG , "importPostMessage: " + s );
395
+ String loading = "\" loading\" " ;
396
+ String ok = "\" OK\" " ;
397
+ if ( s .equals ( ok )) {
398
+ importHex = null ;
399
+ } else if ( !s .equals ( loading )) {
400
+ }
401
+ }
402
+ });
403
+ importPosting = false ;
302
404
}
303
- }
405
+
406
+ public void onPageFinishedJS ( WebView view , String url ) {
407
+ Log .v (TAG , "addListeners(" + url + ");" );
408
+
409
+ StringBuilder sb = new StringBuilder ();
410
+ String nl = "\n " ;
411
+ sb .append ( "javascript:(" );
412
+ sb .append (nl ).append ("function f() {" );
413
+ sb .append (nl ).append ( "var ret = 'OK'" );
414
+ sb .append (nl ).append ( "try {" );
415
+ sb .append (nl ).append ( "var brands = document.getElementsByClassName(\" brand\" )" );
416
+ sb .append (nl ).append ( "for (let i = 0; brands != null && i < brands.length; i++) {" );
417
+ sb .append (nl ).append ( "brands[i].addEventListener(\" click\" ," );
418
+ sb .append (nl ).append ( "function(e) {" );
419
+ sb .append (nl ).append ( "AndroidFunction.clickBrand();" );
420
+ sb .append (nl ).append ( "e.preventDefault();" );
421
+ sb .append (nl ).append ( "return false;" );
422
+ sb .append (nl ).append ( "})" );
423
+ sb .append (nl ).append ( "}" );
424
+ sb .append (nl ).append ( "var downs = document.getElementsByClassName(\" download-button\" )" );
425
+ sb .append (nl ).append ( "for (let i = 0; downs != null && i < downs.length; i++) {" );
426
+ sb .append (nl ).append ( "downs[i].addEventListener(\" click\" ," );
427
+ sb .append (nl ).append ( "function(e) {" );
428
+ sb .append (nl ).append ( "AndroidFunction.clickDownload();" );
429
+ sb .append (nl ).append ( "e.preventDefault();" );
430
+ sb .append (nl ).append ( "return false;" );
431
+ sb .append (nl ).append ( "})" );
432
+ sb .append (nl ).append ( "}" );
433
+ sb .append (nl ).append ( "} catch( err) {" );
434
+ sb .append (nl ).append ( "ret = err.message" );
435
+ sb .append (nl ).append ( "}" );
436
+ sb .append (nl ).append ( "return ret" );
437
+ sb .append (nl ).append ("}" );
438
+ sb .append (nl ).append (")()" );
439
+
440
+ webView .evaluateJavascript ( sb .toString (), new ValueCallback <String >() {
441
+ @ Override
442
+ public void onReceiveValue (String s ) {
443
+ Log .d (TAG , s );
444
+ }
445
+ });
446
+ }}
304
447
305
448
/* Javascript Interface */
306
449
class JavaScriptInterface {
307
- Context mContext ;
450
+ MakeCodeWebView mContext ;
308
451
309
- JavaScriptInterface (Context c ) {
452
+ JavaScriptInterface ( MakeCodeWebView c ) {
310
453
mContext = c ;
311
454
}
312
455
313
456
@ JavascriptInterface
314
- public void returnToHome () {
457
+ public void clickBrand () {
315
458
try {
316
459
MakeCodeWebView .activityHandle .finish ();
317
460
} catch (Exception e ) {
318
461
Log .v (TAG , e .toString ());
319
462
}
320
463
}
464
+
465
+ @ JavascriptInterface
466
+ public void clickDownload () {
467
+ try {
468
+ mContext .projectDownload = true ;
469
+ } catch (Exception e ) {
470
+ Log .v (TAG , e .toString ());
471
+ }
472
+ }
321
473
}
0 commit comments