SAF: App Inventor implementation of Storage Access Framework

1.Introduction

Description: Basically AI2 wrapper of Storage Access Framework. Using this extension, you can get read and/or write access to a single document or tree document (and all of its children recursively).
Latest Version: 1.3
Released: 2021-09-16T18:30:00Z
Last Updated: 2023-11-15T18:30:00Z

2.Blocks



















image
image




3.Documentation

Events

ErrorOccurred Event indicating error/exception has occurred and returns origin method and error message.
methodName | text
errorMessage | text
DocumentCreated Event invoked after creating document.Returns document's uri if operation was successful else returns error message
uriString | text
GotWriteResult Event invoked after writing to document.Returns document's uri if operation was successful else returns error message
response | text
GotReadResult Event invoked after reading from document.Returns content if operation was successful else returns error message
result | any
GotUri Event invoked when user selects a document or tree from SAF file picker
uri | any
uriString | text
GotFilesList Event invoked after getting files list
filesList | list
GotCopyResult Event invoked after getting copy document result.Response will be target document's uri if operation was successful else returns error message
successful | boolean
response | text
GotMoveResult Event invoked after getting move document result.Response will be target document's uri if operation was successful else returns error message
successful | boolean
response | text
DocumentCopiedToFile Event raised after getting 'CopyDocumentToFile' result
successful | boolean
response | text
DocumentCopiedFromFile Event raised after getting 'CopyDocumentFromFile' result
successful | boolean
response | text

Methods

CreateFlags Combines two flags and returns resulting flag
f1 | number
f2 | number
StringFromUriObject Convert uri to string
uri | any
StringToUriObject Converts string to uri
uriString | text
InitialDir Returns uri which can be used as Initial Dir in SAF picker
dir | text
OpenDocumentTree Prompts user to select a document tree
title | text
initialDir | text
OpenSingleDocument Prompts user to select a single file
title | text
initialDir | text
type | text
extraMimeTypes | list
TakePersistableUriPermission Take a persistable URI permission grant that has been offered. Once taken, the permission grant will be remembered across device reboots.
uri | any
flags | number
IsTreeUri Returns whether given uri is a tree uri
uriString | text
IsDocumentUri Returns whether given uri is a document uri
uriString | text
IsChildDocumentUri Returns whether second uri is child of first uri
parentUri | text
childUri | text
GetTreeDocumentId Returns document id of tree uri (should be either tree uri itself or a direct child uri)
uriString | text
GetDocumentId Returns document id of an uri (should only be grand child)
uriString | text
BuildDocumentUriUsingTree Builds document uri using tree uri and document id
treeUri | text
documentId | text
BuildChildDocumentsUriUsingTree Builds child documents id using tree (documents which is child of parent document) uri and its parent document id
treeUri | text
parentDocumentId | text
GetDisplayName Returns display name of given document uri
documentUri | text
GetSize Returns size (in bytes) of given document uri
documentUri | text
GetLastModifiedTime Returns last modified time (epoch) of given document uri
documentUri | text
GetMimeType Returns mime type of given document uri
documentUri | text
IsCopySupported Returns whether document can be copied or not
documentUri | text
IsMoveSupported Returns whether document is movable or not
documentUri | text
IsDeleteSupported Returns whether document is deletable or not
documentUri | text
IsRenameSupported Returns whether document is deletable or not
documentUri | text
CreateDocument Creates a new and empty document.If document already exists then an incremental value will be suffixed.
parentDocumentUri | text
fileName | text
mimeType | text
WriteToFile Writes content as text to given uri
uriString | text
content | text
WriteAsHexString Writes content as HEX to given uri
uriString | text
content | text
WriteAsByteArray Writes byte array to given document
uriString | text
byteArray | any
DeleteDocument Tries to delete document from given uri and returns result
uriString | text
ReadFromFile Reads from given document as text
uriString | text
ReadAsByteArray Reads content of document as byte array
uriString | text
ReadAsHexString Reads content of document as HEX string
uriString | text
IsReadGranted Returns whether read is available for given uri
uri | text
ReleasePermission Relinquish a persisted URI permission grant
uri | text
flags | number
IsWriteGranted Returns whether write is available for given uri
uri | text
ListFiles Tries to list files from given dir
dirUri | text
dirDocumentId | text
CopyDocument Tries to copy document from source uri to target dir
sourceUri | text
targetParentUri | text
MoveDocument Tries to move document from source uri to target dir
sourceUri | text
sourceParentUri | text
targetParentUri | text
RenameDocument Tries to rename a document and returns updated uri
documentUri | text
displayName | text
CopyDocumentToFile Tries to copy document from source uri to specified folder
sourceUri | text
dirPath | text
CopyDocumentFromFile
filePath | text
targetParentUri | text
ConvertStringToBytes Converts text to bytes and return Byte Array object. It can be used with 'WriteAsByteArray' method.
byteString | text
CreateDocumentSync Creates document on main thread and returns its uri immediately if operation was successful otherwise empty string is returned
parentDocumentUri | text
fileName | text
mimeType | text

Properties

DocumentDirMimeType Returns mime type of document dir
Property Type : read-only
Accepts : text
FlagGrantReadPermission Flag to get write permission
Property Type : read-only
Accepts : number
FlagGrantWritePermission Flag to get read permission
Property Type : read-only
Accepts : number

4.Usages

1.Open document tree
image

2.Get access (not necessary for one-time usage)

image

3.Build child document uri

  1. if document is direct child

  1. if document is grandchild

4.Read file/Set picture
image

Examples by Power Users
I am thankful to them for their efforts.

5.Download

Aix:
com.sunny.saf.aix (29.2 KB)

6.Open Source

7.Liked my work/Want to donate :heart:

Thank you :hugs:

8. ChangeLog

ChangeLog Version 1.1

New Blocks
image
image

Changes

  • Removed category param from OpenSingleDocument method
  • GotCopyResult and GotMoveResult now return resulting/target document’s uri

Bug Fixes

  • Fixed issue in write methods
  • Fixed null pointer exception when SAF picker was cancelled by user
ChangeLog Version 1.2

SAF: App Inventor implementation of Storage Access Framework - #331 by vknow360 - Extensions - MIT App Inventor Community

ChangeLog Version 1.3

SAF: App Inventor implementation of Storage Access Framework - #360 by vknow360 - Extensions - MIT App Inventor Community

Thank you.
Hope it helps! :slightly_smiling_face:

43 Likes

Didn’t understand anything :cold_sweat: . why should we use this extension instead file component. What is document tree

That’s not a problem.
You can always google it.

People interested in Storage and Developers working with files will find it useful.

2 Likes

I want to know, about it work

I Am Just Shocked How Much Hardwork You Have Done In Making Extension

specially In Creating So Long Post With Proper & A to Z Documentation.

Its Took Me around 10 Sec to scroll to view comments

A Big Salute to you :love_you_gesture: :love_you_gesture: :+1: :+1:

Really You Are Masterpiece

Awesome Extesnions

6 Likes

What an amazing extension! Great job!
You are far ahead of AI2. :wink:
I’ve only done a few tests and it seems to be working so far.

6 Likes

@vknow360 excellent work! thank you very much! :partying_face:
I guess, you also will publish in the App Inventor community soon…

see the overview by @bodymindpower…

everywhere you can see Storage Access Framework you can use it… these are places the file component can’t access… for example to read or write non media files created by other apps …

Taifun

7 Likes

Thank you :blush:

Already did, waiting for approval.


It will work in Android KitKat and above versions but it is recommended to use SAF on Android 5.0+.

1 Like

can it work in android 11?

Done …
It’s a shame that your extensions need approval in AI2.

11 Likes

We are facing problem with the file component of kodular after the new update of kodular with android 11 phones
I am just creating a file in the external storage and retrieving it from the same place as per the requirement
Does it will solve the issue?

Excellent work :+1: :clap:

3 Likes

starting with SDK30 you should not create arbitrary directories anymore…
use the ASD or shared storage like /Download…
see also the overview by @bodymindpower

Taifun

2 Likes

Epic work @vknow360 :love_you_gesture:

3 Likes

My app is a offline app, which stores salary statements of the employee. I have included a tab to export the stored data to the phone to provide the user to transfer data to new phone in case the user is changing the phone.
I was storing the file directly to the external storage “/storage/emulated/0/salary”. Now this thing is not working in the new kodular update.
Pl suggest me if i want to use this extension then how to do this.


blocks(25)

@Shreyaa
I dont know how to use this
…
If you can help. I need to create the file (if possible any where in phone) and save data in that

bruh why you @narender_kumar mention me ? ask from @vknow360 he is the developer of extension

Read the post and show the block what you have tried till now

@vknow360

I was having little bit problem to understand how it works

In .OpenDocumentTree block what I have to add in it

I added this /storage/emulated/0/Android/data path in OpenDocumentTree

When I call the block it show the /storage/emulated/0/

Actually I was trying to access text file in this path /storage/emulated/0/Android/data/com.OtherAppPrivate.Dir/files/text.txt

And trying to modifying it

Why you put the “/storage/0001-61E9” in that block

I am very confused about SAF

SAF can give you access to 90% of the file system.
But you can’t access /Android/data and /Android/obb dir and its childs.

That’s path of sdcard in my phone. :slightly_smiling_face:

Example 2

1 Like