-
Notifications
You must be signed in to change notification settings - Fork 445
How to integrate Firebase across all platforms (web nativescript desktop)
This page shows how to integrate Firebase into the seed. Huge thank you to Scott Lowe.
There's a plugin for adding firebase to nativescript, but it doesn't have the same API as the web SDK. To accomodate this, we create one service for each platform (web and native), then swap the implementation during setup, depending on the platform.
Open your Firebase project at the Google console and follow the instructions for adding Firebase to your Android/iOS app to get the google-services.json
and GoogleService-Info.plist
files. (Make sure the package name for android matches your nativescript.id
in ./nativescript/package.json
)
Android
- Copy
google-services.json
into./nativescript/platforms/android/
- Update
./nativescript/platforms/android/build.gradle
:
-
Add google-services classpath dependency:
... dependencies { classpath "com.android.tools.build:gradle:1.5.0" classpath "com.google.gms:google-services:3.0.0" } ...
-
Add
applicationId
andmultiDexEnabled
to the defaultConfig (replacecom.yourdomain.appname
with yournativescript.id
from./nativescript/package.json
):... defaultConfig { minSdkVersion 17 targetSdkVersion computeTargetSdkVersion() applicationId "com.yourdomain.appname" multiDexEnabled true } ...
-
Apply plugin at the end of the file:
... dependsOn deleteExplodedAarFolder } apply plugin: "com.google.gms.google-services"
- Verify you have the correct versions of Google Play Services (rev 30) and Google Repository (rev 26) installed
iOS
- Copy
GoogleService-Info.plist
into./nativescript/app/App_Resources/iOS/
- From the root of the seed (not the nativescript folder) run
npm install firebase --save
- Update project config (
./tools/config/project.config.ts
) to add dependency for web support:
let additionalPackages: ExtendPackages[] = [{
name: 'firebase',
// Path to the package's bundle
path: 'node_modules/firebase/firebase.js'
}];
this.addPackagesBundles(additionalPackages);
We will be using your-folder
folder as an example here.
-
src/client/app/shared/your-folder/index.ts
to contain the token
import {InjectionToken} from '@angular/core';
export const FIREBASE: InjectionToken = new InjectionToken('firebase');
- Create
NSDatabaseService
in./nativescript/src/mobile/core/services/database.service.ts
:
import {Injectable, Inject, NgZone} from '@angular/core';
import {FIREBASE} from '../../../app/shared/your-folder/index'
@Injectable()
export class NSDatabaseService {
private database:any;
private onSync:Function;
private userID:string;
constructor(@Inject(FIREBASE) firebase:any, private ngZone: NgZone) {
console.log('Constructing NSDatabaseService');
this.database = firebase;
this.database.init({
persist: true // Allow disk persistence. Default false.
}).then((instance:any) => {
console.log('firebase.init successful');
}, (error:any) => {
console.log('firebase.init error: ' + error);
});
}
sync(path: string, onValueReceived: Function):void {
this.database.addValueEventListener((result:any) => {
this.ngZone.run(() => {
onValueReceived(result.value);
});
}, path);
}
addChild(path:string, data:any, callback?:Function):void {
this.database.push(path, data).then((result:any) => {
console.log('created key: ' + result.key);
if (callback) {
this.ngZone.run(() => {
callback(result.key);
});
}
});
}
}
- Add a line to
./nativescript/src/mobile/core/index.ts
to export your new service:
export * from './services/database.service';
- Create
DatabaseService
in./src/client/app/shared/your-folder/services/database.service.ts
:
import {Injectable, Inject, NgZone} from '@angular/core';
import {FIREBASE} from '../../your-folder/index';
@Injectable()
export class DatabaseService {
private database:any;
private onSync:Function;
private userID:string;
constructor(@Inject(FIREBASE) firebase:any, private ngZone: NgZone) {
console.log('Constructing DatabaseService');
// Initialize Firebase
var config = {
// your web config from Firebase console
};
firebase.initializeApp(config);
this.database = firebase.database();
}
sync(path: string, onValueReceived: Function):void {
this.database.ref(path).on('value', (snapshot:any) => {
this.ngZone.run(() => {
onValueReceived(snapshot.val());
});
});
}
addChild(path: string, data:any, callback?:Function):void {
this.database.ref(path).push(data, (err:any) => {
if (callback && !err) {
this.ngZone.run(() => {
callback();
});
}
});
}
}
- Modify
./src/client/app/shared/your-folder/index.ts
to export your new service:
export * from './services/database.service';
- Configure
./nativescript/src/native.module.ts
to useNSDatabaseService
:
...
import {FIREBASE} from './app/shared/your-folder/index';
var firebase = require('nativescript-plugin-firebase');
export function firebaseFactory() {
return firebase;
}
@NgModule({
// other imports, etc.
providers: [
NS_ANALYTICS_PROVIDERS,
{ provide: RouterExtensions, useClass: TNSRouterExtensions }
{ provide: FIREBASE, useFactory: (firebaseFactory) }
],
bootstrap: [NSAppComponent]
]);
- Configure
./src/client/web.module.ts
to useDatabaseService
:
...
import {FIREBASE} from './app/shared/your-folder/index';
var firebasePlugin = require('firebase');
export function firebaseFactory() {
return firebasePlugin.firebase;
}
@NgModule({
// other imports, etc.
providers: [
{
provide: APP_BASE_HREF,
useValue: '<%= APP_BASE %>'
},
{
provide: FIREBASE, useFactory: (firebaseFactory)
}
],
bootstrap: [AppComponent]
})
Simply inject the DatabaseService as you would any other provider to interact with firebase, regardless of which platform you're on.
Example with the home component, ./src/client/app/components/home/home.component.ts
:
// libs
import {Store} from '@ngrx/store';
// app
import {NameListService} from '../../shared/app/index';
import {DatabaseService} from '../../shared/core/services/database.service';
@Component({
moduleId: module.id,
selector: 'sd-home',
templateUrl: 'home.component.html',
styleUrls: ['home.component.css']
})
export class HomeComponent {
public newName: string = '';
constructor(private store: Store<any>, public nameListService: NameListService, private databaseService: DatabaseService) {
let count = 0;
databaseService.sync('counters', (data:any) => {
console.log('Synced path updated', data);
});
setInterval(() => {
databaseService.addChild('counters', count++);
}, 3000);
}
/*
* @param newname any text as input.
* @returns return false to prevent default form submit behavior to refresh the page.
*/
addName(): boolean {
this.nameListService.add(this.newName);
this.newName = '';
return false;
}
}
Our service currently only supports addChild
and sync
. To add more functionality (such as auth), simply add new methods to DatabaseService
/NSDatabaseService
that consume their respective web
/native
firebase dependencies.