Loading image from Firebase Storage in Flutter App (Android, iOS & Web)
Target Audience: Beginner
Recipe: Implement loading image from Firebase Storage on Flutter Native and Flutter WebApp.
Goal: In this code recipe, we'll do following:
- Touch basing Firebase Project and configuration setup.
- Touch basing availability of two sample images in Storage using Firebase Console.
- Fetching one of the image randomly from Firebase Storage.
- Checkout code for loading image in native and web app.
Android:
iOS:
Flutter Web:
Checkout the Youtube video:
Lets's go!
This code recipe would demonstrate image Loading from Firebase Storage in Flutter Native and Web Apps.
pubspec.yaml
dependencies
Step #1. Flutter plugin for accessing images in FirebaseStorage for Native apps:
dependencies:
firebase_storage: ^3.0.8
firebase_core: ^0.4.0+9
firebase_analytics: ^5.0.6
Flutter plugin for accessing files in Firebase Storage for Web apps:
dependencies:
firebase: ^5.0.4
Step #2. Firebase Project review
Project Setup:
Make sure that your Firebase project is configured for all three platforms.
- Android: Checkout this link to configure Firebase project for Android app.
- iOS: Checkout this link to configure Firebase project for iOS app.
- Web: Checkout this link to configure Firebase project for Flutter Web app.
Images in Firebase Storage Console:
I've uploaded two images in Storage as shown in screenshot below.
Don't forget to tune Firebase Storage files 'Rules' depending on your usage. For demonstration purposes for this code recipe, I want to let user read images regardless of their authentication status. So, I'm making images readable to all as shown in screenshot below:
Step #3. Code Structure for loading image
I'll be using StatefulWidget
to load image since I'll be toggling between two images available in my FirebaseStorage bucket. FutureBuilder
widget is used to fetch the image from the Storage, and display the image depending on the connectionState and successful image retrieval.
class LoadFirbaseStorageImage extends StatefulWidget {
@override
_LoadFirbaseStorageImageState createState() =>
_LoadFirbaseStorageImageState();
}
class _LoadFirbaseStorageImageState extends State<LoadFirbaseStorageImage> {
...
Expanded(
...
//Image Loading code goes here
child: FutureBuilder(
future: _getImage(context, image),
builder: (context, snapshot) {
if (snapshot.connectionState ==
ConnectionState.done)
return Container(
height:
MediaQuery.of(context).size.height / 1.25,
width:
MediaQuery.of(context).size.width / 1.25,
child: snapshot.data,
);
if (snapshot.connectionState ==
ConnectionState.waiting)
return Container(
height: MediaQuery.of(context).size.height /
1.25,
width: MediaQuery.of(context).size.width /
1.25,
child: CircularProgressIndicator());
return Container();
},
),
),
...
//This is button to toggle image.
loadButton(context),
}
_getImage(...)
is responsible for directing the call to appropriate library targeted to specific platform. For example, native or web. FireStorageService
is the interface that internally fetches image using the correct platform specific library.
Future<Widget> _getImage(BuildContext context, String image) async {
Image m;
await FireStorageService.loadImage(context, image).then((downloadUrl) {
m = Image.network(
downloadUrl.toString(),
fit: BoxFit.scaleDown,
);
});
return m;
}
Checkout this plugins directory to familiarize yourself with the platform specific call re-direction.
File file_storage_service.dart
uses dart.library
to decide on redirecting calls to native vs web implementation for FireStorageService
.
export 'unsupported_storage.dart'
if (dart.library.html) 'web_storage.dart'
if (dart.library.io) 'mobile_storage.dart';
Any platform which is not web or native falls back to unsupported_storage.dart
file:
import 'package:flutter/material.dart';
class FireStorageService extends ChangeNotifier {
FireStorageService._();
FireStorageService();
static Future<dynamic> loadImage(BuildContext context, String image) {
throw ("Platform not found");
}
}
Note: Checkout my previous article about plugins directory structure in details, and supporting web and native app's from single source code.
Step #4. Loading Image in Flutter Native App
Let's take a look at Native variant of FireStorageService
in mobile_storage.dart
file below:
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
class FireStorageService extends ChangeNotifier {
FireStorageService();
static Future<dynamic> loadImage(BuildContext context, String image) async {
return await FirebaseStorage.instance.ref().child(image).getDownloadURL();
}
}
Step #5. Loading Image in Flutter Web App
Let's move on to Web variant of FireStorageService
in web_storage.dart
file below:
import 'package:firebase/firebase.dart';
import 'package:flutter/material.dart';
class FireStorageService extends ChangeNotifier {
FireStorageService() {
initializeApp(
apiKey: "AIzaSyDEktNdn4CsMUxeOyVkPFBnaoAdNhcpEPc",
authDomain: "fir-recipes-b5611.firebaseapp.com",
databaseURL: "https://fir-recipes-b5611.firebaseio.com",
projectId: "fir-recipes-b5611",
storageBucket: "fir-recipes-b5611.appspot.com",
messagingSenderId: "728428768644");
}
static Future<dynamic> loadImage(BuildContext context, String image) async {
var url = await storage().ref(image).getDownloadURL();
return url;
}
}
Please note that you would need to provide Firebase web project configuration to access storage()
instance for web.
Checkout the source code for detailed implementation. As usual, this code recipe is linked from main flutter_widgets code recipes sample app.
Source code repo
References:
- Configure Firebase project for Flutter Native Android app
- Configure Firebase project for Flutter Native iOS app
- Configuring Firebase project for Flutter Web app
- Previous article about supporting web and native app's from single source code.
Happy cooking with Flutter
Liked the article ? Couldn't find a topic of your interest ? Please leave comments or email me about topics you would like me to write
Follow me at twitter