Android/IOS internal and SD storage

Share your advanced knowledge/code with the community.
tj1010
Posts: 201
Joined: Wed May 27, 2015 1:36 pm
Contact:

Android/IOS internal and SD storage

Post by tj1010 »

This allows you to read and write files(text and binary), make folders, delete folders, and get folder contents(like ExamineDirectory) on internal and SD storage on Android and IOS devices.

Tested on Android 12 on a S21 5G only. Needs IOS testing; should work as the plugin was made for both by Cordova team.
INFO
Source

Code: Select all

Import "cordova telemetry on" : EndImport
Import "cordova plugin add cordova-plugin-file" : EndImport
;cordova.file.externalDataDirectory(if app data directory is on SD)
;cordova.file.externalRootDirectory(SD card root)
;cordova.file.applicationStorageDirectory(internal storage App r/w directory)
;NOTE:internal storage root not accessible from cordova; requires special permissions and not-included API stuff

SD_ROOT.s="" : !v_sd_root=cordova.file.externalRootDirectory
SD_APP.s="" : !v_sd_app=cordova.file.externalDataDirectory
INTERNAL.s="" : !v_internal=cordova.file.applicationStorageDirectory

Structure MobileFSData
  Contents$
  Folder$
  Error.b
  Ready.b
EndStructure
Global LibMobileFSData.MobileFSData

;-correct error codes(copied from file read)
;-implement onErrorGetDir?
;asynchronus
Procedure DeleteDirectory(path.s)
  Protected ifolder.s=StringField(path,CountString(path,"/"),"/")
  Protected ipath.s=ReverseString(Mid(ReverseString(path),FindString(ReverseString(path),"/",FindString(ReverseString(path),"/")+1),Len(path)))
  !var onErrorGetDir=function(){};
  !function createDirectory(rootDirEntry) {
  !    rootDirEntry.getDirectory(v_ifolder, { create: false }, function (dirEntry) {
  !    }, onErrorGetDir);
  !    v_libmobilefsdata._Error=0;
  !    v_libmobilefsdata._Ready=1;
  !}
  !function fail(FileError) {
  !	switch(FileError["code"]){
  !		case 1:
  !		v_libmobilefsdata._Contents$='NOT_FOUND_ERR';
  !		break
  !		case 2:
  !		v_libmobilefsdata._Contents$='SECURITY_ERR';
  !		break
  !		case 3:
  !		v_libmobilefsdata._Contents$='ABORT_ERR';
  !		break
  !		case 4:
  !		v_libmobilefsdata._Contents$='NOT_READABLE_ERR';
  !		break
  !		case 5:
  !		v_libmobilefsdata._Contents$='ENCODING_ERR';
  !		break
  !		case 6:
  !		v_libmobilefsdata._Contents$='NO_MODIFICATION_ALLOWED_ERR';
  !		break
  !		case 7:
  !		v_libmobilefsdata._Contents$='INVALID_STATE_ERR';
  !		break
  !		case 8:
  !		v_libmobilefsdata._Contents$='SYNTAX_ERR';
  !		break
  !		case 9:
  !		v_libmobilefsdata._Contents$='INVALID_MODIFICATION_ERR';
  !		break
  !		case 10:
  !		v_libmobilefsdata._Contents$='QUOTA_EXCEEDED_ERR';
  !		break
  !		case 11:
  !		v_libmobilefsdata._Contents$='TYPE_MISMATCH_ERR';
  !		break
  !		case 12:
  !		v_libmobilefsdata._Contents$='PATH_EXISTS_ERR';
  !		break
  !		default:
  !	}
  ! v_libmobilefsdata._Error=1;
  ! v_libmobilefsdata._Ready=1;
  !}
  !resolveLocalFileSystemURL(v_ipath,createDirectory,fail);
EndProcedure

;-correct error codes(copied from file read)
;-implement onErrorGetDir?
;asynchronous
Procedure MobileCreateDirectory(path.s)
  Protected ifolder.s=StringField(path,CountString(path,"/"),"/")
  Protected ipath.s=ReverseString(Mid(ReverseString(path),FindString(ReverseString(path),"/",FindString(ReverseString(path),"/")+1),Len(path)))
  !var onErrorGetDir=function(){};
  !function createDirectory(rootDirEntry) {
  !    rootDirEntry.getDirectory(v_ifolder, { create: true }, function (dirEntry) {
  !    }, onErrorGetDir);
  !    v_libmobilefsdata._Error=0;
  !    v_libmobilefsdata._Ready=1;
  !}
  !function fail(FileError) {
  !	switch(FileError["code"]){
  !		case 1:
  !		v_libmobilefsdata._Contents$='NOT_FOUND_ERR';
  !		break
  !		case 2:
  !		v_libmobilefsdata._Contents$='SECURITY_ERR';
  !		break
  !		case 3:
  !		v_libmobilefsdata._Contents$='ABORT_ERR';
  !		break
  !		case 4:
  !		v_libmobilefsdata._Contents$='NOT_READABLE_ERR';
  !		break
  !		case 5:
  !		v_libmobilefsdata._Contents$='ENCODING_ERR';
  !		break
  !		case 6:
  !		v_libmobilefsdata._Contents$='NO_MODIFICATION_ALLOWED_ERR';
  !		break
  !		case 7:
  !		v_libmobilefsdata._Contents$='INVALID_STATE_ERR';
  !		break
  !		case 8:
  !		v_libmobilefsdata._Contents$='SYNTAX_ERR';
  !		break
  !		case 9:
  !		v_libmobilefsdata._Contents$='INVALID_MODIFICATION_ERR';
  !		break
  !		case 10:
  !		v_libmobilefsdata._Contents$='QUOTA_EXCEEDED_ERR';
  !		break
  !		case 11:
  !		v_libmobilefsdata._Contents$='TYPE_MISMATCH_ERR';
  !		break
  !		case 12:
  !		v_libmobilefsdata._Contents$='PATH_EXISTS_ERR';
  !		break
  !		default:
  !	}
  ! v_libmobilefsdata._Error=1;
  ! v_libmobilefsdata._Ready=1;
  !}
  !!resolveLocalFileSystemURL(v_ipath,createDirectory,fail);
EndProcedure

;-correct error codes(copied from file read)
;asynchronous
Procedure MobileExamineDirectory(path.s)
  !function success(entries) {
  !    var i=0;
  !    const jsonbuf=[];
  !    for(i=0;i<entries.length;i++){
  !       jsonbuf.push({"type":entries[i].IsFile,"name":entries[i].name,"path":entries[i].nativeURL});
  !    }
  !    v_libmobilefsdata._Contents$=JSON.stringify(jsonbuf);
  !    v_libmobilefsdata._Error=0;
  !    v_libmobilefsdata._Ready=1;
  !}
  !function fail(FileError) {
  !	switch(FileError["code"]){
  !		case 1:
  !		v_libmobilefsdata._Contents$='NOT_FOUND_ERR';
  !		break
  !		case 2:
  !		v_libmobilefsdata._Contents$='SECURITY_ERR';
  !		break
  !		case 3:
  !		v_libmobilefsdata._Contents$='ABORT_ERR';
  !		break
  !		case 4:
  !		v_libmobilefsdata._Contents$='NOT_READABLE_ERR';
  !		break
  !		case 5:
  !		v_libmobilefsdata._Contents$='ENCODING_ERR';
  !		break
  !		case 6:
  !		v_libmobilefsdata._Contents$='NO_MODIFICATION_ALLOWED_ERR';
  !		break
  !		case 7:
  !		v_libmobilefsdata._Contents$='INVALID_STATE_ERR';
  !		break
  !		case 8:
  !		v_libmobilefsdata._Contents$='SYNTAX_ERR';
  !		break
  !		case 9:
  !		v_libmobilefsdata._Contents$='INVALID_MODIFICATION_ERR';
  !		break
  !		case 10:
  !		v_libmobilefsdata._Contents$='QUOTA_EXCEEDED_ERR';
  !		break
  !		case 11:
  !		v_libmobilefsdata._Contents$='TYPE_MISMATCH_ERR';
  !		break
  !		case 12:
  !		v_libmobilefsdata._Contents$='PATH_EXISTS_ERR';
  !		break
  !		default:
  !	}
  ! v_libmobilefsdata._Error=1;
  ! v_libmobilefsdata._Ready=1;
  !}
  !window.resolveLocalFileSystemURL(v_path , function(dirEntry) {
  !    var directoryReader = dirEntry.createReader();
  !    directoryReader.readEntries(success,fail);
  !});
EndProcedure

;-correct error codes(copied from file read)
;asynchronous
Procedure MobileCreateFile(path.s)
  Protected file.s = ReverseString(Mid(ReverseString(aa$),1,FindString(ReverseString(aa$),"/")-1))
  Protected ipath.s = ReverseString(Mid(ReverseString(aa$),FindString(ReverseString(aa$),"/")))
  !var path = v_ipath;
  !var filename = v_file;
  !
  !window.resolveLocalFileSystemURL(v_path,
  !   function(dir) {
  !	      dir.getFile(v_file, {create:true,exclusive:true}, function(fileEntry) {
  !           v_libmobilefsdata._Error=0;
  !           v_libmobilefsdata._Ready=1;
  !       });
  !   },
  !   function(FileError){
  !       switch(FileError["code"]){
  !		        case 1:
  !		        v_libmobilefsdata._Contents$='NOT_FOUND_ERR';
  !		        break
  !		        case 2:
  !		        v_libmobilefsdata._Contents$='SECURITY_ERR';
  !		        break
  !		        case 3:
  !		        v_libmobilefsdata._Contents$='ABORT_ERR';
  !		        break
  !		        case 4:
  !		        v_libmobilefsdata._Contents$='NOT_READABLE_ERR';
  !		        break
  !		        case 5:
  !		        v_libmobilefsdata._Contents$='ENCODING_ERR';
  !		        break
  !		        case 6:
  !		        v_libmobilefsdata._Contents$='NO_MODIFICATION_ALLOWED_ERR';
  !		        break
  !		        case 7:
  !		        v_libmobilefsdata._Contents$='INVALID_STATE_ERR';
  !		        break
  !		        case 8:
  !		        v_libmobilefsdata._Contents$='SYNTAX_ERR';
  !		        break
  !		        case 9:
  !		        v_libmobilefsdata._Contents$='INVALID_MODIFICATION_ERR';
  !		        break
  !		        case 10:
  !		        v_libmobilefsdata._Contents$='QUOTA_EXCEEDED_ERR';
  !		        break
  !		        case 11:
  !		        v_libmobilefsdata._Contents$='TYPE_MISMATCH_ERR';
  !		        break
  !		        case 12:
  !		        v_libmobilefsdata._Contents$='PATH_EXISTS_ERR';
  !		        break
  !		        default:
  !       }
  !       v_libmobilefsdata._Error=1;
  !       v_libmobilefsdata._Ready=1;  
  !});
EndProcedure

;-handle error codes and file not found
;asynchronous
Procedure MobileDeleteFile(path.s)
  Protected file.s = ReverseString(Mid(ReverseString(aa$),1,FindString(ReverseString(aa$),"/")-1))
  Protected ipath.s = ReverseString(Mid(ReverseString(aa$),FindString(ReverseString(aa$),"/")))
  !window.resolveLocalFileSystemURL(v_ipath,
  !   function(dir) {
  !       dir.getFile(v_file, {create:false}, function(fileEntry) {
  !           fileEntry.remove(function(){
  !               v_libmobilefsdata._Error=0;
  !               v_libmobilefsdata._Ready=1;
  !           },function(error){
  !               // Error deleting the file
  !           },function(){
  !               // The file doesn't exist
  !           });
  !       });
  !});
EndProcedure

;-correct error codes(copied from file read)
;1=binary, 0=text
;handle write error codes
;asynchronous
Procedure MobileWriteFile(path.s,content.s,mode.b)
  Protected file.s = ReverseString(Mid(ReverseString(aa$),1,FindString(ReverseString(aa$),"/")-1))
  Protected ipath.s = ReverseString(Mid(ReverseString(aa$),FindString(ReverseString(aa$),"/")))
  !function writeFile(fileEntry) {
  !    fileEntry.createWriter(function (fileWriter) {
  !        fileWriter.onwriteend = function() {
  !           v_libmobilefsdata._Error=0;
  !           v_libmobilefsdata._Ready=1;
  !        };
  !
  !        fileWriter.onerror = function (e) {
  !           v_libmobilefsdata._Error=1;
  !           v_libmobilefsdata._Ready=1;
  !        };
  !
  !        //filler data if no data
  !        if (!v_content) {
  !            if(mode==1){
  !               v_content = new Blob([' '], { type: 'application/octet-stream' });
  !            }Else{
  !               v_content = new Blob([' '], { type: 'text/plain' });
  !            }
  !        }else{
  !            if(mode==1){
  !               v_content = new Blob([v_content], { type: 'application/octet-stream' });
  !            }Else{
  !               v_content = new Blob([v_content], { type: 'text/plain' });
  !            }
  !        }
  !        fileWriter.write(v_content);
  !    });
  !}
  !function fail(FileError) {
  !	switch(FileError["code"]){
  !		case 1:
  !		v_libmobilefsdata._Contents$='NOT_FOUND_ERR';
  !		break
  !		case 2:
  !		v_libmobilefsdata._Contents$='SECURITY_ERR';
  !		break
  !		case 3:
  !		v_libmobilefsdata._Contents$='ABORT_ERR';
  !		break
  !		case 4:
  !		v_libmobilefsdata._Contents$='NOT_READABLE_ERR';
  !		break
  !		case 5:
  !		v_libmobilefsdata._Contents$='ENCODING_ERR';
  !		break
  !		case 6:
  !		v_libmobilefsdata._Contents$='NO_MODIFICATION_ALLOWED_ERR';
  !		break
  !		case 7:
  !		v_libmobilefsdata._Contents$='INVALID_STATE_ERR';
  !		break
  !		case 8:
  !		v_libmobilefsdata._Contents$='SYNTAX_ERR';
  !		break
  !		case 9:
  !		v_libmobilefsdata._Contents$='INVALID_MODIFICATION_ERR';
  !		break
  !		case 10:
  !		v_libmobilefsdata._Contents$='QUOTA_EXCEEDED_ERR';
  !		break
  !		case 11:
  !		v_libmobilefsdata._Contents$='TYPE_MISMATCH_ERR';
  !		break
  !		case 12:
  !		v_libmobilefsdata._Contents$='PATH_EXISTS_ERR';
  !		break
  !		default:
  !	}
  ! v_libmobilefsdata._Error=1;
  ! v_libmobilefsdata._Ready=1;
  !}
  !resolveLocalFileSystemURL(v_ipath,writeFile,fail);
EndProcedure

;asynchronus
Procedure MobileReadFile(path.s)
  !var onErrorReadFile=function(){};
  !function ReadFile(fileEntry){
  !
  !    fileEntry.file(function (file) {
  !        var reader = new FileReader();
  !
  !        reader.onloadend = function() {
  !            v_libmobilefsdata._Contents$=this.result;
  !            v_libmobilefsdata._Error=0;
  !            v_libmobilefsdata._Ready=1;
  !        };
  !
  !        reader.readAsText(file);
  !
  !    }, onErrorReadFile);
  !}
  !
  !function fail(FileError) {
  !	switch(FileError["code"]){
  !		case 1:
  !		v_libmobilefsdata._Contents$='NOT_FOUND_ERR';
  !		break
  !		case 2:
  !		v_libmobilefsdata._Contents$='SECURITY_ERR';
  !		break
  !		case 3:
  !		v_libmobilefsdata._Contents$='ABORT_ERR';
  !		break
  !		case 4:
  !		v_libmobilefsdata._Contents$='NOT_READABLE_ERR';
  !		break
  !		case 5:
  !		v_libmobilefsdata._Contents$='ENCODING_ERR';
  !		break
  !		case 6:
  !		v_libmobilefsdata._Contents$='NO_MODIFICATION_ALLOWED_ERR';
  !		break
  !		case 7:
  !		v_libmobilefsdata._Contents$='INVALID_STATE_ERR';
  !		break
  !		case 8:
  !		v_libmobilefsdata._Contents$='SYNTAX_ERR';
  !		break
  !		case 9:
  !		v_libmobilefsdata._Contents$='INVALID_MODIFICATION_ERR';
  !		break
  !		case 10:
  !		v_libmobilefsdata._Contents$='QUOTA_EXCEEDED_ERR';
  !		break
  !		case 11:
  !		v_libmobilefsdata._Contents$='TYPE_MISMATCH_ERR';
  !		break
  !		case 12:
  !		v_libmobilefsdata._Contents$='PATH_EXISTS_ERR';
  !		break
  !		default:
  !	}
  ! v_libmobilefsdata._Error=1;
  ! v_libmobilefsdata._Ready=1;
  !}
  !resolveLocalFileSystemURL(v_path,ReadFile,fail);
EndProcedure
Demos
List everything on root of SD

Code: Select all

Procedure CloseWindowEvent()
  CloseWindow(EventWindow())
EndProcedure

Procedure TimerEvents()
  If LibMobileFSData\Ready=#True
    If LibMobileFSData\Error=0
      ;{"type":entries[i].IsFile,"name":entries[i].name,"path":entries[i].nativeURL}
      If ParseJSON(0,LibMobileFSData\Contents$)
        For i = 0 To JSONArraySize(JSONValue(0)) - 1
          Select GetJSONBoolean(GetJSONMember(GetJSONElement(JSONValue(0),i),"type"))
            Case 0:
              Debug "Type: Folder"
            Case 1:
              Debug "Type: File"
          EndSelect
          Debug "Name: "+GetJSONString(GetJSONMember(GetJSONElement(JSONValue(0),i),"name"))
          Debug "Path: "+GetJSONString(GetJSONMember(GetJSONElement(JSONValue(0),i),"path"))
        Next
      EndIf
    Else
      Debug "ERROR: "+LibMobileFSData\Contents$
    EndIf
    LibMobileFSData\Ready=#False
    LibMobileFSData\Contents$=""
    LibMobileFSData\Error=0
    LibMobileFSData\Folder$=""
  EndIf
EndProcedure

ExamineDesktops()
OpenWindow(0,0,0,DesktopWidth(0),DesktopHeight(0),"")
AddWindowTimer(0,0,3000)
BindEvent(#PB_Event_Timer, @TimerEvents())
BindEvent(#PB_Event_CloseWindow, @CloseWindowEvent())

LibMobileFSData\Ready=#False
MobileExamineDirectory(SD_ROOT)
Create new folder in SD app directory

Code: Select all

Procedure CloseWindowEvent()
  CloseWindow(EventWindow())
EndProcedure

Procedure TimerEvents()
  If LibMobileFSData\Ready=#True
    If LibMobileFSData\Error=0
      Debug LibMobileFSData\Contents$
    Else
      Debug "ERROR: "+LibMobileFSData\Contents$
    EndIf
    LibMobileFSData\Ready=#False
    LibMobileFSData\Contents$=""
    LibMobileFSData\Error=0
    LibMobileFSData\Folder$=""
  EndIf
EndProcedure

ExamineDesktops()
OpenWindow(0,0,0,DesktopWidth(0),DesktopHeight(0),"")
AddWindowTimer(0,0,3000)
BindEvent(#PB_Event_Timer, @TimerEvents())
BindEvent(#PB_Event_CloseWindow, @CloseWindowEvent())

LibMobileFSData\Ready=#False
MobileCreateDirectory(SD_APP+"testdir")
bembulak
Posts: 71
Joined: Wed Feb 26, 2014 9:53 am

Re: Android/IOS internal and SD storage

Post by bembulak »

Needs IOS testing;
I do have the necessary setup to test iOS. Could you provide a working example/demo? Then I'll compile & test it on iPhone & iPad.

edit: This is very helpful and awesome! Thank you!
bembulak
Posts: 71
Joined: Wed Feb 26, 2014 9:53 am

Re: Android/IOS internal and SD storage

Post by bembulak »

I tried to glue together some sort of example to test, but had no success. Compiling / transferring / testing works (not always easy with Apple), but the program does nothing.

As said: I'm willing to help. However, I'm not that firm with SB, let alone additional functionality.
tj1010
Posts: 201
Joined: Wed May 27, 2015 1:36 pm
Contact:

Re: Android/IOS internal and SD storage

Post by tj1010 »

I'll update demos and the code once SB works again. I get a lot of Gradle errors with current version of SB regardless of connection or machine. I can't test or add stuff till then. It's also why I haven't done TPM/TEE/keystore stuff...

I actually need it for storing a sqlite db in the app directory for a Android app, but SB will only do web stuff right now... I want to get rid of of the need for timer too with blocking functions..
Post Reply