38
38
import android .view .inputmethod .InputMethodManager ;
39
39
import android .widget .Toast ;
40
40
41
- import androidx .annotation .NonNull ;
42
41
import androidx .core .app .ActivityCompat ;
43
42
import androidx .core .content .ContextCompat ;
44
43
import androidx .core .content .FileProvider ;
@@ -95,10 +94,10 @@ public class MainActivity extends NativeActivity {
95
94
private static final int BASE_FONT_SIZE = 18 ;
96
95
private static final long LOCATION_INTERVAL = 1000 ;
97
96
private static final float LOCATION_DISTANCE = 1 ;
98
- private static final int REQUEST_STORAGE_PERMISSION = 1 ;
99
97
private static final int REQUEST_LOCATION_PERMISSION = 2 ;
100
98
private static final String FOLDER_NAME = "SmallBASIC" ;
101
99
private static final int COPY_BUFFER_SIZE = 1024 ;
100
+ private static final String [] SAMPLES = {"welcome.bas" };
102
101
private String _startupBas = null ;
103
102
private boolean _untrusted = false ;
104
103
private final ExecutorService _audioExecutor = Executors .newSingleThreadExecutor ();
@@ -254,6 +253,18 @@ public void run() {
254
253
return result ;
255
254
}
256
255
256
+ public String getExternalStorage () {
257
+ String result = null ;
258
+ File files = getExternalFilesDir (null );
259
+ if (files != null ) {
260
+ String externalFiles = files .getAbsolutePath ();
261
+ if (isPublicStorage (externalFiles )) {
262
+ result = externalFiles ;
263
+ }
264
+ }
265
+ return result ;
266
+ }
267
+
257
268
public String getIpAddress () {
258
269
String result = "" ;
259
270
try {
@@ -397,16 +408,6 @@ public boolean onPrepareOptionsMenu(Menu menu) {
397
408
return super .onPrepareOptionsMenu (menu );
398
409
}
399
410
400
- @ Override
401
- public void onRequestPermissionsResult (int requestCode ,
402
- @ NonNull String [] permissions ,
403
- @ NonNull int [] grantResults ) {
404
- super .onRequestPermissionsResult (requestCode , permissions , grantResults );
405
- if (requestCode == REQUEST_STORAGE_PERMISSION && grantResults [0 ] != PackageManager .PERMISSION_DENIED ) {
406
- setupStorageEnvironment (true );
407
- }
408
- }
409
-
410
411
public void optionsBox (final String [] items ) {
411
412
this ._options = items ;
412
413
runOnUiThread (new Runnable () {
@@ -448,10 +449,10 @@ public void run() {
448
449
}).start ();
449
450
}
450
451
451
- public void playTone (int frq , int dur , int vol , boolean bgplay ) {
452
+ public void playTone (int frq , int dur , int vol , boolean backgroundPlay ) {
452
453
float volume = (vol / 100f );
453
454
final Sound sound = new Sound (frq , dur , volume );
454
- if (bgplay ) {
455
+ if (backgroundPlay ) {
455
456
_sounds .add (sound );
456
457
_audioExecutor .execute (new Runnable () {
457
458
@ Override
@@ -641,7 +642,8 @@ protected void onCreate(Bundle savedInstanceState) {
641
642
super .onCreate (savedInstanceState );
642
643
processIntent ();
643
644
processSettings ();
644
- checkFilePermission ();
645
+ String homeFolder = setupStorageEnvironment ();
646
+ installSamples (homeFolder );
645
647
}
646
648
647
649
@ Override
@@ -669,21 +671,6 @@ protected void onStop() {
669
671
}
670
672
}
671
673
672
- private void checkFilePermission () {
673
- if (!permitted (Manifest .permission .WRITE_EXTERNAL_STORAGE )) {
674
- setupStorageEnvironment (false );
675
- Runnable handler = new Runnable () {
676
- @ Override
677
- public void run () {
678
- checkPermission (Manifest .permission .WRITE_EXTERNAL_STORAGE , REQUEST_STORAGE_PERMISSION );
679
- }
680
- };
681
- new Handler ().postDelayed (handler , 250 );
682
- } else {
683
- setupStorageEnvironment (true );
684
- }
685
- }
686
-
687
674
private void checkPermission (final String permission , final int result ) {
688
675
runOnUiThread (new Runnable () {
689
676
@ Override
@@ -711,18 +698,6 @@ private void copy(File src, File dst) throws IOException {
711
698
copy (new FileInputStream (src ), new FileOutputStream (dst ));
712
699
}
713
700
714
- private String execBuffer (final String buffer , final String name , boolean run ) throws IOException {
715
- File outputFile = new File (getInternalStorage (), name );
716
- BufferedWriter output = new BufferedWriter (new FileWriter (outputFile ));
717
- output .write (buffer );
718
- output .close ();
719
- if (run ) {
720
- Log .i (TAG , "invoke runFile: " + outputFile .getAbsolutePath ());
721
- runFile (outputFile .getAbsolutePath ());
722
- }
723
- return outputFile .getAbsolutePath ();
724
- }
725
-
726
701
private void execScheme (final String data ) {
727
702
try {
728
703
String input = data .substring (SCHEME .length ());
@@ -742,7 +717,7 @@ private void execScheme(final String data) {
742
717
} else {
743
718
bas = URLDecoder .decode (input , "utf-8" );
744
719
}
745
- _startupBas = execBuffer (bas , SCHEME_BAS , false );
720
+ _startupBas = saveSchemeData (bas );
746
721
_untrusted = true ;
747
722
} catch (IOException e ) {
748
723
Log .i (TAG , "saveSchemeData failed: " , e );
@@ -763,7 +738,11 @@ private void execStream(InputStream inputStream) throws IOException {
763
738
runFile (outputFile .getAbsolutePath ());
764
739
}
765
740
766
- private String getExternalStorage () {
741
+ private String getInternalStorage () {
742
+ return getFilesDir ().getAbsolutePath ();
743
+ }
744
+
745
+ private String getLegacyStorage () {
767
746
String result ;
768
747
String path = Environment .getExternalStorageDirectory ().getAbsolutePath ();
769
748
if (isPublicStorage (path )) {
@@ -773,18 +752,23 @@ private String getExternalStorage() {
773
752
} else {
774
753
result = path ;
775
754
}
776
- } else if (android .os .Build .VERSION .SDK_INT >= Build .VERSION_CODES .LOLLIPOP ) {
777
- // https://commonsware.com/blog/2019/06/07/death-external-storage-end-saga.html
778
- File [] dirs = getExternalMediaDirs ();
779
- result = dirs != null && dirs .length > 0 ? dirs [0 ].getAbsolutePath () : getInternalStorage ();
780
755
} else {
781
- result = getInternalStorage () ;
756
+ result = null ;
782
757
}
783
758
return result ;
784
759
}
785
760
786
- private String getInternalStorage () {
787
- return getFilesDir ().getAbsolutePath ();
761
+ private String getMediaStorage () {
762
+ String result = null ;
763
+ if (android .os .Build .VERSION .SDK_INT >= Build .VERSION_CODES .LOLLIPOP ) {
764
+ // https://commonsware.com/blog/2019/06/07/death-external-storage-end-saga.html
765
+ File [] dirs = getExternalMediaDirs ();
766
+ String path = dirs != null && dirs .length > 0 ? dirs [0 ].getAbsolutePath () : null ;
767
+ if (isPublicStorage (path )) {
768
+ result = path ;
769
+ }
770
+ }
771
+ return result ;
788
772
}
789
773
790
774
private Uri getSharedFile (File file ) {
@@ -813,6 +797,20 @@ private String getString(final byte[] bytes) {
813
797
}
814
798
}
815
799
800
+ private void installSamples (String toDir ) {
801
+ File [] toFiles = new File (toDir ).listFiles (new BasFileFilter ());
802
+ if (toFiles == null || toFiles .length == 0 ) {
803
+ // only attempt with a clean destination folder
804
+ try {
805
+ for (String sample : SAMPLES ) {
806
+ copy (getAssets ().open ("samples/" + sample ), new FileOutputStream (new File (toDir , sample )));
807
+ }
808
+ } catch (IOException e ) {
809
+ Log .d (TAG , "Failed to copy sample: " , e );
810
+ }
811
+ }
812
+ }
813
+
816
814
private boolean isPublicStorage (String dir ) {
817
815
boolean result ;
818
816
if (dir == null || dir .isEmpty ()) {
@@ -824,27 +822,6 @@ private boolean isPublicStorage(String dir) {
824
822
return result ;
825
823
}
826
824
827
- private void migrateFiles (File fromDir , File toDir ) {
828
- FilenameFilter filter = new FilenameFilter () {
829
- @ Override
830
- public boolean accept (File dir , String name ) {
831
- return name != null && name .endsWith (".bas" );
832
- }
833
- };
834
- File [] toFiles = toDir .listFiles (filter );
835
- File [] fromFiles = fromDir .listFiles (filter );
836
- if (fromFiles != null && (toFiles == null || toFiles .length == 0 )) {
837
- // only attempt file copy into a clean destination folder
838
- for (File file : fromFiles ) {
839
- try {
840
- copy (file , new File (toDir , file .getName ()));
841
- } catch (IOException e ) {
842
- Log .d (TAG , "failed to copy: " , e );
843
- }
844
- }
845
- }
846
- }
847
-
848
825
private boolean permitted (String permission ) {
849
826
return (ContextCompat .checkSelfPermission (this , permission ) == PackageManager .PERMISSION_GRANTED );
850
827
}
@@ -921,21 +898,26 @@ private String readLine(InputStream inputReader) throws IOException {
921
898
return b == -1 ? null : out .size () == 0 ? "" : out .toString ();
922
899
}
923
900
924
- private void setupStorageEnvironment (boolean external ) {
901
+ private String saveSchemeData (final String buffer ) throws IOException {
902
+ File outputFile = new File (getInternalStorage (), SCHEME_BAS );
903
+ BufferedWriter output = new BufferedWriter (new FileWriter (outputFile ));
904
+ output .write (buffer );
905
+ output .close ();
906
+ return outputFile .getAbsolutePath ();
907
+ }
908
+
909
+ private String setupStorageEnvironment () {
925
910
setenv ("INTERNAL_DIR" , getInternalStorage ());
926
- if (external ) {
927
- String externalDir = getExternalStorage ();
928
- File files = getExternalFilesDir (null );
929
- if (files != null ) {
930
- String externalFiles = files .getAbsolutePath ();
931
- if (!externalDir .equals (externalFiles ) && isPublicStorage (externalFiles )) {
932
- migrateFiles (new File (externalDir ), files );
933
- setenv ("LEGACY_DIR" , externalDir );
934
- externalDir = externalFiles ;
935
- }
936
- }
937
- setenv ("EXTERNAL_DIR" , externalDir );
911
+ setenv ("LEGACY_DIR" , getMediaStorage ());
912
+ String legacyStorage = getLegacyStorage ();
913
+ String externalStorage ;
914
+ if (isPublicStorage (legacyStorage )) {
915
+ externalStorage = legacyStorage ;
916
+ } else {
917
+ externalStorage = getExternalStorage ();
938
918
}
919
+ setenv ("EXTERNAL_DIR" , externalStorage );
920
+ return externalStorage ;
939
921
}
940
922
941
923
private static class BasFileFilter implements FilenameFilter {
@@ -963,6 +945,9 @@ protected Response getFile(String path, boolean asset) throws IOException {
963
945
result = new Response (getAssets ().open (name ), length );
964
946
} else {
965
947
File file = getFile (getExternalStorage (), path );
948
+ if (file == null ) {
949
+ file = getFile (getMediaStorage (), path );
950
+ }
966
951
if (file == null ) {
967
952
file = getFile (getInternalStorage (), path );
968
953
}
@@ -979,6 +964,7 @@ protected Response getFile(String path, boolean asset) throws IOException {
979
964
protected Collection <FileData > getFileData () throws IOException {
980
965
Collection <FileData > result = new ArrayList <>();
981
966
result .addAll (getFiles (new File (getExternalStorage ())));
967
+ result .addAll (getFiles (new File (getMediaStorage ())));
982
968
result .addAll (getFiles (new File (getInternalStorage ())));
983
969
return result ;
984
970
}
@@ -1009,6 +995,9 @@ protected void renameFile(String from, String to) throws IOException {
1009
995
if (fromFile == null ) {
1010
996
fromFile = getFile (getExternalStorage (), from );
1011
997
}
998
+ if (fromFile == null ) {
999
+ fromFile = getFile (getInternalStorage (), from );
1000
+ }
1012
1001
if (fromFile == null ) {
1013
1002
throw new IOException ("Previous file does not exist" );
1014
1003
}
0 commit comments