Firebase Storage on Android and iOS

Hello,
I have a problem with Firebase Storage.
Please point it out if there is a mistake in how to use it.
This has been discussed in other topics,
so if it is an issue, please add Firebase Storage to tests for next version.
Uploading image on iOS

The results are as follows:
Android
NoSecure:OK, Secure:NG("Permission denied.")
iOS
NoSecure:NG, Secure:NG

The rule of Storage:
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /NoSec/{allPaths=} {
allow read, write: if true;
}
match /Secure/{allPaths=
} {
allow read, write: if request.auth != null;
}
}
}

The blocks of NoSecure sample:

The blocks of Secure sample:

Thank you.

You should be able to get everything you need from here:

The guide covers secure and non secure firebase storage as well.

This is the expected behavior on ios.

According to https://doesappinventorrunonios.com/ Firebase does not work with ios yet. Search in the above link for Components>Experimental>FirrebaseDB.to see the documentation.

But no reason, as far as I know, that will prevent a developer interacting with Firebase using the Web component.

The only issue outstanding is PATCH, which is not needed for FirebaseStorage:

I'm sure you're the owner.
With your information below, I was able to create an app with Firebase Authentication, Realtime Database and Storage using a web component.

  • METRIC RAT AI2 Registration & Login with Firebase Authentication
  • METRIC RAT AI2 Firebase with a Web Component

Thank you.But I can't solve this problem.
Has anyone experienced this?

Show your blocks and outputs.

A valid firebase user must sign in to get their valid idToken, this must then be passed to the firebase storage POST/GET request.

Ensure your firebaseStorage rules are correct as per my guide:

For the firebase storage, I will use rules that allow authenticated 
users to read and write everything, within the FBDEMO folder:

rules_version = '2';

service firebase.storage {
  match /b/myProject.appspot.com/o {
    match /FBDEMO/{allPaths=**} {
      allow read: if request.auth != null
      allow write:  if request.auth != null;
    }
  }
}

And this:

looks incorrect, it should be:

projectID.appspot.com, and you need to use your actual projectID ?

I used your rules and it worked fine.
But, I changed it back to the first rule below and it worked fine.
(allow read, write: if request.auth != null;)
Probably my mistake.
The iOS issue remains.
Thank you for your help.

Whilst I do not have an iOS device to test, I cannot see why a fairly simple web POST or GET request does not work.

Try without secure rules, and report back on the output from Firebase returned in the Web1.GotText responseContent. The raw response from firebase is always a json...

Ensure that your filePath in IOS is correct, I am aware these look quite different to those on Android, and that the file in question has read permissions for the web component.

Can you try a simple web GET request to another/different url ?

I respond to your requests.
I tried without secure rules.

###ios####:
-responseCode:
200

-responseContent:
{
"name": "NoSec%2Ftest1.png",
"bucket": "PROJECTID.firebasestorage.app",
"generation": "1742355065963451",
"metageneration": "1",
"timeCreated": "2025-03-19T03:31:05.975Z",
"updated": "2025-03-19T03:31:05.975Z",
"storageClass": "REGIONAL",
"size": "0",
"md5Hash": "1B2M2Y8AsgTpgAmY7PhCfg==",
"contentEncoding": "identity",
"contentDisposition": "inline; filename*=utf-8''NoSec%252Ftest1.png",
"crc32c": "AAAAAA==",
"etag": "CLuHnraalYwDEAE=",
"downloadTokens": "83f95c2c-c21f-46d9-8260-8b198a8c743f"
}

-Result:
A folder called "NoSec%2Ftest1.png" is created.
But I can't delete it.To be precise, even if I delete it, it comes back.

###android####:
-responseCode:
200

-responseContent:
{
"name": "NoSec/test1.png",
"bucket": "PROJECTID.firebasestorage.app",
"generation": "1742355419050748",
"metageneration": "1",
"contentType": "application/x-www-form-urlencoded",
"timeCreated": "2025-03-19T03:36:59.056Z",
"updated": "2025-03-19T03:36:59.056Z",
"storageClass": "REGIONAL",
"size": "178637",
"md5Hash": "qVRAlXURDXUiYxweRrru5Q==",
"contentEncoding": "identity",
"contentDisposition": "inline; filename*=utf-8''test1.png",
"crc32c": "x33EZg==",
"etag": "CPzlzN6blYwDEAE=",
"downloadTokens": "e82138fb-6617-4797-aaca-3e4cd6752eb4"
}

-Result:
it works fine of course .

####About the file path####:
It is obtained using ImagePicker component.

ImagePicker

The example of file path is follow.
/var/mobile/Containers/Data/Application/8B26D756-D2DE-444A-B745-AE8E5712B0B5/Library/Application Support/AppInventor/asset.JPG

The image is displayed on the screen.

####another/different url####
The PostText block for chatGPT API works fine.
The Get block for Google Books API works fine.

Thank you.

Looking at the responseContent for both, I would initially guess that Firebase is not getting the file. Let me do a little bit of testing, and I will come back with a few suggestions.

Try like this:


(application/x-www-form-urlencoded)

If that doesn't work try with image/png as the content-type.

Please show your relevant blocks, just so we can be sure they are correct.

I am drawn back to your filepath as well, you provide what appears to be a relative or absolute path, we may be requiring a full path...on Android it would look like this for a file picked in the Download folder, which is then copied to the ASD:
file:///storage/emulated/0/Android/data/edu.mit.appinventor.aicompanion3/files/Pictures/_app_inventor_image_picker/picked_image1565366041313282111.png

The iOS file/storage system is and remains a black box. For example, if I download a file from my server via the web component, I can't specify a fixed path. I see the result (the path) at the end, but I can't check whether the file exists either via the file manager or programmatically. The only option is to use a component that attempts to access the path (the file) and determine whether the file actually exists there. If the attempt fails, I have to download the file again and see that a new path is created.

This is one of the main reasons why I've currently paused development of my iOS apps. Since only 30MB is available for the aia (IPA), I have to download larger files in advance. After some time or after restarting the iOS device, the files/paths seem to disappear, so I have to start a complicated and time-consuming procedure before each restart of the app to ensure the existence of all files.

1 Like

There may be another approach, as shown by @Anke here:

and loosely based on this:

and this:

I have a working html file you can test if you wish...

I added the RequestHeaders but unfortunately that didn't change anything.

Given my previous post on an alternative, you might try this instead:

wvFBS.aia (3.7 KB)
(this is for iOS only)

You will need to fill in all the blanks for all the variables from firebase Config, and add your directory.

You can get your Firebase Config from the console here:

image

image

(screenshots from using with android and webviewextra extension)

<!DOCTYPE html>

<html>
<meta name=“viewport” content=“width=device-width, initial-scale=1.0”>
<meta charset="utf-8">

<head>
  <title>UPLOAD-FB-STORAGE-AI2</title>
  <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
  <script src="https://www.gstatic.com/firebasejs/8.10.0/firebase-app.js"></script>
  <script src="https://www.gstatic.com/firebasejs/8.10.0/firebase-storage.js"></script>
</head>

<body>

<input class="w3-btn w3-blue" type="file" accept="image/*" id="fUpload"><br><br>
<div id="filepath"></div>

<script>

var wvs = window.AppInventor.getWebViewString().split(",");

const firebaseConfig = {
  apiKey: 		    wvs[0],
  authDomain: 		wvs[1],
  databaseURL: 		wvs[2],
  projectId: 		wvs[3],
  storageBucket: 	wvs[4],
  messagingSenderId:wvs[5],
  appId: 		    wvs[6],
  measurementId: 	wvs[7]
}; 


firebase.initializeApp(firebaseConfig);

let fileUpload = document.getElementById("fUpload");

fileUpload.addEventListener('change', function(evt) {
   let firstFile = evt.target.files[0];
   let fname = firstFile.name;
   let storageRef = firebase.storage().ref(wvs[8] + "/" + fname);
   let uploadTask = storageRef.put(firstFile)
   .then(function() {
   storageRef.getDownloadURL().then(function(downloadURL) {
   document.getElementById("filepath").innerHTML = "File uploaded to Firebase Storage"
   window.AppInventor.setWebViewString(downloadURL);
   });
   });
});
</script>

</body>

</html>

wvFBS.aia worked in my environment.
there is not the measurementId parm at Firebase Config of my project.
I skiped to set this parm.
Thank you for your help.

It seems like there's a permission issue with Firebase Storage. The error 'Permission denied' on Android and iOS suggests that the security rules are not configured correctly. Double-checking the storage rules and ensuring that the correct bucket and path are being referenced may resolve the issue.

I disagree. The issue appears to be that the POSTFile block is not getting a proper "fix" on the path to the file. This is demonstrated by the outputs shown by the OP above, and from previous posts by @Anke it is not just when trying to upload a file to Firebase Storage.

Could MIT take a look ? @ewpatton