Skip to content

Commit 5e53c34

Browse files
committed
ANDROID: update storage handling
1 parent ec231c8 commit 5e53c34

File tree

2 files changed

+100
-90
lines changed

2 files changed

+100
-90
lines changed

src/platform/android/app/src/main/java/net/sourceforge/smallbasic/MainActivity.java

Lines changed: 94 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ public class MainActivity extends NativeActivity {
107107
private MediaPlayer _mediaPlayer = null;
108108
private LocationAdapter _locationAdapter = null;
109109
private TextToSpeechAdapter _tts;
110+
private Storage _storage;
110111

111112
static {
112113
System.loadLibrary("smallbasic");
@@ -254,18 +255,6 @@ public void run() {
254255
return result;
255256
}
256257

257-
public String getExternalStorage() {
258-
String result = null;
259-
File files = getExternalFilesDir(null);
260-
if (files != null) {
261-
String externalFiles = files.getAbsolutePath();
262-
if (isPublicStorage(externalFiles)) {
263-
result = externalFiles;
264-
}
265-
}
266-
return result;
267-
}
268-
269258
public String getIpAddress() {
270259
String result = "";
271260
try {
@@ -291,7 +280,7 @@ public String getIpAddress() {
291280
@SuppressLint("MissingPermission")
292281
public String getLocation() {
293282
StringBuilder result = new StringBuilder("{");
294-
if (permitted(Manifest.permission.ACCESS_FINE_LOCATION)) {
283+
if (locationPermitted()) {
295284
LocationManager locationService = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
296285
Location location = _locationAdapter != null ? _locationAdapter.getLocation() : null;
297286
if (locationService != null) {
@@ -485,7 +474,7 @@ public boolean removeLocationUpdates() {
485474
public boolean requestLocationUpdates() {
486475
final LocationManager locationService = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
487476
boolean result = false;
488-
if (!permitted(Manifest.permission.ACCESS_FINE_LOCATION)) {
477+
if (!locationPermitted()) {
489478
checkPermission(Manifest.permission.ACCESS_FINE_LOCATION, REQUEST_LOCATION_PERMISSION);
490479
} else if (locationService != null) {
491480
final Criteria criteria = new Criteria();
@@ -641,11 +630,11 @@ public void speak(final byte[] textBytes) {
641630
@Override
642631
protected void onCreate(Bundle savedInstanceState) {
643632
super.onCreate(savedInstanceState);
644-
String homeFolder = setupStorageEnvironment();
633+
setupStorageEnvironment();
645634
if (!libraryMode()) {
646635
processIntent();
647636
processSettings();
648-
installSamples(homeFolder);
637+
installSamples();
649638
}
650639
}
651640

@@ -728,7 +717,7 @@ private void execScheme(final String data) {
728717
}
729718

730719
private void execStream(InputStream inputStream) throws IOException {
731-
File outputFile = new File(getInternalStorage(), WEB_BAS);
720+
File outputFile = new File(_storage.getInternal(), WEB_BAS);
732721
BufferedWriter output = new BufferedWriter(new FileWriter(outputFile));
733722
Log.i(TAG, "execStream() entered");
734723
String line = readLine(inputStream);
@@ -741,39 +730,6 @@ private void execStream(InputStream inputStream) throws IOException {
741730
runFile(outputFile.getAbsolutePath());
742731
}
743732

744-
private String getInternalStorage() {
745-
return getFilesDir().getAbsolutePath();
746-
}
747-
748-
private String getLegacyStorage() {
749-
String result;
750-
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
751-
if (isPublicStorage(path)) {
752-
File sb = new File(path, FOLDER_NAME);
753-
if ((sb.isDirectory() && sb.canWrite()) || sb.mkdirs()) {
754-
result = path + "/" + FOLDER_NAME;
755-
} else {
756-
result = path;
757-
}
758-
} else {
759-
result = null;
760-
}
761-
return result;
762-
}
763-
764-
private String getMediaStorage() {
765-
String result = null;
766-
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
767-
// https://commonsware.com/blog/2019/06/07/death-external-storage-end-saga.html
768-
File[] dirs = getExternalMediaDirs();
769-
String path = dirs != null && dirs.length > 0 ? dirs[0].getAbsolutePath() : null;
770-
if (isPublicStorage(path)) {
771-
result = path;
772-
}
773-
}
774-
return result;
775-
}
776-
777733
private Uri getSharedFile(File file) {
778734
Uri result;
779735
try {
@@ -800,7 +756,8 @@ private String getString(final byte[] bytes) {
800756
}
801757
}
802758

803-
private void installSamples(String toDir) {
759+
private void installSamples() {
760+
String toDir = _storage.getExternal();
804761
File[] toFiles = new File(toDir).listFiles(new BasFileFilter());
805762
if (toFiles == null || toFiles.length == 0) {
806763
// only attempt with a clean destination folder
@@ -814,18 +771,8 @@ private void installSamples(String toDir) {
814771
}
815772
}
816773

817-
private boolean isPublicStorage(String dir) {
818-
boolean result;
819-
if (dir == null || dir.isEmpty()) {
820-
result = false;
821-
} else {
822-
File file = new File(dir);
823-
result = file.isDirectory() && file.canRead() && file.canWrite();
824-
}
825-
return result;
826-
}
827-
828-
private boolean permitted(String permission) {
774+
private boolean locationPermitted() {
775+
String permission = Manifest.permission.ACCESS_FINE_LOCATION;
829776
return (ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED);
830777
}
831778

@@ -902,25 +849,18 @@ private String readLine(InputStream inputReader) throws IOException {
902849
}
903850

904851
private String saveSchemeData(final String buffer) throws IOException {
905-
File outputFile = new File(getInternalStorage(), SCHEME_BAS);
852+
File outputFile = new File(_storage.getInternal(), SCHEME_BAS);
906853
BufferedWriter output = new BufferedWriter(new FileWriter(outputFile));
907854
output.write(buffer);
908855
output.close();
909856
return outputFile.getAbsolutePath();
910857
}
911858

912-
private String setupStorageEnvironment() {
913-
setenv("INTERNAL_DIR", getInternalStorage());
914-
setenv("LEGACY_DIR", getMediaStorage());
915-
String legacyStorage = getLegacyStorage();
916-
String externalStorage;
917-
if (isPublicStorage(legacyStorage)) {
918-
externalStorage = legacyStorage;
919-
} else {
920-
externalStorage = getExternalStorage();
921-
}
922-
setenv("EXTERNAL_DIR", externalStorage);
923-
return externalStorage;
859+
private void setupStorageEnvironment() {
860+
_storage = new Storage();
861+
setenv("EXTERNAL_DIR", _storage.getExternal());
862+
setenv("INTERNAL_DIR", _storage.getInternal());
863+
setenv("LEGACY_DIR", _storage.getMedia());
924864
}
925865

926866
private static class BasFileFilter implements FilenameFilter {
@@ -930,6 +870,71 @@ public boolean accept(File dir, String name) {
930870
}
931871
}
932872

873+
private final class Storage {
874+
private final String _external;
875+
private final String _internal;
876+
private final String _media;
877+
878+
private Storage() {
879+
String external = null;
880+
String media = null;
881+
882+
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
883+
if (isPublicStorage(path)) {
884+
File sb = new File(path, FOLDER_NAME);
885+
if ((sb.isDirectory() && sb.canWrite()) || sb.mkdirs()) {
886+
external = path + "/" + FOLDER_NAME;
887+
}
888+
}
889+
890+
if (external == null) {
891+
File files = getExternalFilesDir(null);
892+
if (files != null) {
893+
String externalFiles = files.getAbsolutePath();
894+
if (isPublicStorage(externalFiles)) {
895+
external = externalFiles;
896+
}
897+
}
898+
}
899+
900+
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
901+
// https://commonsware.com/blog/2019/06/07/death-external-storage-end-saga.html
902+
File[] dirs = getExternalMediaDirs();
903+
path = dirs != null && dirs.length > 0 ? dirs[0].getAbsolutePath() : null;
904+
if (isPublicStorage(path)) {
905+
media = path;
906+
}
907+
}
908+
909+
this._external = external;
910+
this._internal = getFilesDir().getAbsolutePath();
911+
this._media = media;
912+
}
913+
914+
public String getExternal() {
915+
return _external;
916+
}
917+
918+
public String getInternal() {
919+
return _internal;
920+
}
921+
922+
public String getMedia() {
923+
return _media;
924+
}
925+
926+
private boolean isPublicStorage(String dir) {
927+
boolean result;
928+
if (dir == null || dir.isEmpty()) {
929+
result = false;
930+
} else {
931+
File file = new File(dir);
932+
result = file.isDirectory() && file.canRead() && file.canWrite();
933+
}
934+
return result;
935+
}
936+
}
937+
933938
private class WebServerImpl extends WebServer {
934939
private final Map<String, Long> fileLengths = new HashMap<>();
935940

@@ -947,12 +952,12 @@ protected Response getFile(String path, boolean asset) throws IOException {
947952
log("Opened " + name + " " + length + " bytes");
948953
result = new Response(getAssets().open(name), length);
949954
} else {
950-
File file = getFile(getExternalStorage(), path);
955+
File file = getFile(_storage.getExternal(), path);
951956
if (file == null) {
952-
file = getFile(getMediaStorage(), path);
957+
file = getFile(_storage.getMedia(), path);
953958
}
954959
if (file == null) {
955-
file = getFile(getInternalStorage(), path);
960+
file = getFile(_storage.getInternal(), path);
956961
}
957962
if (file != null) {
958963
result = new Response(new FileInputStream(file), file.length());
@@ -966,9 +971,9 @@ protected Response getFile(String path, boolean asset) throws IOException {
966971
@Override
967972
protected Collection<FileData> getFileData() throws IOException {
968973
Collection<FileData> result = new ArrayList<>();
969-
result.addAll(getFiles(new File(getExternalStorage())));
970-
result.addAll(getFiles(new File(getMediaStorage())));
971-
result.addAll(getFiles(new File(getInternalStorage())));
974+
result.addAll(getFiles(new File(_storage.getExternal())));
975+
result.addAll(getFiles(new File(_storage.getMedia())));
976+
result.addAll(getFiles(new File(_storage.getInternal())));
972977
return result;
973978
}
974979

@@ -987,31 +992,31 @@ protected void renameFile(String from, String to) throws IOException {
987992
if (to == null || !to.endsWith(".bas")) {
988993
throw new IOException("Invalid file name: " + to);
989994
}
990-
File toFile = getFile(getInternalStorage(), to);
995+
File toFile = getFile(_storage.getInternal(), to);
991996
if (toFile == null) {
992-
toFile = getFile(getExternalStorage(), to);
997+
toFile = getFile(_storage.getExternal(), to);
993998
}
994999
if (toFile != null) {
9951000
throw new IOException("File already exists");
9961001
}
997-
File fromFile = getFile(getInternalStorage(), from);
1002+
File fromFile = getFile(_storage.getInternal(), from);
9981003
if (fromFile == null) {
999-
fromFile = getFile(getExternalStorage(), from);
1004+
fromFile = getFile(_storage.getExternal(), from);
10001005
}
10011006
if (fromFile == null) {
1002-
fromFile = getFile(getInternalStorage(), from);
1007+
fromFile = getFile(_storage.getInternal(), from);
10031008
}
10041009
if (fromFile == null) {
10051010
throw new IOException("Previous file does not exist");
10061011
}
1007-
if (!fromFile.renameTo(new File(getExternalStorage(), to))) {
1012+
if (!fromFile.renameTo(new File(_storage.getExternal(), to))) {
10081013
throw new IOException("File rename failed");
10091014
}
10101015
}
10111016

10121017
@Override
10131018
protected void saveFile(String fileName, byte[] content) throws IOException {
1014-
File file = new File(getExternalStorage(), fileName);
1019+
File file = new File(_storage.getExternal(), fileName);
10151020
if (file.exists()) {
10161021
throw new IOException("File already exists: " + fileName);
10171022
} else if (file.isDirectory()) {

src/platform/android/webui/src/App.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,14 +92,15 @@ function renameFile(from, to, success, fail) {
9292
callApi('/api/rename', body, success, fail);
9393
}
9494

95-
function copyFiles(event, success, fail) {
95+
function copyFiles(event, success, progress, fail) {
9696
const fileReader = new FileReader();
9797
const input = event.target;
9898
const files = input.files;
9999
let index = 0;
100100
fileReader.onload = () => {
101101
upload(files[index].name, fileReader.result, () => {
102102
if (++index < files.length) {
103+
progress(index);
103104
fileReader.readAsText(files[index]);
104105
} else {
105106
getFiles(success, fail);
@@ -164,7 +165,11 @@ function GridToolbarUpload(props) {
164165
props.setRows(newRows);
165166
setSeverity("success");
166167
setError(`Uploaded ${length} files`);
168+
}, (count) => {
169+
setSeverity("success");
170+
setError(`Uploaded ${count} files`);
167171
}, (error) => {
172+
setSeverity("error");
168173
setError(error);
169174
// show any successful uploads
170175
getFiles((newRows) => {

0 commit comments

Comments
 (0)