AngularFire & Firebase SDK


#1

I’ve been trying to get photo uploads to firebase storage working.

However in the tutorials I’ve been following, they require me to use ‘firebase.initialiseApp(firebase_config)’.
I am getting an error telling me that the app is already initialised and I think that is because I’m using AngularFire also… and I’ve initialised the app like so ‘AngularFireModule.initializeApp(firebase_config)’ elsewhere.

Because of this the photos I take on my device aren’t being uploaded to my firebase storage.

Please help,
Thanks


#2

I’m using:

    "angularfire2": "^5.0.0-rc.6.0",

In your CoreModule you should initialise the AngularFireModule:

...

import { AngularFireModule } from 'angularfire2';
import { AngularFirestore, AngularFirestoreModule } from 'angularfire2/firestore';
import { AngularFireAuthModule } from 'angularfire2/auth';

import { ENV } from '@env';

...

@NgModule({
  imports: [
    CommonModule,
    IonicModule,
    AngularFireModule.initializeApp(ENV.firebase),
    AngularFirestoreModule,
    AngularFireAuthModule,

    ...

    ServiceWorkerModule.register('/ngsw-worker.js', { enabled: ENV.production })
  ],
  exports: [],
  declarations: [],
  providers: [
    AuthService,
    { provide: ErrorHandler, useClass: IonicErrorHandler },
    { provide: LoggerService, useClass: ConsoleLoggerService },

    ...

  ]
})
export class CoreModule {
  constructor( private afs: AngularFirestore,
               @Optional() @SkipSelf() parentModule: CoreModule) {

    throwIfAlreadyLoaded(parentModule, 'CoreModule');

    const settings = { timestampsInSnapshots: true };
    afs.app.firestore().settings(settings);
  }
}

You don’t need to call:

firebase.initialiseApp(firebase_config);

#3

Don’t do this. AngularFire has changed dramatically in the last few months to include Firestore, and is just now releasing version 7. Start with the official documentation. I bet almost all tutorials on the web are out of date.


#4

Thanks for the info…

However that still doesn’t sort the problem out.
In my app.module file I am initialising Firebase like so…

@NgModule({
  declarations: [
    MyApp
  ],
  imports: [
    BrowserModule,
    IonicModule.forRoot(MyApp), 
    AngularFireModule.initializeApp(FIREBASE_CONFIG), 
    AngularFireAuthModule, 
    AngularFireDatabaseModule, 
    AngularFirestoreModule,
    AngularFireStorageModule
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp
  ],
  providers: [
    StatusBar,
    SplashScreen,
    FileChooser,
    File,
    Geolocation,
    Camera,
    { provide: ErrorHandler, useClass: IonicErrorHandler }, 
    AuthService, 
    DataService
  ]
})

While in my page that requires the photo to be uploaded to Firebase, I am using…

async takePhoto()
  {
    try
    {
      // Defining camera options
      const options: CameraOptions = 
      {
        quality: 50, 
        targetHeight: 600, 
        targetWidth: 600, 
        destinationType: this.camera.DestinationType.DATA_URL, 
        encodingType: this.camera.EncodingType.JPEG,
        mediaType: this.camera.MediaType.PICTURE
      }
      // take picture with camera
      const result = await this.camera.getPicture(options)

      const image = `data:image/jpeg;base64,${result}`;

      const pictures = this.afStorage.ref('Profile Pictures');
      pictures.putString(image, 'data_url');
    }
    catch(e) 
    {
      console.error(e);
    }
  }

I receive no error, but the photo doesn’t get uploaded to Firebase storage, any ideas?

Thanks


#5

Are you still getting this error?

What version of Angularfire2 are you using, for example:

"angularfire2": "^5.0.0-rc.6.0",

If you are using the latest version ‘5.0.0-rc.6.0’ you should see errors in the DevTools console unless you set:

const settings = { timestampsInSnapshots: true };
afs.app.firestore().settings(settings);

Camera wise you can try:

<input type="file" accept="image/*;capture=camera">

See: iOS 11 its not me its you (tags: iOS11, PWA, Camera)


#6

Try:

const image = 'data:image/jpeg;base64,' + result;
this. afStorage.ref('cool.jpeg').putString(image, 'data_url');

See: https://github.com/angular/angularfire2/issues/1439


#7

Robinyo,

I am using version…

"angularfire2": "^5.0.0-rc.6.0"

I followed the video below from Paul Halliday, notice how at around the 6.10 mark of the video, he initializes the app with firebase. However I already have my app initialized with angularfire… So to avoid this error, I commented out the ‘initializeApp(FIREBASE_CONFIG)’ as shown in the video. I now get no error but the pictures dont upload to firebase.
I’m nearly sure its because I’m setting up my reference to storage the wrong way, but not sure how.


#8

That is why avoid AngularFire at all and just insert the firebase object to use the regular js api. The web sdk documentation is always more up to date and more comprehensive to use. And creating an observable on realtime data isn’t that difficult, abolishing the need for AngularFire imho at all.

In fact, you just need to make one provider that caters these needs for the rest of all your projects.


#9

Hi Tommertom,

If i’m already using AngularFire in my project to read and write data to the real-time database, should I just change my whole project to get rid of AngularFire?

Is there definitely no way to only use the Firebase SDK for connecting to Storage, while leaving my AngularFire connections with the database the same?

Thanks for your patience


#10

Pt 1: well that is what I would do. But there is a large group of AngularFire fans around there who will disagree. I recently removed AngularFire from my project and was surprised how easy it actually was. Only the stuff on Observables will require a bit of work and testing. All depending how deeply rooted u are using it.

Pt2: while I would think this is possible, it isn’t very clean to mix two different API approaches to the same cloud. May result in conflicts as it requires two instances of the firebase stuff


#11

No problem thanks for the information,

I’ll try to refactor my code to include only the Firebase SDK as opposed to AngularFire.
Fingers crossed :slight_smile:

Thanks again


#12

Eh, if you fix a stable configuration, AF is a lot smoother if you manipulate a lot of Observables. People have problems if they either update a lot, or aren’t comfortable with Observables. Even Firebase introduced breaking changes in 4.8, not waiting for version 5. Bottom line: Firebase is a production product, and AF is a release candidate, that was in beta for years.

AF trying to deal with Firebase Storage is brand new, and I don’t know how stable it is. I use AF2 for an email implementation, and Firebase Storage SDK for images.


#13

Aaron that’s exactly what I am getting at.

I have used AF for my authentication and real-time database connections… but I want to use Firebase Storage SDK for storing images.

How did you do this without initializing the app twice… both with the angular fire module & firebase?

Thanks


#14

With AF 6.0 I broke it down into two files: a config file and an import-into-module file. You can just do everything in app.module.ts if you want, maybe I was too cute.

Config file:

// AngularFire config

import { AngularFireModule } from 'angularfire2';
import { AngularFireAuthModule } from 'angularfire2/auth';
import { AngularFirestoreModule } from 'angularfire2/firestore'


const myFirebaseConfig = { 
    apiKey: 
    authDomain: 
    databaseURL:
    projectId: 
    storageBucket: 
    messagingSenderId:
  }

export const ANGULAR_FIRE_CONFIG = [
  AngularFireModule.initializeApp(myFirebaseConfig),
  AngularFireAuthModule,
  AngularFirestoreModule
]

Installing AF automatically installs Firebase. So in the image manager provider I put
import firebase from 'firebase';
and then used it, for example here’s a method that checks whether an item exists at a storage location:

private existsInStorage(refToCheck: firebase.storage.Reference): Promise<boolean> {
    return <Promise<boolean>> refToCheck.getDownloadURL()
                                        .then(_ => true,
                                              err => this.processErrorCodeForNonexistence(err));
  }

  private processErrorCodeForNonexistence(err: any): boolean {
    if (err.code === 'storage/object-not-found') {
      return false
    }
    else {
      // error handler that doesn't matter for this topic
    }
  }

#15

AngularFire is awesome if you need to wrap the Firebase SDK in RxJS to use Observables etc. If you don’t need that, I’d also discourage you from even using AngularFire at all, simply because the versioning and interdependency with the various Firebase versions out there now and its typings, as well as Firebase’s typings, are just a mess.

I use AngularFire wherever I need Observables. Everywhere else I just use the Firebase SDK directly. That includes Auth and Storage… perfectly fine without AngularFire.

To make the two SDKs coexist and avoid initializing twice, you can do this:

if (!firebase.apps.length) //<-- https://goo.gl/njMgt2
    firebase.initializeApp(FIREBASE_CONFIG);

Use it in all your providers that use Firebase. Basically, it avoids initializing twice if/when initializing already happened…