In my android app I am using client side fan-out to upload data to multiple places in database at the same time to avoid problems for example in case of lost internet connection. Here is example code from Firebase blog:
Map updatedUser = new HashMap();
newPost.put("name", "Shannon");
newPost.put("username": "shannonrules");
Firebase ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/");
Map fanoutObject = new HashMap();
fanoutObject.put("/users/1", updatedUser);
fanoutObject.put("/usersWhoAreCool/1", updatedUser);
fanoutObject.put("/usersToGiveFreeStuffTo/1", updatedUser);
ref.updateChildren(fanoutObject); // atomic updating goodness
But now I would also like to upload image file to storage alongside that data. Is that posiible to do that at the same time?
I don't think you can synchronize calls to Firebase Database and storage. The documentation does not mention it anywhere.
But just so you know: Firebase will save any requests made by updateChildren() in the cache if they cannot be sent due to loss of connection. When the user reconnects, Firebase will then dispatch all the cached requests in the same order that they were saved.
One way to do these two tasks concurrently would be to first determine your file path in Storage, and kick off the upload, then also use that file path to update the database. That's about as good as you'll get.
However, most of the time you want to store the "download URL" of the uploaded file in the database, instead of the path in the storage bucket. This makes it easier for clients to go directly to the content without having to "look up" the download URL first. In this case, you really do need to wait for the storage upload to complete first, get the download URL from the UploadTask, then update the database with that string. You can't know the download URL before the upload completes.
Related
I am really confused about the process of retrieving and displaying images to your android app from firebase cloud storage. I looked around the web, but am unable to get a definitive answer to my questions.
With regards to my app, I simply want a place to store a bunch of images (around 2500) that I can display. I don't use authentication and I don't mind making these images public.
Do I have to request a download URL every time I want to retrieve an image from storage? I am worried because Firebase Storage allows you to download 1GB/day and only 50k/day download operations for free, which is not a lot of download operations for 2500 images.
Is there a way for me to access and display images without having to call reference.getDownloadUrl() ** every time I display an image?** Maybe some sort of workaround by making the images public and then storing the cloud storage URLs in a Room Database?
Any help is appreciated.
Do I have to request a download URL every time I want to retrieve an image from storage?
No, you can use the same URL repeatedly. Store that URL anywhere you like. But you will always pay the cost for egress every time the URL is accessed. There are no free downloads after the free allowance.
Is there a way for me to access and display images without having to call reference.getDownloadUrl() every time I display an image?
No, as I said above, you can reuse the same URL if you want. You can also configre the entire cloud storage bucket as public and simply build URLs to object as described in the links here. But again, downloads will be billed according to the normal Cloud Storage rates.
Please enable Firebase Storage for your bucket by visiting the Storage tab in the Firebase Console and ensure that you have sufficient permission to properly provision resources.",
"status": "ACCESS_BUCKET"
I wanted to store the specific path in Firebase database (JSON) in local phone storage, not all data at the realtime-Firebase database. Say I have a news-feed path for each user in my Firebase-database and I want to save only the news-feed which is specified for the user instead of loading whole useless data on the local storage of user's mobile.
I read this paragraph from the official Firabase site which mentioned that
The Firebase Real-time Database synchronizes and stores a local copy of the data for active listeners. In addition, you can keep specific locations in sync.
DatabaseReference scoresRef = FirebaseDatabase.getInstance().getReference("scores");
scoresRef.keepSynced(true);
If this is the solution to my question, then I can use this line directly without writing that line
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
Those two bits of code are not really related. They don't do the same thing.
keepSynced(true) effectively keeps a listener active on the given reference, from the moment it's called, for as long as the app is running, so that the local version of the data is always in sync with the remote version on the server.
setPersistenceEnabled(true) just activates local caching of the data read by the SDK. When persistence is enabled, the app can still query data previously read. It takes effect for all data read by the SDK. While persistence is enabled, you can't control which data is cached - all read data is cached up to 10MB max. When the max is reached the oldest data will be evicted from the cache.
According to me the best way will be to parse the Firebase JSON data and map it into an object and then save only data that you need in a local storage (News-feed in your case), and then access it later whenever you need it.
For this, you can use Paper DB as a local storage to store specific data and use it whenever you need to. It stores data as a key value pair so you can access your data with the same key you inserted it with in the database. (Just like shared preferences work).
It stores data as cache in your local storage and uses Kryo serialization framework which is pretty fast for I/O operations.
Or you can also use Room (a google library) with SQLite to achieve this task.
Haven't tried Room but i think it will suite your purpose.
Here's the official documentation for Room
From what I´ve read from the official firebase documentation and after watching this firecast my understanding is that in order to display images on a client there are two approaches:
The first is server based,using functions and writing the SignedUrls to the database.
The second is client based using StorageReference and pointing to the desired path in storage.
I have decided to follow the second approach due to the fact that the Firebase client SDK gives you the ability to directly query a storage photo for additional useful information about the photo (creation date,metadata etc) without the need of creating additional entries in the database
(like in the SignedUrl case by using functions.storage.ObjectMetadata).
My questions are:
1) can the bucket name or the full internal photo path be used in the client code without any security risks?
The path form may be:
gs://myapp.appspot.com/bucket_folder/username/photoname.PNG (non-default bucket)
2) Are there any drawbacks by using the client SDK method over the server-produced SignedUrls?
There are two ways to access items in Cloud Storage through the Firebase SDK:
By using the Firebase SDK methods to access the data.
By using the download URL.
When you use the download URL, the user doesn't have to be signed in. But the user can only ever read the file and (as you discovered) will only have access to the raw payload of the file, not the metadata.
When you use the other methods of the Firebase SDK, your access is controlled by the security rules. So your user may have to sign in.
I am creating an Android App where Firebase is the backed. In my app, I have some selected images that I have stored inside my Firebase storage by direct uploading (Without coding).
Now I have to view that images in my app through a recycle view. For that purpose, I have to get the download URL of all the images and put them into my Firebase real-time database programmatically so that I can access the URL to my app. Is there any methods available for that?
I have tried to iterate through storage, unfortunately there is no method for that.
There is currently no way to iterate a list of files in Firebase Storage using the Firebase SDKs. Instead, after you upload a file, you should also store its download URL in Firebase Realtime Database (or some other place) that you can query for the download URLs.
I was searching for a proper answer to this question for 2 days. What i found is, There is no proper API or Class in Firebase Storage for the same purpose. If you guys want to do the same effectively, get the files in your code programmatically and upload them to firebase storage through a loop. Through that you can get the download links after uploading of each files. Store it in the Real time Database of Firebase.
You can create a function that can can return a file. You can set up a /link url in the hosting to that function.
I have yet to find any good documentation to tell me how to manage this issue. Is there any guidance someone can reference for this issue?
For an Android app, I have started using Google Firebase Storage along with my realtime Database, and I have a question on how to ensure file uploads and database updates happen in the proper order.
Previously, I was encoding an audio file to a string and uploading it to FB Database along with other related data as a single hash map to ensure consistency. The related data that is being stored is a POJO relating to what users can access the audio, the path where the audio is stored in the database, and more.
My new set up is first to upload the audio file to FB Storage, and, once the file is uploaded, trigger a FB Database update for the related data. Once the database listener indicates completion, the app moves to a different activity.
I am concerned that this two step process is unstable (user leaves the activity before both tasks are done, Storage upload is interrupted and Database update never occurs, etc.). If the Database information isn't updated, the other users won't be notified that the audio file is online and they won't have the path to reference it stored in the database.
What is the proper order for structuring simultaneous Storage and Database uploads in the new Google Firebase?
Thanks,
Andy
Not sure why there are no solid answers for this yet. Anyway, I have faced very similar problems and eventually resorted with nested-updates using completion blocks (exactly how you described in your question).
Very recently, Firebase introduced cloud functions. I am utilizing this to watch the files that are uploaded, and then create a metadata entry into FB Database with the cloud function.
Basically, I use childByAutoId() to generate a key which is used to name the file. For example, profile pictures are saved at "gs://bucket-id/profile_pictures/somerandomkey.jpeg". Then I create a metadata entry into my FB database with cloud functions by utilizing the key from the filename.
I am not sure if there is a better way, but using cloud functions surely seems like a better approach than the nested-updates approach.
You can upload image using Firebase Storage, in success you get a downloadable URL of that image. Then put all the values in the custom object including that image URL and save that object in RealTime Database of Firebase.
And you can use the image URL by retrieving object from RealTime Database.