12

I am searching for a way, to cache images from the storage on google firebase platform. For now, I can download images, and show these to users, but I am not able to cache this, and access, even without internet connection. The database can be accessed offline. So I thought, there would be a way for storage too. I don't want to download every single image to storage, cause then I would need to check everytime, if the image is still up to date, it may be changed. Here are few links, what I could find, but no answer for my question. Maybe someone know a workaround, or a way how to accomplish it. Thanks!

Download files: https://firebase.google.com/docs/storage/android/download-files

Cache (offline) database: https://firebase.google.com/docs/database/android/offline-capabilities

UPDATE 1

Here is how I "cache" files with picasso, I added activity, that cares the download:

Picasso.with(getApplicationContext())
                            .load(uri.toString())
                            .networkPolicy(NetworkPolicy.OFFLINE)
                            .into(image1);

Any help is welcome. Thanks!

Vini.g.fer
  • 11,639
  • 16
  • 61
  • 90
Wladislaw
  • 1,200
  • 2
  • 12
  • 23

3 Answers3

9

I'm afraid the Firebase SDK doesn't provide image caching by itself. But there are several great libraries that could do it for you. They download image, show it in an ImageView and cache it in a single line of code. Just request the Firebase for an image download url and feed it to the image caching library.

Something like this, if you choose Picasso as a caching library:

storageRef.child("users/me/profile.png").getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
    @Override
    public void onSuccess(Uri uri) {
        // Got the download URL for 'users/me/profile.png'
        // Pass it to Picasso to download, show in ImageView and caching
        Picasso.with(context).load(uri.toString()).into(imageView);
    }
}).addOnFailureListener(new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception exception) {
        // Handle any errors
    }
});

UPD: To use disk caching with Picasso you need to explicitly setup OkHttpDownloader. Look here How do I use disk caching in Picasso?

Community
  • 1
  • 1
  • 2
    i already tried picasso, exactly the way you provided. The thing is, if i restart the app, without internet, images are not showing up...is there something i have to say, to store the images? Or maybe i need permission to storage? – Wladislaw Jun 08 '16 at 12:05
  • Right, there is a catch: to use disk caching with Picasso you need to explicitly setup OkHttpDownloader. Look here http://stackoverflow.com/questions/23978828/how-do-i-use-disk-caching-in-picasso – Aleksei Reshetnikov Jun 08 '16 at 12:22
  • Okay, i implemented this one. Now i can see blue symbol, that means it is on disk. But whenever i disconnect me from wifi, and becomes offline, this is what i get in Logcat... `W/ExponenentialBackoff: network unavailable, sleeping.` – Wladislaw Jun 08 '16 at 12:32
  • Seems like firebase can't fetch file reference while offline. Had you setup firebase persistence? `FirebaseDatabase.getInstance().setPersistenceEnabled(true);` – Aleksei Reshetnikov Jun 08 '16 at 12:54
  • Yes i did, but is this not only for database? And not the storage. As i said, my database strings are stored localy, and i can access them while i am offline. – Wladislaw Jun 08 '16 at 12:56
  • Before that I was sure the persistence includes file references. Probably I was wrong. In that case I couldn't help you. – Aleksei Reshetnikov Jun 08 '16 at 13:00
  • 3
    Firebase Storage is separate from the Database and this `setPersistenceEnabled(true)` doesn't work. We're investigating a built-in cache for enabling offline use cases (and improving performance), but we don't have concrete plans yet, so we recommend using image loading libraries like Picaso, Glide, and SDWebImage (iOS) for this use case. – Mike McDonald Jun 08 '16 at 14:37
  • @mike-mcdonald is it mean there is no offline access to files urls also? – Aleksei Reshetnikov Jun 08 '16 at 15:09
  • If you use a disk cache, then the files will be cached for offline access. – Mike McDonald Jun 08 '16 at 15:13
  • 7
    It's so, but to fetch a file from the cache I need to specify it's original url, which I can obtain only from the firebase storage. Am I missing smth? – Aleksei Reshetnikov Jun 08 '16 at 15:20
  • 1
    When you store the image you get a Snapshot with a downloadURL - store this URL in your database instead of the image name, so you don't have to do storageRef.child("users/me/profile.png").getDownloadUrl() – N.J. Jun 22 '17 at 10:06
  • @Wladislaw, I have restarted my real device (API level 25) and the images continues to show up even without internet connection. `/data/data/com.example.myapp/cache/picasso-cache` is the hard disk path where `Picasso` saves the image. – Aliton Oliveira Jun 10 '19 at 23:29
7

Thanks to @ATom for notice. Api has changed, and FirebaseUI 3.0 now uses Glide 4.x Here is updated sample:

To load an image from a StorageReference, first register in your AppGlideModule:

@GlideModule
public class MyAppGlideModule extends AppGlideModule {

    @Override
    public void registerComponents(Context context, Glide glide, Registry registry) {
        // Register FirebaseImageLoader to handle StorageReference
        registry.append(StorageReference.class, InputStream.class,
                new FirebaseImageLoader.Factory());
    }
}

Then you can load a StorageReference into an ImageView:

// Reference to an image file in Cloud Storage
StorageReference storageReference = ...;

// ImageView in your Activity
ImageView imageView = ...;

// Download directly from StorageReference using Glide
// (See MyAppGlideModule for Loader registration)
GlideApp.with(this /* context */)
        .load(storageReference)
        .into(imageView);

And don't forget to add dependency in your build.gradle:

implementation 'com.firebaseui:firebase-ui-:3.1.0'

Answer source on GitHub

Old answer:

FirebaseUI 1.0 now released. Storage example has class FirebaseImageLoader

Images displayed using FirebaseImageLoader are cached by their path in Firebase Storage, so repeated loads will be fast and conserve bandwidth.

    // Reference to an image file in Firebase Storage
    StorageReference storageReference = ...;

    // ImageView in your Activity
    ImageView imageView = ...;

    // Load the image using Glide
    Glide.with(this /* context */)
            .using(new FirebaseImageLoader())
            .load(storageReference)
            .into(imageView);
Dmytro Rostopira
  • 10,588
  • 4
  • 64
  • 86
2

I had the same issue. Tried all possible ways but couldn't fix that. I think the problem lies with the links generated by firebase storage. Picasso generally caches the images it loads. I have tried other cloud services like cloudinary, LibPixel whose links end with image format (Eg:.jpg) and picasso caches these link images. While firebase links end with token numbers. Strange thing it fails!

Nihal
  • 740
  • 9
  • 15