mirror of
https://github.com/zhigang1992/react-native-firebase.git
synced 2026-01-12 22:50:20 +08:00
[docs] version docs
This commit is contained in:
3
docs/_navbar.md
Normal file
3
docs/_navbar.md
Normal file
@@ -0,0 +1,3 @@
|
||||
- <div style="padding: 8px; border-radius: 3px; border: 1px solid #e3e3e3;"><b>Version:</b> v3.x.x</div>
|
||||
- [v2.x.x](/v2/)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>react-native-firebase - A react native firebase library supporting both android and ios native firebase SDK's</title>
|
||||
<title>React Native Firebase - A react native firebase library supporting both android and ios native firebase SDK's</title>
|
||||
<meta name="description" content="A react native firebase library supporting both android and ios native firebase SDK's">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
<link rel="shortcut icon" type="image/png" href="https://camo.githubusercontent.com/6c827e5a0bb91259f82a1f4923ab7efa4891b119/687474703a2f2f692e696d6775722e636f6d2f303158514c30782e706e67"/>
|
||||
@@ -12,28 +12,30 @@
|
||||
</body>
|
||||
<script>
|
||||
window.$docsify = {
|
||||
name: 'react-native-firebase',
|
||||
name: 'React Native Firebase - Documentation',
|
||||
repo: 'https://github.com/invertase/react-native-firebase',
|
||||
loadSidebar: true,
|
||||
loadNavbar: true,
|
||||
mergeNavbar: true,
|
||||
search: 'auto',
|
||||
themeColor: '#f5820b',
|
||||
subMaxLevel: 3,
|
||||
maxLevel: 4,
|
||||
ga: 'UA-98196653-1',
|
||||
formatUpdated: '{DD}/{MM}/{YYYY} {HH}:{mm}',
|
||||
plugins: [
|
||||
function (hook) {
|
||||
var footer = [
|
||||
'<hr/>',
|
||||
'<footer>',
|
||||
`<span>Caught a mistake or want to contribute to the documentation? <a href="https://github.com/invertase/react-native-firebase/tree/master/docs" target="_blank">Edit documentation on Github!</a>.</span>`,
|
||||
'</footer>'
|
||||
].join('');
|
||||
|
||||
hook.afterEach(function (html) {
|
||||
return html + footer
|
||||
function(hook, vm) {
|
||||
hook.beforeEach(function (html) {
|
||||
var url = 'https://github.com/invertase/react-native-firebase/blob/master/docs/' + vm.route.file;
|
||||
var editHtml = '[:memo: Edit](' + url + ')\n';
|
||||
return editHtml
|
||||
+ html
|
||||
+ '\n----\n'
|
||||
+ '<b>Last updated</b>: {docsify-updated} '
|
||||
+ editHtml
|
||||
})
|
||||
}
|
||||
]
|
||||
],
|
||||
}
|
||||
</script>
|
||||
<script>
|
||||
|
||||
66
docs/v2/README.md
Normal file
66
docs/v2/README.md
Normal file
@@ -0,0 +1,66 @@
|
||||
|
||||
<h1 align="center">
|
||||
<img src="https://camo.githubusercontent.com/6c827e5a0bb91259f82a1f4923ab7efa4891b119/687474703a2f2f692e696d6775722e636f6d2f303158514c30782e706e67"/><br>
|
||||
|
||||
React Native Firebase
|
||||
</h1>
|
||||
|
||||
<div style="text-align: center;">
|
||||
[](https://www.npmjs.com/package/react-native-firebase)
|
||||
[](https://www.npmjs.com/package/react-native-firebase)
|
||||
[](http://packagequality.com/#?package=react-native-firebase)
|
||||
[](/LICENSE)
|
||||
[](https://discord.gg/t6bdqMs)
|
||||
[](https://gitter.im/invertase/react-native-firebase)
|
||||
[](https://www.patreon.com/invertase)
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
RNFirebase is a _light-weight_ layer sitting on-top of the native Firebase libraries for both iOS and Android which mirrors the Firebase Web SDK as closely as possible.
|
||||
|
||||
Although the [Firebase Web SDK](https://www.npmjs.com/package/firebase) library will work with React Native, it is mainly built for the web.
|
||||
|
||||
RNFirebase provides a JavaScript bridge to the native Firebase SDKs for both iOS and Android therefore Firebase will run on the native thread, allowing the rest of your app to run on the [JS thread](https://facebook.github.io/react-native/docs/performance.html#javascript-frame-rate). The Firebase Web SDK also runs on the JS thread, therefore potentially affecting the frame rate causing jank with animations, touch events etc.
|
||||
|
||||
The native SDKs also allow us to hook into device sdk's which are not possible with the web SDK, for example crash reporting, offline realtime database support, analyics and more!
|
||||
|
||||
All in all, RNFirebase provides much faster performance (~2x) over the web SDK and provides device sdk's not found in the web sdk (see the feature table below).
|
||||
|
||||
---
|
||||
|
||||
## Supported Firebase Features
|
||||
> The Web SDK column indicates what modules from the Firebase Web SDK are usable within React Native.
|
||||
|
||||
| Firebase Features | v1 | v2 | Web SDK |
|
||||
| ---------------------- | :---: | :---: | :---: |
|
||||
| AdMob | ❌ | ✅ | ❌ |
|
||||
| Analytics | ✅ | ✅ | ❌ |
|
||||
| App Indexing | ❌ | ❌ | ❌ |
|
||||
| Authentication | ✅ | ✅ | ✅ |
|
||||
| Cloud Messaging (FCM) | ✅ | ✅ | ❌ |
|
||||
| Crash Reporting | ✅ | ✅ | ❌ |
|
||||
| Dynamic Links | ❌ | ❌ | ❌ |
|
||||
| Invites | ❌ | ❌ | ❌ |
|
||||
| Performance Monitoring | ✅ | ✅ | ❌ |
|
||||
| Realtime Database | ✅ | ✅ | ✅ |
|
||||
| - Offline Persistence | ✅ | ✅ | ❌ |
|
||||
| - Transactions | ✅ | ✅ | ✅ |
|
||||
| Remote Config | ✅ | ✅ | ❌ |
|
||||
| Storage | ✅ | ✅ | ❌ |
|
||||
|
||||
---
|
||||
### Supported versions - React Native / Firebase
|
||||
|
||||
> The table below shows the supported version of `react-native-firebase` for different React Native versions
|
||||
|
||||
| | v0.36 - v0.39 | v0.40 - v0.46 | v0.47 +
|
||||
| ------------------------------- | :---: | :---: | :---: |
|
||||
| react-native-firebase | 1.X.X | 2.X.X | 2.1.X |
|
||||
|
||||
> The table below shows the minimum supported versions of the Firebase SDKs for each version of `react-native-firebase`
|
||||
|
||||
| | v1 | v2 |
|
||||
| ---------------------- | :---: | :---: |
|
||||
| Firebase Android SDK | 10.2.0+ | 11.0.0 + |
|
||||
| Firebase iOS SDK | 3.15.0+ | 4.0.0 + |
|
||||
3
docs/v2/_navbar.md
Normal file
3
docs/v2/_navbar.md
Normal file
@@ -0,0 +1,3 @@
|
||||
- <div style="padding: 8px; border-radius: 3px; border: 1px solid #e3e3e3;"><b>Version:</b> v2.x.x</div>
|
||||
- [v3.x.x](/)
|
||||
|
||||
34
docs/v2/_sidebar.md
Normal file
34
docs/v2/_sidebar.md
Normal file
@@ -0,0 +1,34 @@
|
||||
- Getting started
|
||||
- [Initial setup](/initial-setup)
|
||||
- [Installation - iOS](/installation-ios)
|
||||
- [Installation - Android](/installation-android)
|
||||
- [Usage](/usage)
|
||||
- [Migration Guide](/migration-guide)
|
||||
|
||||
- Contributing
|
||||
- [Guidelines](/contributing/guidelines)
|
||||
- [Testing](/contributing/testing)
|
||||
|
||||
- Core
|
||||
- [App](/core/app)
|
||||
- [Firebase](/core/firebase)
|
||||
|
||||
- Modules
|
||||
- [Admob](/modules/admob)
|
||||
- [Analytics](/modules/analytics)
|
||||
- [Authentication](/modules/authentication)
|
||||
- [Cloud Messaging](/modules/cloud-messaging)
|
||||
- [Crash Reporting](/modules/crash)
|
||||
- [Database](/modules/database)
|
||||
- [Remote Config](/modules/config)
|
||||
- [Storage](/modules/storage)
|
||||
- [Transactions](/modules/transactions)
|
||||
- [Performance Monitoring](/modules/perf)
|
||||
|
||||
- Other
|
||||
- [Usage with Redux](/redux)
|
||||
- [Project Board](https://github.com/invertase/react-native-firebase/projects)
|
||||
- [FAQs / Troubleshooting](/faqs)
|
||||
- [Examples](https://github.com/invertase/react-native-firebase-examples)
|
||||
- [Chat](https://discord.gg/t6bdqMs)
|
||||
- [Gitter](https://gitter.im/invertase/react-native-firebase)
|
||||
5
docs/v2/contributing/guidelines.md
Normal file
5
docs/v2/contributing/guidelines.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Guidelines
|
||||
|
||||
We welcome any contribution to the repository. Please ensure your changes to the JavaScript code follow the styling guides controlled by ESlint. Changes to native code should be kept clean and follow the standard of existing code.
|
||||
|
||||
Changes to existing code should ensure all relevant tests on the test app pass. Any new features should have new tests created and ensure all existing tests pass.
|
||||
330
docs/v2/contributing/testing.md
Normal file
330
docs/v2/contributing/testing.md
Normal file
@@ -0,0 +1,330 @@
|
||||
# Testing
|
||||
|
||||
Currently due to the blackbox Firebase enviroment, we have found the best way to test the library is to directly test against the library using a live Firebase project. As some modules also work with the offical web SDK, we can directly compare the results against our own library. This is however restrictive as it doesn't directly test the native code/modules. Plans are in place to overhaul the entire testing setup.
|
||||
|
||||
## Running the test app
|
||||
|
||||
For convenience all of the required NPM scripts are packaged with the main library to run the test app.
|
||||
|
||||
### Step 1 - Fork & Clone
|
||||
|
||||
```bash
|
||||
git clone git@github.com:<username>/react-native-firebase.git
|
||||
```
|
||||
|
||||
### Step 2 - Install dependencies
|
||||
|
||||
```bash
|
||||
npm run tests-npm-install
|
||||
```
|
||||
|
||||
|
||||
### Step 3 - Install [WML](https://github.com/wix/wml)
|
||||
|
||||
WML is a library which copies files & directories to a location. This allows us to copy any changes from the library directly into the tests app, so we can quickly test changes.
|
||||
|
||||
```bash
|
||||
npm install -g wml
|
||||
```
|
||||
|
||||
### Step 4 - Start the watcher
|
||||
|
||||
```bash
|
||||
npm run tests-watch-init
|
||||
npm run tests-watch-start
|
||||
```
|
||||
|
||||
### Step 5 - Start the app
|
||||
|
||||
```bash
|
||||
npm run tests-packager
|
||||
```
|
||||
|
||||
#### Android
|
||||
|
||||
Open the `tests/android` directory from Android Studio and allow Gradle to sync. Now run the app on an emulator/device.
|
||||
|
||||
#### iOS
|
||||
|
||||
First install the Pods:
|
||||
|
||||
```
|
||||
npm run tests-pod-install
|
||||
```
|
||||
|
||||
Open the `tests/ios/ReactNativeFirebaseDemo.xcworkspace` file in XCode and build for your preffered device or simulator.
|
||||
|
||||
## Tests
|
||||
|
||||
Tests are bootstrapped and ran when the `play` button is pressed. The status of each test suite and individual test will update as and when a test has completed or errored.
|
||||
|
||||
### Running tests
|
||||
|
||||
Tests can be run by pressing the play button in the toolbar of the app. Test can be run individually, by suite, or all at once.
|
||||
|
||||

|
||||
|
||||
|
||||
### Adding test
|
||||
|
||||
To add tests to an existing test suite, you need to pass a function to `addTests`.
|
||||
|
||||
#### Synchronous tests
|
||||
|
||||
Synchronous tests are created by passing a function to `it`. The next test is run immediately after the last line is executed.
|
||||
|
||||
```javascript
|
||||
testSuite.addTests(({ describe, it }) => {
|
||||
describe('synchronous test', () => {
|
||||
|
||||
it('does something correctly', () => {
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
#### Asynchronous tests
|
||||
|
||||
Tests can be asynchronous if they return a promise. The test suite waits for the promise to resolve before executing the next test.
|
||||
|
||||
```javascript
|
||||
testSuite.addTests(({ describe, it }) => {
|
||||
describe('async successful test', () => {
|
||||
|
||||
it('does something correctly', () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
// ...
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
Asynchronous tests can also be created using the `async` function syntax:
|
||||
|
||||
```javascript
|
||||
testSuite.addTests(({ describe, it }) => {
|
||||
describe('async successful test', () => {
|
||||
|
||||
it('does something correctly', async () => {
|
||||
// ...
|
||||
|
||||
await somethingAsynchronous();
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
> When rejecting, always ensure a valid [JavaScript Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) is provided.
|
||||
|
||||
### Creating a new test suite
|
||||
|
||||
A test suite groups together test categories under the same Firebase feature. e.g. *Realtime Database* tests.
|
||||
|
||||
To add a new test suite:
|
||||
|
||||
1. Create a new directory within `src/tests`.
|
||||
2. Create an `index.js` file.
|
||||
|
||||
In this file, you need to create an instance of `TestSuite` - see [TestSuite constructor](#testsuite-constructor).
|
||||
|
||||
```javascript
|
||||
import TestSuite from 'lib/TestSuite';
|
||||
|
||||
const MyNewSuite = new TestSuite('Realtime Database Storage', 'Upload/Download storage tests');
|
||||
|
||||
export default MyNewSuite;
|
||||
```
|
||||
|
||||
3. `addTests` is then used as many times as is necessary to add tests to the test suite, accepting a function that defines one or more tests.
|
||||
4. The test suite must then be imported into `src/tests/index.js` and added to `testSuiteInstances` in order for it to be included in the list of test suites available to run in the app.
|
||||
|
||||
## TestSuite API
|
||||
|
||||
### TestSuite Constructor
|
||||
|
||||
The TestSuite constructor accepts 3 arguments:
|
||||
|
||||
- **name**: String containing the name of the test suite. e.g. 'Realtime Storage'
|
||||
- **description**: String containing description of the test suite
|
||||
- **firebase**: This is the object exported from `src/firebase` and contains both the native and web firebase instances.
|
||||
|
||||
```javascript
|
||||
import firebase from '../firebase';
|
||||
|
||||
new TestSuite('Realtime Database Storage', 'firebase.database()', firebase);
|
||||
```
|
||||
|
||||
### Test Definition
|
||||
|
||||
#### describe()
|
||||
|
||||
The `describe()` function takes 2 - 3 arguments:
|
||||
|
||||
- **description**: String describing the context or target of all the tests defined in `testDefinitions`
|
||||
- **options**: (Optional) object of options:
|
||||
* **focus**: Boolean marking all the tests defined in `testDefinitions` (and any others marked as focused) as the only one(s) that should run
|
||||
* **pending**: Boolean marking all the tests defined in `testDefinitions` as excluded from running in the test suite
|
||||
- **testDefinitions**: Function that defines 1 or more tests by calling `it`, `xit` or `fit`
|
||||
|
||||
```javascript
|
||||
function testCategory({ describe }) {
|
||||
|
||||
describe('a feature', () => {
|
||||
it('does something synchronously', () => {
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
export default testCategory;
|
||||
```
|
||||
|
||||
`describe()` statements can be arbitrarily nested.
|
||||
|
||||
#### context()
|
||||
|
||||
`context()` is an alias for `describe()` provided as syntactical sugar. `xcontext()` and `fcontext()` work similar to `xdescribe()` and `fdescribe()`, respectively.
|
||||
|
||||
#### it()
|
||||
|
||||
The `it()` function takes 2 - 3 arguments:
|
||||
|
||||
- **description**: String describing the test defined in `testDefinition`
|
||||
- **options**: (Optional) object of options:
|
||||
* **focus**: Boolean marking the test defined in `testDefinition` (and any others marked as focused) as the only one(s) that should run
|
||||
* **pending**: Boolean marking the test defined in `testDefinition` as excluded from running in the test suite
|
||||
* **timeout**: Time in milliseconds a test is allowed to execute before it's considered to have timed out. Default is 5000ms (5 seconds).
|
||||
- **testDefinition**: Function that defines a test with one or more assertions. Can be a synchronous or asynchronous function. Functions that return a promise cause the test environment to wait for the promise to be resolved before proceding to the next test.
|
||||
|
||||
```javascript
|
||||
it('does something synchronously', () => {
|
||||
|
||||
});
|
||||
|
||||
it('does something asynchronously', async () => {
|
||||
|
||||
});
|
||||
|
||||
it('does something else asynchronously', () => {
|
||||
return new Promise(/* ... */);
|
||||
});
|
||||
```
|
||||
|
||||
`it()` statements can *not* be nested.
|
||||
|
||||
#### xdescribe() & xit()
|
||||
|
||||
##### Pending Tests
|
||||
|
||||
You can mark all tests within a `describe` statement as pending by using the `xdescribe` function instead. The test will appear greyed out and will not be run as part of the test suite.
|
||||
|
||||
You can mark a single test as pending by using `xit` as you would `it`.
|
||||
|
||||
Tests should only be marked as pending temporarily, and should not normally be committed to the test suite unless they are fully implemented.
|
||||
|
||||
#### fdescribe() & fit()
|
||||
|
||||
##### Focused Tests
|
||||
|
||||
You can mark all tests within a `describe` statement as focused by using the `fdescribe` function instead. Tests that are focused will be the only ones that appear and run in the test suite until all tests are removed from being focused. This is useful for running and working on a few tests at a time.
|
||||
|
||||
You can mark a single test as focused by using `fit` as you would `it`.
|
||||
|
||||
#### Test Assertions
|
||||
|
||||
The assertion library Should.js is used in the tests. The complete list of available assertions is available in the [Should.js documentation](https://shouldjs.github.io).
|
||||
|
||||
#### Lifecycle methods
|
||||
|
||||
Four lifecycle methods are provided for each test context:
|
||||
|
||||
- **before** - Run once, before the current test context executes
|
||||
- **beforeEach** - Run before every test in the current test context
|
||||
- **after** - Run once, after the current test context has finished executing
|
||||
- **afterEach** - Run after every test in the current test context
|
||||
|
||||
A new test context is created when the test suite encounters any of `describe`, `xdescribe`, `fdescribe`, `context`, `xcontext` or `fcontext`, and close again when it reaches the end of the block. Test contexts can be nested and lifecycle hooks set for parent contexts apply for all descendents.
|
||||
|
||||
Each lifecycle hook accepts either a synchronous function, a function that returns a promise or an `async` function.
|
||||
|
||||
```javascript
|
||||
function testCategory({ before, beforeEach, afterEach, after }) {
|
||||
|
||||
before(() => console.log('Before all tests start.'));
|
||||
beforeEach(() => console.log('Before every test starts.'));
|
||||
|
||||
describe('sync successful test', function() {
|
||||
// ...
|
||||
});
|
||||
|
||||
afterEach(() => console.log('After each test starts.'));
|
||||
after(() => console.log('After all tests are complete, with success or error.'));
|
||||
}
|
||||
```
|
||||
|
||||
An optional hash of options can also be passed as the first argument, defining one or more of the following values:
|
||||
|
||||
* **timeout**: Time in milliseconds a hook is allowed to execute before it's considered to have timed out. Default is 5000ms (5 seconds).
|
||||
|
||||
#### Accessing Firebase
|
||||
|
||||
`react-native-firebase` is available `firebase.native`:
|
||||
|
||||
```javascript
|
||||
function testCategory({ describe, firebase }) {
|
||||
|
||||
describe('sync successful test', 'category', function() {
|
||||
firebase.native.database();
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
If you need to access the web API for Firebase to compare with the functionality of `react-native-firebase`, you can access it on `firebase.web`.
|
||||
|
||||
> All tests should be written in terms of `react-native-firebase`'s behaviour and should **not** include direct comparisons with the web API. It's available for reference, only.
|
||||
|
||||
## Development Notes
|
||||
|
||||
> JavaScript changes do **not** require restarting the React Native packager to take effect
|
||||
|
||||
> Java changes will need to be rebuilt in Android Studio
|
||||
|
||||
> Objective-C changes need to be rebuilt in Xcode
|
||||
|
||||
### Debugging or viewing internals of the test suite
|
||||
|
||||
`react-native-firebase/tests` is compatible with [react-native-debugger](https://github.com/jhen0409/react-native-debugger) and is the recommended way to view the internal state of the test suite for development or troubleshooting.
|
||||
|
||||
It allows you to view state and prop values of the React component tree, view the actions and contents of the Redux store and view and interact with the debugging console.
|
||||
|
||||
Make sure **Remote JS Debugging** when running the application and close any chrome debugging windows that appear and start React Native Debugger.
|
||||
|
||||
### Running the internal tests
|
||||
|
||||
`react-native-firebase-tests` has its own tests to verify the testing framework is working as expected. These are run from the command line:
|
||||
|
||||
```bash
|
||||
npm run internal-tests
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Invalid React.podspec file: no implicit conversion of nil into String
|
||||
|
||||
This error occurs if you are using ruby version 2.1.2. Upgrade your version of ruby and try again.
|
||||
|
||||
|
||||
### Unable to resolve module ../../../node_modules/react-native/packager/...
|
||||
|
||||
Run the packager separately, clearing the cache:
|
||||
|
||||
```bash
|
||||
npm start -- --reset-cache
|
||||
```
|
||||
34
docs/v2/core/app.md
Normal file
34
docs/v2/core/app.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# App - firebase.app(): FirebaseApp
|
||||
|
||||
RNFirebase supports both initializing apps natively and also via js code over the RN bridge.
|
||||
|
||||
Apps initialized natively are available immediately at app runtime, there is no need to call `initializeApp` for them.
|
||||
|
||||
For example, to access the default app initialized via the `Google-Services` `plist` or `json` file:
|
||||
```javascipt
|
||||
import firebase from 'react-native-firebase';
|
||||
|
||||
const defaultApp = firebase.app();
|
||||
|
||||
defaultApp.database().ref('foobar').once('value', (snapshot) => {
|
||||
// snapshot from default app
|
||||
});
|
||||
|
||||
// get the default app name/options that were initialized natively
|
||||
console.log("name", defaultApp.name);
|
||||
console.log("apiKey", defaultApp.options.apiKey);
|
||||
console.log("applicationId", defaultApp.options.applicationId);
|
||||
console.log("databaseUrl", defaultApp.options.databaseUrl);
|
||||
console.log("messagingSenderId", defaultApp.options.messagingSenderId);
|
||||
console.log("projectId", defaultApp.options.projectId);
|
||||
console.log("storageBucket", defaultApp.options.projectId);
|
||||
```
|
||||
|
||||
|
||||
TODO api ref docs:
|
||||
|
||||
- name: String
|
||||
- options: Object
|
||||
- delete(): Promise
|
||||
|
||||
|
||||
10
docs/v2/core/firebase.md
Normal file
10
docs/v2/core/firebase.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# Firebase
|
||||
|
||||
TODO api ref docs:
|
||||
|
||||
- apps(): Array<FirebaseApp>
|
||||
- app(): FirebaseApp
|
||||
- initializeApp(): FirebaseApp
|
||||
- setLogLevel()
|
||||
- SDK_VERSION: String
|
||||
- googleApiAvailability: Object
|
||||
103
docs/v2/faqs.md
Normal file
103
docs/v2/faqs.md
Normal file
@@ -0,0 +1,103 @@
|
||||
# FAQs / Troubleshooting
|
||||
|
||||
## Usage with Expo
|
||||
|
||||
If you use Expo and would like to use this package, you'll need to eject. If you do not want to eject, but wish to make use of features
|
||||
such as Realtime Database (without offline support) & Authentication, you can still use the Firebase Web SDK in your project.
|
||||
|
||||
For features such a Crash Reporting, Push Notifications (via Firebase not Expo), Performance Monitoring, AdMob, Analytics, Storage & Remote Config, you will have to eject your Expo project as these require the native SDKs, as the Web SDK does not support these.
|
||||
|
||||
You can see an indepth conversation [here](https://expo.canny.io/feature-requests/p/full-native-firebase-integration).
|
||||
|
||||
## Comparison to Firestack
|
||||
|
||||
Firestack was a great start to integrating Firebase and React Native, however has underlying issues which needed to be fixed.
|
||||
A V3 fork of Firestack was created to help address issues such as lack of standardisation with the Firebase Web SDK,
|
||||
and missing core features (crash reporting, transactions etc). The volume of pull requests with fixes/features soon became
|
||||
too large to manage on the existing repository, whilst trying to maintain backwards compatibility.
|
||||
|
||||
RNFirebase was re-written from the ground up, addressing these issues with core focus being around matching the Web SDK as
|
||||
closely as possible and fixing the major bugs/issues along the way.
|
||||
|
||||
## [Android] Google Play Services related issues
|
||||
|
||||
The firebase SDK requires a certain version of Google Play Services installed on Android in order to function properly.
|
||||
|
||||
If the version of Google Play Services installed on your device is incorrect or non existent, React Native Firebase will throw a red box error, and your app will possibly crash as well. The red box error will have a numerical code associated with it. These codes can be found here:
|
||||
|
||||
https://developers.google.com/android/reference/com/google/android/gms/common/ConnectionResult#SERVICE_VERSION_UPDATE_REQUIRED
|
||||
|
||||
Here is a quick guide to some of the most common errors encountered:
|
||||
|
||||
code 2 - Google Play Services is required to run this application but no valid installation was found:
|
||||
|
||||
The emulator/device you're using does not have the Play Services SDK installed.
|
||||
|
||||
- Emulator: Open SDK manager, under 'SDK Tools' ensure "Google Play services, rev X" is installed. Once installed,
|
||||
create a new emulator image. When selecting your system image, ensure the target comes "with Google APIs".
|
||||
- Device: Play Services needs to be downloaded from the Google Play Store.
|
||||
|
||||
code 9 - The version of the Google Play services installed on this device is not authentic:
|
||||
|
||||
This error applies to modified or 'shimmed' versions of Google Play Services which you might be using in a third
|
||||
party emulator such as GenyMotion.
|
||||
|
||||
Using this kind of workaround with Google Play Services can be problematic, so we
|
||||
recommend using the native Android Studio emulators to reduce the chance of these complications.
|
||||
|
||||
## [Android] Turning off Google Play Services availability errors
|
||||
|
||||
G.P.S errors can be turned off using a config option like so:
|
||||
|
||||
```javascript
|
||||
const firebase = RNFirebase.initializeApp({
|
||||
errorOnMissingPlayServices: false,
|
||||
});
|
||||
```
|
||||
This will stop your app from immediately red-boxing or crashing, but won't solve the underlying issue of G.P.S not being available or of the correct version. This will mean certain functionalities won't work properly and your app may even crash.
|
||||
|
||||
## [Android] Checking for Google Play Services availability with React Native Firebase
|
||||
|
||||
React Native Firebase actually has a useful helper object for checking G.P.S availability:
|
||||
|
||||
```javascript
|
||||
const availability = firebase.googleApiAvailability;
|
||||
```
|
||||
|
||||
The availability object would then have the following properties that you can run checks against:
|
||||
|
||||
```javascript
|
||||
isAvailable: boolean
|
||||
```
|
||||
|
||||
and if not available (isAvailable === false):
|
||||
|
||||
```javascript
|
||||
isUserResolvableError: boolean
|
||||
```
|
||||
|
||||
This variable indicates whether or not the end user can fix the issue, for example by downloading the required version of Google Play Services. In a case such as a GenyMotion emulator, this would return false for missing G.P.S, as the end user can't add the package directly.
|
||||
|
||||
```javascript
|
||||
error: string
|
||||
```
|
||||
This error will match the messages and error codes mentioned above, and can be found here:
|
||||
|
||||
https://developers.google.com/android/reference/com/google/android/gms/common/ConnectionResult#SERVICE_VERSION_UPDATE_REQUIRED
|
||||
|
||||
|
||||
## [Android] Duplicate Dex Files error (build time error)
|
||||
|
||||
A common build time error when using libraries that require google play services is of the form:
|
||||
'Failed on android with com.android.dex.DexException: Multiple dex files... '
|
||||
|
||||
This error (https://github.com/invertase/react-native-firebase/issues/48) occurs because different versions of google play services or google play services modules are being required by different libraries.
|
||||
|
||||
The process to fix this is fairly manual and depends on your specific combination of external libraries. Essentially what's required is to check the app level build.gradle file of each external library and establish which ones have a Google Play Services dependency.
|
||||
|
||||
You then need to find the lowest common version of each G.P.S module dependency, require that in the app level build.gradle file of your own project, and exclude it from being required by the modules themselves. This will force the use of a consistent version of the G.P.S module.
|
||||
|
||||
It's not a good idea to modify the version within the library's build.gradle, as this will be overwritten when you update the library, which will lead to the build breaking again.
|
||||
|
||||
A good break down of this process can be found here:
|
||||
https://medium.com/@suchydan/how-to-solve-google-play-services-version-collision-in-gradle-dependencies-ef086ae5c75f
|
||||
21
docs/v2/initial-setup.md
Normal file
21
docs/v2/initial-setup.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Install the library
|
||||
|
||||
`npm install --save react-native-firebase`
|
||||
|
||||
# Initial Setup
|
||||
|
||||
The RNFirebase library is intended on making it easy to work with [Firebase](https://firebase.google.com/) and provides a small native shim to the Firebase native code.
|
||||
|
||||
To add Firebase to your project, make sure to create a project in the [Firebase console](https://firebase.google.com/console)
|
||||
|
||||

|
||||
|
||||
Each platform uses a different setup method after creating the project.
|
||||
|
||||
## iOS
|
||||
|
||||
For iOS, follow the instructions [here](/installation-ios).
|
||||
|
||||
## Android
|
||||
|
||||
For Android, follow the instructions [here](/installation-android).
|
||||
184
docs/v2/installation-android.md
Normal file
184
docs/v2/installation-android.md
Normal file
@@ -0,0 +1,184 @@
|
||||
# Android Installation
|
||||
|
||||
## 1) Setup google-services.json
|
||||
Download the `google-services.json` file provided by Firebase in the _Add Firebase to Android_ platform menu in your Firebase configuration console. This file should be downloaded to `YOUR_PROJECT/android/app/google-services.json`.
|
||||
|
||||
Next you'll have to add the google-services gradle plugin in order to parse it.
|
||||
|
||||
Add the google-services gradle plugin as a dependency in the *project* level build.gradle
|
||||
`android/build.gradle`
|
||||
```java
|
||||
buildscript {
|
||||
// ...
|
||||
dependencies {
|
||||
// ...
|
||||
classpath 'com.google.gms:google-services:3.0.0'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In your app build.gradle file, add the gradle plugin at the VERY BOTTOM of the file (below all dependencies)
|
||||
`android/app/build.gradle`
|
||||
```java
|
||||
apply plugin: 'com.google.gms.google-services'
|
||||
```
|
||||
|
||||
## 2) Link RNFirebase
|
||||
|
||||
RNFirebase is split into separate modules to allow you to only include the Firebase functionality that you need in your application.
|
||||
|
||||
First add the project path to `android/settings.gradle`:
|
||||
|
||||
```
|
||||
include ':react-native-firebase'
|
||||
project(':react-native-firebase').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-firebase/android')
|
||||
```
|
||||
|
||||
Now you need to include RNFirebase and the required Firebase dependencies in our `android/app/build.gradle` so that they are compiled as part of React Native. In the `dependencies` listing, add the appropriate `compile` lines:
|
||||
|
||||
```
|
||||
dependencies {
|
||||
// RNFirebase required dependencies
|
||||
compile(project(':react-native-firebase')) {
|
||||
transitive = false
|
||||
}
|
||||
compile "com.google.firebase:firebase-core:11.0.4"
|
||||
|
||||
// If you are receiving Google Play API availability issues, add the following dependency
|
||||
compile "com.google.android.gms:play-services-base:11.0.4"
|
||||
|
||||
// RNFirebase optional dependencies
|
||||
compile "com.google.firebase:firebase-ads:11.0.4"
|
||||
compile "com.google.firebase:firebase-analytics:11.0.4"
|
||||
compile "com.google.firebase:firebase-auth:11.0.4"
|
||||
compile "com.google.firebase:firebase-config:11.0.4"
|
||||
compile "com.google.firebase:firebase-crash:11.0.4"
|
||||
compile "com.google.firebase:firebase-database:11.0.4"
|
||||
compile "com.google.firebase:firebase-messaging:11.0.4"
|
||||
compile "com.google.firebase:firebase-perf:11.0.4"
|
||||
compile "com.google.firebase:firebase-storage:11.0.4"
|
||||
}
|
||||
```
|
||||
|
||||
To install `react-native-firebase` in your project, you'll need to import the packages you need from `io.invertase.firebase` in your project's `android/app/src/main/java/com/[app name]/MainApplication.java` and list them as packages for ReactNative in the `getPackages()` function:
|
||||
|
||||
```java
|
||||
package com.youcompany.application;
|
||||
// ...
|
||||
// Required package
|
||||
import io.invertase.firebase.RNFirebasePackage; // <-- Add this line
|
||||
// Optional packages - add as appropriate
|
||||
import io.invertase.firebase.admob.RNFirebaseAdMobPackage; //Firebase AdMob
|
||||
import io.invertase.firebase.analytics.RNFirebaseAnalyticsPackage; // Firebase Analytics
|
||||
import io.invertase.firebase.auth.RNFirebaseAuthPackage; // Firebase Auth
|
||||
import io.invertase.firebase.config.RNFirebaseRemoteConfigPackage; // Firebase Remote Config
|
||||
import io.invertase.firebase.crash.RNFirebaseCrashPackage; // Firebase Crash Reporting
|
||||
import io.invertase.firebase.database.RNFirebaseDatabasePackage; // Firebase Realtime Database
|
||||
import io.invertase.firebase.messaging.RNFirebaseMessagingPackage; // Firebase Cloud Messaging
|
||||
import io.invertase.firebase.perf.RNFirebasePerformancePackage; // Firebase Performance
|
||||
import io.invertase.firebase.storage.RNFirebaseStoragePackage; // Firebase Storage
|
||||
// ...
|
||||
public class MainApplication extends Application implements ReactApplication {
|
||||
// ...
|
||||
|
||||
@Override
|
||||
protected List<ReactPackage> getPackages() {
|
||||
return Arrays.<ReactPackage>asList(
|
||||
new MainReactPackage(),
|
||||
new RNFirebasePackage(), // <-- Add this line
|
||||
// Add these packages as appropriate
|
||||
new RNFirebaseAdMobPackage(),
|
||||
new RNFirebaseAnalyticsPackage(),
|
||||
new RNFirebaseAuthPackage(),
|
||||
new RNFirebaseRemoteConfigPackage(),
|
||||
new RNFirebaseCrashPackage(),
|
||||
new RNFirebaseDatabasePackage(),
|
||||
new RNFirebaseMessagingPackage(),
|
||||
new RNFirebasePerformancePackage(),
|
||||
new RNFirebaseStoragePackage()
|
||||
);
|
||||
}
|
||||
};
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
## 3) Cloud Messaging (optional)
|
||||
|
||||
If you plan on using [Firebase Cloud Messaging](https://firebase.google.com/docs/cloud-messaging/), add the following to `android/app/src/main/AndroidManifest.xml`.
|
||||
|
||||
Add permissions:
|
||||
```xml
|
||||
<manifest ...>
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
```
|
||||
|
||||
Set app [launch mode](https://inthecheesefactory.com/blog/understand-android-activity-launchmode/en) inside activity props:
|
||||
```xml
|
||||
<activity
|
||||
...
|
||||
android:launchMode="singleTop"
|
||||
>
|
||||
```
|
||||
|
||||
Add messaging service:
|
||||
```xml
|
||||
<application ...>
|
||||
<service
|
||||
android:name="io.invertase.firebase.messaging.MessagingService"
|
||||
android:enabled="true"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="com.google.firebase.MESSAGING_EVENT" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
<service android:name="io.invertase.firebase.messaging.InstanceIdService" android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
|
||||
</intent-filter>
|
||||
</service>
|
||||
```
|
||||
|
||||
If you would like to schedule local notifications then you also need to add the following:
|
||||
```xml
|
||||
<receiver android:name="io.invertase.firebase.messaging.RNFirebaseLocalMessagingPublisher"/>
|
||||
<receiver android:enabled="true" android:exported="true" android:name="io.invertase.firebase.messaging.RNFirebaseSystemBootEventReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED"/>
|
||||
<action android:name="android.intent.action.QUICKBOOT_POWERON"/>
|
||||
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
```
|
||||
|
||||
## 4) Performance Monitoring (optional)
|
||||
|
||||
If you'd like to take advantage of Firebase's [Performance Monitoring](https://firebase.google.com/docs/perf-mon/), the following additions
|
||||
to your project setup are required:
|
||||
|
||||
In your projects `android/build.gradle` file, add the plugin to your dependencies:
|
||||
|
||||
```
|
||||
dependencies {
|
||||
...
|
||||
classpath 'com.google.firebase:firebase-plugins:1.1.0'
|
||||
}
|
||||
```
|
||||
|
||||
At the top of your `android/app/build.gradle` file, below other plugins, apply the `firebase-perf` plugin:
|
||||
```
|
||||
apply plugin: "com.android.application"
|
||||
apply plugin: "com.google.firebase.firebase-perf"
|
||||
```
|
||||
|
||||
In the same file, add the `firebase-perf` module to your dependencies:
|
||||
|
||||
```
|
||||
dependencies {
|
||||
...
|
||||
compile "com.google.firebase:firebase-perf:11.0.0"
|
||||
}
|
||||
```
|
||||
164
docs/v2/installation-ios.md
Normal file
164
docs/v2/installation-ios.md
Normal file
@@ -0,0 +1,164 @@
|
||||
# iOS Installation
|
||||
|
||||
Please note that there is a known issue when using Cocoapods with the `use_frameworks!` enabled. This is explained [here](https://github.com/invertase/react-native-firebase/issues/252#issuecomment-316340974). Unfortunately we don't currently have a workaround, but are engaging with Firebase directly to try and resolve the problem.
|
||||
|
||||
## 1) Setup GoogleService-Info.plist
|
||||
Setup the `GoogleService-Info.plist` file by following the instructions and adding it to the root of your project at `ios/[YOUR APP NAME]/GoogleService-Info.plist` [here](https://firebase.google.com/docs/ios/setup#add_firebase_to_your_app).
|
||||
|
||||
### 1.1) Initialisation
|
||||
Make sure you've added the following to the top of your `ios/[YOUR APP NAME]]/AppDelegate.m` file:
|
||||
|
||||
`#import <Firebase.h>`
|
||||
|
||||
and this to the `didFinishLaunchingWithOptions:(NSDictionary *)launchOptions` method before the `return` statement:
|
||||
|
||||
`[FIRApp configure];`
|
||||
|
||||
## 2) Setup RNFirebase
|
||||
|
||||
Unfortunately, due to the fact that Firebase is much easier to setup using Cocoapods, *we do not recommend* `react-native link` as it is not customisable enough for our needs and we have had numerous problems reported.
|
||||
|
||||
### 2.0) If you don't already have Cocoapods set up
|
||||
Follow the instructions to install Cocoapods and create your Podfile [here](https://firebase.google.com/docs/ios/setup#add_the_sdk).
|
||||
|
||||
**NOTE: The Podfile needs to be initialised in the `ios` directory of your project. Make sure to update cocoapods libs first by running `pod update`**
|
||||
|
||||
#### Troubleshooting
|
||||
1) When running `pod install` you may encounter an error saying that a `tvOSTests` target is declared twice. This appears to be a bug with `pod init` and the way that react native is set up.
|
||||
|
||||
**Resolution:**
|
||||
- Open your Podfile
|
||||
- Remove the duplicate `tvOSTests` target nested within the main project target
|
||||
- Re-run `pod install`.
|
||||
|
||||
2) When running `pod install` you may encounter a number of warnings relating to `target overrides 'OTHER_LDFLAGS'`.
|
||||
|
||||
**Resolution:**
|
||||
- Open Xcode
|
||||
- Select your project
|
||||
- For each target:
|
||||
-- Select the target
|
||||
-- Click Build settings
|
||||
-- Search for `other linker flags`
|
||||
-- Add `$(inherited)` as the top line if it doesn't already exist
|
||||
- Re-run `pod install`
|
||||
|
||||
3) When running `pod install` you may encounter a warning that a default iOS platform has been assigned. If you wish to specify a different minimum version:
|
||||
|
||||
**Resolution**
|
||||
- Open your Podfile
|
||||
- Uncomment the `# platform :ios, '9.0'` line by removing the `#` character
|
||||
- Change the version as required
|
||||
|
||||
### 2.1) Add the required pods
|
||||
Simply add the following to your `Podfile` either at the top level, or within the main project target:
|
||||
|
||||
```ruby
|
||||
# Required by RNFirebase
|
||||
pod 'Firebase/Core'
|
||||
pod 'RNFirebase', :path => '../node_modules/react-native-firebase'
|
||||
|
||||
# [OPTIONAL PODS] - comment out pods for firebase products you won't be using.
|
||||
pod 'Firebase/AdMob'
|
||||
pod 'Firebase/Analytics'
|
||||
pod 'Firebase/Auth'
|
||||
pod 'Firebase/Crash'
|
||||
pod 'Firebase/Database'
|
||||
pod 'Firebase/DynamicLinks'
|
||||
pod 'Firebase/Messaging'
|
||||
pod 'Firebase/RemoteConfig'
|
||||
pod 'Firebase/Storage'
|
||||
```
|
||||
|
||||
If you do not already have React and Yoga installed as pods, then add Yoga and React to your `Podfile` as follows:
|
||||
|
||||
```ruby
|
||||
pod "Yoga", :path => "../node_modules/react-native/ReactCommon/yoga"
|
||||
pod 'React', :path => '../node_modules/react-native', :subspecs => [
|
||||
'BatchedBridge', # Required For React Native 0.45.0+
|
||||
'Core',
|
||||
# Add any other subspecs you want to use in your project
|
||||
]
|
||||
```
|
||||
|
||||
Run `pod install`.
|
||||
|
||||
**NOTE: You need to use the `ios/[YOUR APP NAME].xcworkspace` instead of the `ios/[YOUR APP NAME].xcproj` file from now on.**
|
||||
|
||||
#### Troubleshooting
|
||||
1) You receive an error `No podspec found for 'RNFirebase'`
|
||||
|
||||
**Resolution**
|
||||
- Run `npm install --save react-native-firebase` from the root of your project
|
||||
|
||||
## 3) Cloud Messaging (optional)
|
||||
|
||||
If you plan on using [Firebase Cloud Messaging](https://firebase.google.com/docs/cloud-messaging/) then, you need to:
|
||||
|
||||
**NOTE: FCM does not work on the iOS simulator, you must test is using a real device. This is a restriction enforced by Apple for some unknown reason.**
|
||||
|
||||
### 3.1) Set up certificates
|
||||
|
||||
Follow the instructions at https://firebase.google.com/docs/cloud-messaging/ios/certs
|
||||
|
||||
### 3.2) Enable capabilities
|
||||
|
||||
In Xcode, enable the following capabilities:
|
||||
|
||||
1) Push Notifications
|
||||
2) Background modes > Remote notifications
|
||||
|
||||
### 3.3) Update `AppDelegate.h`
|
||||
|
||||
Add the following import:
|
||||
|
||||
`@import UserNotifications;`
|
||||
|
||||
Change the interface descriptor to:
|
||||
|
||||
`@interface AppDelegate : UIResponder <UIApplicationDelegate,UNUserNotificationCenterDelegate>`
|
||||
|
||||
### 3.4) Update `AppDelegate.m`
|
||||
|
||||
Add the following import:
|
||||
|
||||
`#import "RNFirebaseMessaging.h"`
|
||||
|
||||
Add the following to the `didFinishLaunchingWithOptions:(NSDictionary *)launchOptions` method after `[FIRApp Configure]`:
|
||||
|
||||
`[[UNUserNotificationCenter currentNotificationCenter] setDelegate:self];`
|
||||
|
||||
Add the following methods:
|
||||
|
||||
```objectivec
|
||||
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
|
||||
[RNFirebaseMessaging didReceiveLocalNotification:notification];
|
||||
}
|
||||
|
||||
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo {
|
||||
[RNFirebaseMessaging didReceiveRemoteNotification:userInfo];
|
||||
}
|
||||
|
||||
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo
|
||||
fetchCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler{
|
||||
[RNFirebaseMessaging didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
|
||||
}
|
||||
|
||||
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
|
||||
willPresentNotification:(UNNotification *)notification
|
||||
withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
|
||||
[RNFirebaseMessaging willPresentNotification:notification withCompletionHandler:completionHandler];
|
||||
}
|
||||
|
||||
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
|
||||
didReceiveNotificationResponse:(UNNotificationResponse *)response
|
||||
withCompletionHandler:(void (^)())completionHandler {
|
||||
[RNFirebaseMessaging didReceiveNotificationResponse:response withCompletionHandler:completionHandler];
|
||||
}
|
||||
```
|
||||
|
||||
### 3.5) Debugging
|
||||
|
||||
If you're having problems with messages not being received, check out the following blog post for help:
|
||||
|
||||
https://firebase.googleblog.com/2017/01/debugging-firebase-cloud-messaging-on.html
|
||||
170
docs/v2/migration-guide.md
Normal file
170
docs/v2/migration-guide.md
Normal file
@@ -0,0 +1,170 @@
|
||||
# Migration
|
||||
|
||||
## From v1 to v2
|
||||
|
||||
The below is a quick summary of steps to take when migrating from v1 to v2 of RNFirebase. Please see the [v2 change log](https://github.com/invertase/react-native-firebase/releases/tag/v2.0.0) for detailed changes.
|
||||
|
||||
##### 1) Install the latest version of RNFirebase:
|
||||
> `npm i react-native-firebase@latest --save`
|
||||
|
||||
|
||||
|
||||
|
||||
##### 2) Upgrade react-native version (only if you're currently lower than v0.40):
|
||||
|
||||
> For example: `npm i react-native@0.44.0 react@16.0.0-alpha.6 --save`
|
||||
|
||||
|
||||
|
||||
|
||||
##### 3) Update your JS code to reflect deprecations/breaking changes:
|
||||
|
||||
|
||||
|
||||
- [deprecated] providerId should now be used instead of provider whilst obtaining auth credentials. The latter will be removed in future releases.
|
||||
- [deprecated] Deprecated User.getToken in favour of User.getIdToken.
|
||||
- [breaking] User.reauthenticate has been removed in favour of User.reauthenticateWithCredential.
|
||||
- [breaking] User.link has been removed in favour of User.linkWithCredential.
|
||||
- [breaking] Removed unnecessary didReceiveNotificationResponse and willPresentNotification methods for iOS messaging. Added additional didReceiveRemoteNotification method.
|
||||
- [breaking] firebase.messaging().onTokenRefresh and firebase.messaging().onMessage return a function to unsubscribe as per the Web SDK spec: https://firebase.google.com/docs/reference/js/firebase.messaging.Messaging#onMessage. Previously they returned an object with a .remove() method.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
##### 4) Android - Update `android/build.gradle`:
|
||||
|
||||
|
||||
The latest google-services version needs to be used:
|
||||
|
||||
```groovy
|
||||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:2.2.3'
|
||||
classpath 'com.google.gms:google-services:3.1.0'
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
##### 5) Android - Update `app/build.gradle`:
|
||||
|
||||
|
||||
All firebase modules are now optional so you only need to import the Firebase functionality that you require in your application.
|
||||
|
||||
You need to make a couple of changes to your `app/build.gradle` file. Update the react-native-firebase compile statement to read:
|
||||
|
||||
```groovy
|
||||
compile(project(':react-native-firebase')) {
|
||||
transitive = false
|
||||
}
|
||||
compile "com.google.firebase:firebase-core:11.0.0"
|
||||
```
|
||||
Add each of the firebase modules you need from the following list:
|
||||
```groovy
|
||||
compile "com.google.firebase:firebase-ads:11.0.0"
|
||||
compile "com.google.firebase:firebase-analytics:11.0.0"
|
||||
compile "com.google.firebase:firebase-auth:11.0.0"
|
||||
compile "com.google.firebase:firebase-config:11.0.0"
|
||||
compile "com.google.firebase:firebase-crash:11.0.0"
|
||||
compile "com.google.firebase:firebase-database:11.0.0"
|
||||
compile "com.google.firebase:firebase-messaging:11.0.0"
|
||||
compile "com.google.firebase:firebase-perf:11.0.0"
|
||||
compile "com.google.firebase:firebase-storage:11.0.0"
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
##### 6) Android - Update `MainApplication.java`:
|
||||
|
||||
|
||||
|
||||
Update `MainApplication.java` and import the modules you require / currently use:
|
||||
|
||||
```java
|
||||
import io.invertase.firebase.admob.RNFirebaseAdMobPackage; //Firebase AdMob
|
||||
import io.invertase.firebase.analytics.RNFirebaseAnalyticsPackage; // Firebase Analytics
|
||||
import io.invertase.firebase.auth.RNFirebaseAuthPackage; // Firebase Auth
|
||||
import io.invertase.firebase.config.RNFirebaseRemoteConfigPackage; // Firebase Remote Config
|
||||
import io.invertase.firebase.crash.RNFirebaseCrashPackage; // Firebase Crash Reporting
|
||||
import io.invertase.firebase.database.RNFirebaseDatabasePackage; // Firebase Realtime Database
|
||||
import io.invertase.firebase.messaging.RNFirebaseMessagingPackage; // Firebase Cloud Messaging
|
||||
import io.invertase.firebase.perf.RNFirebasePerformancePackage; // Firebase Performance Monitoring
|
||||
import io.invertase.firebase.storage.RNFirebaseStoragePackage; // Firebase Storage
|
||||
```
|
||||
Add the packages to the `getPackages()` method as required:
|
||||
```java
|
||||
@Override
|
||||
protected List<ReactPackage> getPackages() {
|
||||
return Arrays.<ReactPackage>asList(
|
||||
new MainReactPackage(),
|
||||
new RNFirebasePackage(), // <-- Keep this line - it's the only one that's required
|
||||
|
||||
// add these optional packages as appropriate
|
||||
new RNFirebaseAdMobPackage(),
|
||||
new RNFirebaseAnalyticsPackage(),
|
||||
new RNFirebaseAuthPackage(),
|
||||
new RNFirebaseRemoteConfigPackage(),
|
||||
new RNFirebaseCrashPackage(),
|
||||
new RNFirebaseDatabasePackage(),
|
||||
new RNFirebaseMessagingPackage(),
|
||||
new RNFirebasePerformancePackage(),
|
||||
new RNFirebaseStoragePackage()
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
##### 7) iOS - Update podfile:
|
||||
|
||||
First, delete your `Podfile.lock` file, and after making any changes from the below re-run `pod install` in your ios directory.
|
||||
|
||||
As all firebase modules are now optional you only need to import the Firebase functionality that you require in your application. Simply update your Podfile to only include the Firebase modules for functionality that you require in your app.
|
||||
|
||||
For example if you only use Auth and Storage in your app then your podfile would look like the below:
|
||||
|
||||
```ruby
|
||||
install! 'cocoapods', :deterministic_uuids => false
|
||||
# Uncomment this line to define a global platform for your project
|
||||
# platform :ios, '9.0'
|
||||
|
||||
target 'ReactNativeFirebaseDemo' do
|
||||
platform :ios, '8.0'
|
||||
# Uncomment this line if you're using Swift or would like to use dynamic frameworks
|
||||
# use_frameworks!
|
||||
|
||||
react_native_path = "../node_modules/react-native"
|
||||
pod "Yoga", :path => "#{react_native_path}/ReactCommon/yoga"
|
||||
pod 'React', :path => '#{react_native_path}', :subspecs => [
|
||||
'BatchedBridge', # Required For React Native 0.45.0+
|
||||
'Core',
|
||||
# Add any other subspecs you want to use in your project
|
||||
# ...
|
||||
]
|
||||
|
||||
# Core is always required
|
||||
pod 'Firebase/Core'
|
||||
|
||||
# Optional modules
|
||||
pod 'Firebase/Auth'
|
||||
pod 'Firebase/Storage'
|
||||
|
||||
pod 'RNFirebase', :path => '../node_modules/react-native-firebase'
|
||||
end
|
||||
```
|
||||
|
||||
|
||||
382
docs/v2/modules/admob.md
Normal file
382
docs/v2/modules/admob.md
Normal file
@@ -0,0 +1,382 @@
|
||||
# AdMob
|
||||
|
||||
The admob allows you to display adverts in your app, using your account from [AdMob by Google](https://www.google.co.uk/admob/). RNFirebase allows you to display Banners, Interstitials, NativeExpress Ads & Rewarded Videos.
|
||||
|
||||
## Initialize
|
||||
|
||||
Before using any AdMob feature, ensure you call the initialize method. This only needs to be done once per the apps lifecycle.
|
||||
Initialize takes your AdMob App ID, where you can find on your AdMob dashboard.
|
||||
|
||||
> For testing purposes, you can use AdMobs test app ID "ca-app-pub-3940256099942544~3347511713".
|
||||
|
||||
```js
|
||||
firebase.admob().initialize("ca-app-pub-3940256099942544~3347511713");
|
||||
```
|
||||
|
||||
## Debugging
|
||||
|
||||
Once initialized, you can debug ((Android)[https://developers.google.com/mobile-ads-sdk/docs/dfp/android/debug]/(iOS)[https://developers.google.com/mobile-ads-sdk/docs/dfp/ios/debug])
|
||||
your ads using the debug menu.
|
||||
|
||||
```js
|
||||
firebase.admob().openDebugMenu();
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### Banner
|
||||
|
||||
AdMob Banners in RNFirebase are exported as a usable React component, allowing you to integrate it easily into your existing app very easily.
|
||||
|
||||
#### Props
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
| ------------------- | ------------------ | --------------------------------------- | ----------------------------------------------------------------------------------- |
|
||||
| size | string (See Sizes) | SMART_BANNER | Returns a sized banner (automatically sets View style) |
|
||||
| unitId | string | | Your AdMob banner unit ID. |
|
||||
| request | AdRequest | new AdRequest().addTestDevice().build() | An instance of AdRequest to load with the Banner |
|
||||
| onAdLoaded | function | | Called when an ad is received. |
|
||||
| onAdOpened | function | | Called when an ad opens an overlay that covers the screen. |
|
||||
| onAdLeftApplication | function | | Called when an ad leaves the application (e.g., to go to the browser). |
|
||||
| onAdClosed | function | | Called when the user is about to return to the application after clicking on an ad. |
|
||||
| onAdFailedToLoad | function | | Called when an ad request failed. See Error Handling |
|
||||
|
||||
#### Example
|
||||
|
||||
```js
|
||||
const Banner = firebase.admob.Banner;
|
||||
const AdRequest = firebase.admob.AdRequest;
|
||||
const request = new AdRequest();
|
||||
request.addKeyword('foobar');
|
||||
...
|
||||
render() {
|
||||
return (
|
||||
<Banner
|
||||
size={"LARGE_BANNER"}
|
||||
request={request.build()}
|
||||
onAdLoaded={() => {
|
||||
console.log('Advert loaded and is now visible');
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Interstitial
|
||||
|
||||
An interstitial is a full screen advert which creates a new activity on top of React. As they need to be controlled,
|
||||
allowing the developer to choose when to display them they're not available as a component. Instead they're controlled via
|
||||
method calls.
|
||||
|
||||
A single interstitial instance can only be shown once. If you want to display another, create a new one.
|
||||
|
||||
To request an interstitial from AdMob, the `loadAd` method must be called with an instance of `AdRequest` (see below for full API):
|
||||
|
||||
#### Methods
|
||||
|
||||
| Method | Description |
|
||||
| ------------------- | ---------------------------------------------------------------------------- |
|
||||
| loadAd(AdRequest) | Loads an advert with request config |
|
||||
| on(event, callback) | Listens to advert events. See Event Types for more information. |
|
||||
| isLoaded() | Returns a boolean value as to whether the advert is loaded and ready to show.|
|
||||
| show() | Show the advert on the device |
|
||||
|
||||
#### Example
|
||||
|
||||
```js
|
||||
const advert = firebase.admob().interstitial('ca-app-pub-3940256099942544/1033173712');
|
||||
|
||||
const AdRequest = firebase.admob.AdRequest;
|
||||
const request = new AdRequest();
|
||||
request.addKeyword('foo').addKeyword('bar');
|
||||
|
||||
// Load the advert with our AdRequest
|
||||
advert.loadAd(request.build());
|
||||
|
||||
advert.on('onAdLoaded', () => {
|
||||
console.log('Advert ready to show.');
|
||||
});
|
||||
|
||||
// Simulate the interstitial being shown "sometime" later during the apps lifecycle
|
||||
setTimeout(() => {
|
||||
if (advert.isLoaded()) {
|
||||
advert.show();
|
||||
} else {
|
||||
// Unable to show interstitial - not loaded yet.
|
||||
}
|
||||
}, 1000);
|
||||
```
|
||||
|
||||
### Native Express
|
||||
|
||||
An AdMob Native Express advert is much like a standard Banner, except it can be integrated seamlessly into your app using user predefined
|
||||
styling (background color, positions, font size etc). Native Express adverts are exported as a usable React component.
|
||||
|
||||
#### Props
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
| ------------------- | ------------------ | --------------------------------------- | ----------------------------------------------------------------------------------- |
|
||||
| size | string (See Sizes) | SMART_BANNER | TODO |
|
||||
| unitId | string | | Your AdMob banner unit ID. |
|
||||
| request | AdRequest | new AdRequest().addTestDevice().build() | An instance of AdRequest to load with the Banner |
|
||||
| video | AdRequest | new VideoOptions().build() | An instance of AdRequest to load with the Banner |
|
||||
| onAdLoaded | function | | Called when an ad is received. |
|
||||
| onAdOpened | function | | Called when an ad opens an overlay that covers the screen. |
|
||||
| onAdLeftApplication | function | | Called when an ad leaves the application (e.g., to go to the browser). |
|
||||
| onAdClosed | function | | Called when the user is about to return to the application after clicking on an ad. |
|
||||
| onAdFailedToLoad | function | | Called when an ad request failed. See Event PropTypes for more information. |
|
||||
| onVideoEnd | function | | Called if the advert video has ended (only called if the advert has a video). |
|
||||
|
||||
#### Usage
|
||||
|
||||
```js
|
||||
const Banner = firebase.admob.Banner;
|
||||
const NativeExpress = firebase.admob.NativeExpress;
|
||||
const AdRequest = firebase.admob.AdRequest;
|
||||
|
||||
const request = new AdRequest();
|
||||
request.addKeyword('foobar');
|
||||
...
|
||||
render() {
|
||||
return (
|
||||
<NativeExpress
|
||||
size={"300x400"}
|
||||
request={request.build()}
|
||||
onAdLoaded={() => {
|
||||
console.log('Advert loaded and is now visible');
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Rewarded Video
|
||||
|
||||
A rewarded video allows you to display a video to a user, whereby they're able to watch it to gain "rewards", or skip it
|
||||
and receive nothing. For example, when a user completes a level on your gaming app, show them a video which will give them in-game
|
||||
credit.
|
||||
|
||||
A single rewarded video instance can only be shown once. If you want to display another, create a new one.
|
||||
|
||||
?> It's recommended you begin loading the video as soon as possible.
|
||||
|
||||
To request an Rewarded Video from AdMob, the `loadAd` method must be called with an instance of `AdRequest` (see below for full API):
|
||||
|
||||
#### Methods
|
||||
|
||||
| Method | Description |
|
||||
| ------------------- | ---------------------------------------------------------------------------- |
|
||||
| loadAd(AdRequest) | Loads an advert with request config |
|
||||
| on(event, callback) | Listens to advert events. See Event Types |
|
||||
| isLoaded() | Returns a boolean value as to whether the advert is loaded and ready to show |
|
||||
| show() | Show the advert on the device |
|
||||
|
||||
#### Example
|
||||
|
||||
```js
|
||||
const advert = firebase.admob().rewarded('ca-app-pub-3940256099942544/1033173712');
|
||||
|
||||
const AdRequest = firebase.admob.AdRequest;
|
||||
const request = new AdRequest();
|
||||
request.addKeyword('foo').addKeyword('bar');
|
||||
|
||||
// Load the advert with our AdRequest
|
||||
advert.loadAd(request.build());
|
||||
|
||||
advert.on('onAdLoaded', () => {
|
||||
console.log('Advert ready to show.');
|
||||
});
|
||||
|
||||
advert.on('onRewarded', (event) => {
|
||||
console.log('The user watched the entire video and will now be rewarded!', event);
|
||||
});
|
||||
|
||||
...
|
||||
|
||||
onLevelComplete()
|
||||
.then(() => {
|
||||
if (advert.isLoaded()) {
|
||||
advert.show();
|
||||
} else {
|
||||
// skip...
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### AdRequest
|
||||
|
||||
The AdRequest class is used to create an object to be passed to each advert request. The request is handled on AdMob,
|
||||
and returns adverts tailored to the request options provided.
|
||||
|
||||
!> If no AdRequest is sent, the default request calls `addTestDevice`. Therefore, ensure a custom AdRequest object is passed through
|
||||
in production.
|
||||
|
||||
##### build()
|
||||
Builds the current request for AdMob to handle.
|
||||
|
||||
##### addTestDevice(device?: string)
|
||||
Sets a device ID as a test device. If no device string is passed, a default emulator id is passed.
|
||||
|
||||
##### addKeyword(keyword: `string`)
|
||||
Add a new keyword to relate the advert to.
|
||||
|
||||
##### setBirthday(date: `Date`)
|
||||
Sets the user's birthday for targeting purposes.
|
||||
|
||||
##### setGender(gender: `male | female | unknown`)
|
||||
Sets the user's gender for targeting purposes.
|
||||
|
||||
##### setLocation()
|
||||
Sets the user's location for targeting purposes.
|
||||
|
||||
##### setRequestAgent(requestAgent: `string`)
|
||||
Sets the request agent string to identify the ad request's origin. Third party libraries that reference the Mobile Ads SDK should call this method to denote the platform from which the ad request originated. For example, if a third party ad network called "CoolAds network" mediates requests to the Mobile Ads SDK, it should call this method with "CoolAds"
|
||||
|
||||
##### setContentUrl(url: `string`)
|
||||
Sets the content URL for targeting purposes.
|
||||
|
||||
##### [android] setIsDesignedForFamilies(forFamilies: `boolean`)
|
||||
If you set this value to true, you indicate that your app requires that the ad request should return a Designed for Families-compliant ad.
|
||||
|
||||
If you set this value to false, you indicate that your app does not require that the ad request should return a Designed for Families-compliant ad.
|
||||
|
||||
##### tagForChildDirectedTreatment(forChildren: `boolean`)
|
||||
|
||||
### VideoOptions
|
||||
|
||||
The VideoOptions class is used to create an object to be passed through to each advert request. If the advert returns a video,
|
||||
the options are used when displaying it on the application.
|
||||
|
||||
?> Currently `NativeExpress` only accepts VideoOptions. If no VideoOptions are sent, the default options call `setStartMuted(true)`.
|
||||
|
||||
##### build()
|
||||
Builds the current options for AdMob to handle.
|
||||
|
||||
##### setStartMuted(muted: `boolean`)
|
||||
If true, any returned video will not play sound when it starts. The end user can manually enable sound on the advert interface.
|
||||
|
||||
## Prop Types
|
||||
|
||||
##### size: `String`
|
||||
Sets the size of an Advert. Can be one of the following or a custom size:
|
||||
|
||||
| Size | Description |
|
||||
| ----------------- | ------------------------------------------------------------------------------------------------------ |
|
||||
| BANNER | Mobile Marketing Association (MMA) banner ad size (320x50 density-independent pixels). |
|
||||
| FULL_BANNER | Interactive Advertising Bureau (IAB) full banner ad size (468x60 density-independent pixels). |
|
||||
| LARGE_BANNER | Large banner ad size (320x100 density-independent pixels). |
|
||||
| LEADERBOARD | Interactive Advertising Bureau (IAB) leaderboard ad size (728x90 density-independent pixels). |
|
||||
| MEDIUM_RECTANGLE | Interactive Advertising Bureau (IAB) medium rectangle ad size (300x250 density-independent pixels). |
|
||||
| SMART_BANNER | A dynamically sized banner that is full-width and auto-height. |
|
||||
|
||||
To specify a custom size, pass a string with the width and height split by an "x" (follows the Regex pattern `([0-9]+)x([0-9]+)`), e.g 320x150
|
||||
|
||||
?> Requesting an advert with a size which does not exist on the AdMob servers will return `admob/error-code-internal-error`.
|
||||
|
||||
##### unitId: `String`
|
||||
The unit ID for the banner. Defaults to the testing unitId provided by Google for the advert type.
|
||||
|
||||
##### request: `AdRequest`
|
||||
A built AdRequest object returned from `AdRequest.build()`.
|
||||
|
||||
##### video: `VideoOptions`
|
||||
A built VideoOptions object returned from `VideoOptions.build()`.
|
||||
|
||||
### Events
|
||||
Every advert returns common event types. On component based adverts (e.g. Banner) they're available as props and on instance based
|
||||
adverts (e.g. Interstitial) they're available via the `on` method.
|
||||
|
||||
##### onAdLoaded(config: `Object`)
|
||||
!> The config is not provided for Interstitial or Rewarded Video adverts.
|
||||
|
||||
On successful response from the AdMob servers. This is also called when a new banner is automatically loaded from the AdMob servers if the current one expires.
|
||||
|
||||
Returns an object of config data related to the loaded advert:
|
||||
```js
|
||||
{
|
||||
hasVideoContent: boolean,
|
||||
width: number,
|
||||
height: number,
|
||||
}
|
||||
```
|
||||
|
||||
##### onAdOpened()
|
||||
Called when the user presses the advert and it successfully opens.
|
||||
|
||||
##### onAdLeftApplication()
|
||||
Called if the opened advert causes the user to leave the application, for example opening a URL in the browser.
|
||||
|
||||
##### onAdClosed()
|
||||
Called when the user returns back to the application after closing an advert.
|
||||
|
||||
##### onAdFailedToLoad(error: `Error`)
|
||||
Called when an advert fails to load. Returns a JavaScript Error with one of the following error codes.
|
||||
|
||||
| code | message |
|
||||
| --------------------------------- | ------------------------------------------------------------------------------------------------------------ |
|
||||
| admob/error-code-internal-error | Something happened internally; for instance, an invalid response was received from the ad server. |
|
||||
| admob/error-code-invalid-request | The ad request was invalid; for instance, the ad unit ID was incorrect. |
|
||||
| admob/error-code-network-error | The ad request was unsuccessful due to network connectivity. |
|
||||
| admob/error-code-no-fill | The ad request was successful, but no ad was returned due to lack of ad inventory. |
|
||||
| admob/os-version-too-low | The current device’s OS is below the minimum required version. |
|
||||
|
||||
##### [NativeExpress] onVideoEnd()
|
||||
Called when video playback finishes playing.
|
||||
|
||||
##### [NativeExpress] onVideoMute(config: `Object`)
|
||||
Called when the video changes mute state.
|
||||
|
||||
```js
|
||||
{
|
||||
isMuted: boolean,
|
||||
}
|
||||
```
|
||||
|
||||
##### [NativeExpress] onVideoPause()
|
||||
Called when video playback is paused.
|
||||
|
||||
##### [NativeExpress] onVideoPlay()
|
||||
Called when video playback is playing.
|
||||
|
||||
##### [NativeExpress] onVideoStart()
|
||||
alled when video playback first begins.
|
||||
|
||||
##### [RewardedVideo] onRewarded(reward: `Object`)
|
||||
Called when the user has been rewarded (usually for watching an entire video). Returns a reward object:
|
||||
|
||||
```js
|
||||
{
|
||||
type: string,
|
||||
amount: number,
|
||||
}
|
||||
```
|
||||
|
||||
##### [RewardedVideo] onRewardedVideoStarted()
|
||||
Called when a rewarded video has started to play.
|
||||
|
||||
## Statics
|
||||
The following statics are available on the `firebase.admob` instance.
|
||||
|
||||
### Banner
|
||||
Exports a React component to display an AdMob Banner.
|
||||
|
||||
### NativeExpress
|
||||
Exports a React component to display an AdMob Native Express advert.
|
||||
|
||||
### AdRequest
|
||||
Used to build a request object to pass into AdMob requests.
|
||||
|
||||
### VideoOptions
|
||||
Used to build an options object for how videos should be handled with adverts containing a video.
|
||||
|
||||
### EventTypes
|
||||
Returns all of the available advert event types.
|
||||
|
||||
### RewardedVideoEventTypes
|
||||
Returns the extra event types for Rewarded Videos.
|
||||
|
||||
### NativeExpressEventTypes
|
||||
Returns the extra event types for Native Express adverts.
|
||||
|
||||
90
docs/v2/modules/analytics.md
Normal file
90
docs/v2/modules/analytics.md
Normal file
@@ -0,0 +1,90 @@
|
||||
# Analytics
|
||||
|
||||
Integrating Firebase analytics is simple. A number of methods are provided to help tailor analytics specifically for your
|
||||
own app. The Firebase SDK includes a number of pre-set events which are automatically handled, and cannot be used with custom `logEvent` events:
|
||||
|
||||
```
|
||||
'app_clear_data',
|
||||
'app_uninstall',
|
||||
'app_update',
|
||||
'error',
|
||||
'first_open',
|
||||
'first_visit',
|
||||
'first_open_time',
|
||||
'first_visit_time',
|
||||
'in_app_purchase',
|
||||
'notification_dismiss',
|
||||
'notification_foreground',
|
||||
'notification_open',
|
||||
'notification_receive',
|
||||
'os_update',
|
||||
'session_start',
|
||||
'screen_view',
|
||||
'user_engagement',
|
||||
'ad_impression',
|
||||
'ad_click',
|
||||
'ad_query',
|
||||
'ad_exposure',
|
||||
'adunit_exposure',
|
||||
'ad_activeiew',
|
||||
```
|
||||
|
||||
#### `logEvent(event: string, params?: Object): void`
|
||||
|
||||
Log a custom event with optional params.
|
||||
|
||||
```javascript
|
||||
firebase.analytics().logEvent('clicked_advert', { id: 1337 });
|
||||
```
|
||||
|
||||
#### `setAnalyticsCollectionEnabled(enabled: boolean): void`
|
||||
|
||||
Sets whether analytics collection is enabled for this app on this device.
|
||||
|
||||
```javascript
|
||||
firebase.analytics().setAnalyticsCollectionEnabled(false);
|
||||
```
|
||||
|
||||
#### `setCurrentScreen(screenName: string, screenClassOverride?: string): void`
|
||||
|
||||
Sets the current screen name, which specifies the current visual context in your app.
|
||||
|
||||
> Whilst `screenClassOverride` is optional, it is recommended it is always sent as your current class name, for example on Android it will always show as 'MainActivity' if not specified.
|
||||
|
||||
```javascript
|
||||
firebase.analytics().setCurrentScreen('user_profile');
|
||||
```
|
||||
|
||||
#### `setMinimumSessionDuration(miliseconds: number): void`
|
||||
|
||||
Sets the minimum engagement time required before starting a session. The default value is 10000 (10 seconds).
|
||||
|
||||
```javascript
|
||||
firebase.analytics().setMinimumSessionDuration(15000);
|
||||
```
|
||||
|
||||
#### `setSessionTimeoutDuration(miliseconds: number): void`
|
||||
|
||||
Sets the duration of inactivity that terminates the current session. The default value is 1800000 (30 minutes).
|
||||
|
||||
```javascript
|
||||
firebase.analytics().setSessionTimeoutDuration(900000);
|
||||
```
|
||||
|
||||
#### `setUserId(id: string): void`
|
||||
|
||||
Gives a user a unique identification.
|
||||
|
||||
```javascript
|
||||
const id = firebase.auth().currentUser.uid;
|
||||
|
||||
firebase.analytics().setUserId(id);
|
||||
```
|
||||
|
||||
#### `setUserProperty(name: string, value: string): void`
|
||||
|
||||
Sets a key/value pair of data on the current user.
|
||||
|
||||
```javascript
|
||||
firebase.analytics().setUserProperty('nickname', 'foobar');
|
||||
```
|
||||
324
docs/v2/modules/authentication.md
Normal file
324
docs/v2/modules/authentication.md
Normal file
@@ -0,0 +1,324 @@
|
||||
# Authentication
|
||||
|
||||
RNFirebase handles authentication for us out of the box, both with email/password-based authentication and through oauth providers (with a separate library to handle oauth providers, see [examples](#examples)).
|
||||
|
||||
> Authentication requires Google Play services to be installed on Android.
|
||||
|
||||
## Auth
|
||||
|
||||
### Properties
|
||||
|
||||
##### `authenticated: boolean` - Returns the current Firebase authentication state.
|
||||
##### `currentUser: User | null` - Returns the currently signed-in user (or null). See the [User](/modules/authentication.md#user) class documentation for further usage.
|
||||
|
||||
### Methods
|
||||
|
||||
#### [`onAuthStateChanged(event: Function): Function`](https://firebase.google.com/docs/reference/js/firebase.auth.Auth#onAuthStateChanged)
|
||||
|
||||
Listen for changes in the users auth state (logging in and out). This method returns a unsubscribe function to stop listening to events. Always ensure you unsubscribe from the listener when no longer needed to prevent updates to components no longer in use.
|
||||
|
||||
```javascript
|
||||
class Example extends React.Component {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.unsubscribe = null;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.unsubscribe = firebase.auth().onAuthStateChanged((user) => {
|
||||
if (user) {
|
||||
// User is signed in.
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.unsubscribe) {
|
||||
this.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
#### [`createUserWithEmailAndPassword(email: string, password: string): Promise`](https://firebase.google.com/docs/reference/js/firebase.auth.Auth#createUserWithEmailAndPassword)
|
||||
|
||||
We can create a user by calling the `createUserWithEmailAndPassword()` function.
|
||||
The method accepts two parameters, an email and a password.
|
||||
|
||||
```javascript
|
||||
firebase.auth().createUserWithEmailAndPassword('foo@bar.com', '123456')
|
||||
.then((user) => {
|
||||
console.log('user created', user)
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('An error occurred', err);
|
||||
});
|
||||
```
|
||||
|
||||
#### [`signInWithEmailAndPassword(email: string, password: string): Promise`](https://firebase.google.com/docs/reference/js/firebase.auth.Auth#signInWithEmailAndPassword)
|
||||
|
||||
To sign a user in with their email and password, use the `signInWithEmailAndPassword()` function.
|
||||
It accepts two parameters, the user's email and password:
|
||||
|
||||
```javascript
|
||||
firebase.auth().signInWithEmailAndPassword('foo@bar.com', '123456')
|
||||
.then((user) => {
|
||||
console.log('User successfully logged in', user)
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('User signin error', err);
|
||||
});
|
||||
```
|
||||
|
||||
#### [`signInAnonymously(): Promise`](https://firebase.google.com/docs/reference/js/firebase.auth.Auth#signInAnonymously)
|
||||
|
||||
Sign an anonymous user. If the user has already signed in, that user will be returned.
|
||||
|
||||
```javascript
|
||||
firebase.auth().signInAnonymously()
|
||||
.then((user) => {
|
||||
console.log('Anonymous user successfully logged in', user)
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('Anonymous user signin error', err);
|
||||
});
|
||||
```
|
||||
|
||||
#### [`signInWithCredential(credential: Object): Promise`](https://firebase.google.com/docs/reference/js/firebase.auth.Auth#signInWithCredential)
|
||||
|
||||
Sign in the user with a 3rd party credential provider. `credential` requires the following properties:
|
||||
|
||||
```javascript
|
||||
{
|
||||
provider: string,
|
||||
token: string,
|
||||
secret: string
|
||||
}
|
||||
```
|
||||
|
||||
```javascript
|
||||
const credential = {
|
||||
provider: 'facebook',
|
||||
token: '12345',
|
||||
secret: '6789',
|
||||
};
|
||||
|
||||
firebase.auth().signInWithCredential(credential)
|
||||
.then((user) => {
|
||||
console.log('User successfully signed in', user)
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('User signin error', err);
|
||||
});
|
||||
```
|
||||
|
||||
#### [`signInWithCustomToken(token: string): Promise`](https://firebase.google.com/docs/reference/js/firebase.auth.Auth#signInWithCustomToken)
|
||||
|
||||
Sign a user in with a self-signed [JWT](https://jwt.io) token.
|
||||
|
||||
To sign a user using a self-signed custom token, use the `signInWithCustomToken()` function. It accepts one parameter, the custom token:
|
||||
|
||||
```javascript
|
||||
firebase.auth().signInWithCustomToken('12345')
|
||||
.then((user) => {
|
||||
console.log('User successfully logged in', user)
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('User signin error', err);
|
||||
});
|
||||
```
|
||||
|
||||
#### [`sendPasswordResetEmail(email: string): Promise`](https://firebase.google.com/docs/reference/js/firebase.auth.Auth#sendPasswordResetEmail)
|
||||
|
||||
Sends a password reset email to the given email address. Unlike the web SDK, the email will contain a password reset link rather than a code.
|
||||
|
||||
```javascript
|
||||
firebase.auth().sendPasswordResetEmail('foo@bar.com')
|
||||
.then(() => {
|
||||
console.log('Password reset email sent');
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Unable send password reset email', error);
|
||||
});
|
||||
```
|
||||
|
||||
#### [`signOut(): Promise`](https://firebase.google.com/docs/reference/js/firebase.auth.Auth#confirmPasswordReset)
|
||||
|
||||
Completes the password reset process, given a confirmation code and new password.
|
||||
|
||||
```javascript
|
||||
firebase.auth().signOut()
|
||||
.then(() => {
|
||||
console.log('User signed out successfully');
|
||||
})
|
||||
.catch();
|
||||
```
|
||||
|
||||
## User
|
||||
|
||||
User class returned from `firebase.auth().currentUser`.
|
||||
|
||||
### Properties
|
||||
|
||||
##### `displayName: string | null` - The user's display name (if available).
|
||||
##### `email: string | null` - The user's email address (if available).
|
||||
##### `emailVerified: boolean` - True if the user's email address has been verified.
|
||||
##### `isAnonymous: boolean`
|
||||
##### `photoURL: string | null` - The URL of the user's profile picture (if available).
|
||||
##### `providerData: Object | null` - Additional provider-specific information about the user.
|
||||
##### `providerId: string | null` - The authentication provider ID for the current user. For example, 'facebook.com', or 'google.com'.
|
||||
##### `uid: string` - The user's unique ID.
|
||||
|
||||
### Methods
|
||||
|
||||
#### [`delete(): Promise`](https://firebase.google.com/docs/reference/js/firebase.User#delete)
|
||||
|
||||
Delete the current user.
|
||||
|
||||
```javascript
|
||||
firebase.auth().currentUser
|
||||
.delete()
|
||||
.then()
|
||||
.catch();
|
||||
```
|
||||
|
||||
#### [`getToken(): Promise`](https://firebase.google.com/docs/reference/js/firebase.User#getToken)
|
||||
|
||||
Returns the users authentication token.
|
||||
|
||||
```javascript
|
||||
firebase.auth().currentUser
|
||||
.getToken()
|
||||
.then((token) => {})
|
||||
.catch();
|
||||
```
|
||||
|
||||
|
||||
#### [`reauthenticate(credential: Object): Promise`](https://firebase.google.com/docs/reference/js/firebase.User#reauthenticate)
|
||||
|
||||
Reauthenticate the current user with credentials:
|
||||
|
||||
```javascript
|
||||
{
|
||||
provider: string,
|
||||
token: string,
|
||||
secret: string
|
||||
}
|
||||
```
|
||||
|
||||
```javascript
|
||||
const credentials = {
|
||||
provider: 'facebook',
|
||||
token: '12345',
|
||||
secret: '6789',
|
||||
};
|
||||
|
||||
firebase.auth().currentUser
|
||||
.reauthenticate(credentials)
|
||||
.then()
|
||||
.catch();
|
||||
```
|
||||
|
||||
#### [`reload(): Promise`](https://firebase.google.com/docs/reference/js/firebase.User#reload)
|
||||
|
||||
Refreshes the current user.
|
||||
|
||||
```javascript
|
||||
firebase.auth().currentUser
|
||||
.reload()
|
||||
.then((user) => {})
|
||||
.catch();
|
||||
```
|
||||
|
||||
#### [`sendEmailVerification(): Promise`](https://firebase.google.com/docs/reference/js/firebase.User#sendEmailVerification)
|
||||
|
||||
Sends a verification email to a user. This will Promise reject is the user is anonymous.
|
||||
|
||||
```javascript
|
||||
firebase.auth().currentUser
|
||||
.sendEmailVerification()
|
||||
.then()
|
||||
.catch();
|
||||
```
|
||||
|
||||
#### [updateEmail(email: string)](https://firebase.google.com/docs/reference/js/firebase.User#updateEmail)
|
||||
|
||||
Updates the user's email address. See Firebase docs for more information on security & email validation. This will Promise reject is the user is anonymous.
|
||||
|
||||
```javascript
|
||||
firebase.auth().currentUser
|
||||
.updateEmail('foo@bar.com')
|
||||
.then()
|
||||
.catch();
|
||||
```
|
||||
|
||||
#### [updatePassword(password: string)](https://firebase.google.com/docs/reference/js/firebase.User#updatePassword)
|
||||
|
||||
Important: this is a security sensitive operation that requires the user to have recently signed in. If this requirement isn't met, ask the user to authenticate again and then call firebase.User#reauthenticate. This will Promise reject is the user is anonymous.
|
||||
|
||||
```javascript
|
||||
firebase.auth().currentUser
|
||||
.updatePassword('foobar1234')
|
||||
.then()
|
||||
.catch();
|
||||
```
|
||||
|
||||
#### [updateProfile(profile: Object)](https://firebase.google.com/docs/reference/js/firebase.User#updateProfile)
|
||||
|
||||
Updates a user's profile data. Profile data should be an object of fields to update:
|
||||
|
||||
```javascript
|
||||
{
|
||||
displayName: string,
|
||||
photoURL: string,
|
||||
}
|
||||
```
|
||||
|
||||
```javascript
|
||||
firebase.auth().currentUser
|
||||
.updateProfile({
|
||||
displayName: 'Display Name'
|
||||
})
|
||||
.then()
|
||||
.catch();
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Facebook authentication with react-native-fbsdk and signInWithCredential
|
||||
|
||||
```javascript
|
||||
import { AccessToken, LoginManager } from 'react-native-fbsdk';
|
||||
|
||||
// ... somewhere in your login screen component
|
||||
LoginManager
|
||||
.logInWithReadPermissions(['public_profile', 'email'])
|
||||
.then((result) => {
|
||||
if (result.isCancelled) {
|
||||
return Promise.resolve('cancelled');
|
||||
}
|
||||
console.log(`Login success with permissions: ${result.grantedPermissions.toString()}`);
|
||||
// get the access token
|
||||
return AccessToken.getCurrentAccessToken();
|
||||
})
|
||||
.then(data => {
|
||||
// create a new firebase credential with the token
|
||||
const credential = firebase.auth.FacebookAuthProvider.credential(data.accessToken);
|
||||
|
||||
// login with credential
|
||||
return firebase.auth().signInWithCredential(credential);
|
||||
})
|
||||
.then((currentUser) => {
|
||||
if (currentUser === 'cancelled') {
|
||||
console.log('Login cancelled');
|
||||
} else {
|
||||
// now signed in
|
||||
console.warn(JSON.stringify(currentUser.toJSON()));
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(`Login fail with error: ${error}`);
|
||||
});
|
||||
```
|
||||
145
docs/v2/modules/cloud-messaging.md
Normal file
145
docs/v2/modules/cloud-messaging.md
Normal file
@@ -0,0 +1,145 @@
|
||||
# Cloud Messaging
|
||||
|
||||
Firebase Cloud Messaging ([FCM](https://firebase.google.com/docs/cloud-messaging/)) allows you to send push messages at no
|
||||
cost to both Android & iOS platforms. Assuming the installation instructions have been followed, FCM is ready to go.
|
||||
|
||||
As the Firebase Web SDK has limited messaging functionality, the following methods within `react-native-firebase` have been
|
||||
created to handle FCM in the React Native environment.
|
||||
|
||||
Badge notification is well known on the iOS platform, but also supported by different Android devices / launchers.
|
||||
This library uses the [ShortcutBadger](https://github.com/leolin310148/ShortcutBadger) library to set the badge number
|
||||
also on Android. A list of supported launcher can be found there.
|
||||
|
||||
!> [iOS] Please note: In order for iOS devices to receive Cloud Messages, ensure you [request permissions](http://invertase.io/react-native-firebase/#/modules/cloud-messaging?id=ios-requestpermissions).
|
||||
|
||||
## API
|
||||
|
||||
### subscribeToTopic(topic: string)
|
||||
|
||||
Subscribes the device to a topic.
|
||||
|
||||
```javascript
|
||||
firebase.messaging().subscribeToTopic('foobar');
|
||||
```
|
||||
|
||||
### unsubscribeFromTopic(topic: string)
|
||||
|
||||
Unsubscribes the device from a topic.
|
||||
|
||||
```javascript
|
||||
firebase.messaging().unsubscribeFromTopic('foobar');
|
||||
```
|
||||
|
||||
### getInitialNotification(): `Promise<Object>`
|
||||
|
||||
When the application has been opened from a notification `getInitialNotification` is called and the notification payload
|
||||
is returned. Use `onMessage` for notifications when the app is running.
|
||||
|
||||
```javascript
|
||||
firebase.messaging().getInitialNotification()
|
||||
.then((notification) => {
|
||||
console.log('Notification which opened the app: ', notification);
|
||||
});
|
||||
```
|
||||
|
||||
### getToken(): `Promise<string>`
|
||||
|
||||
Returns the devices FCM token. This token can be used in the Firebase console to send messages to directly.
|
||||
|
||||
```javascript
|
||||
firebase.messaging().getToken()
|
||||
.then((token) => {
|
||||
console.log('Device FCM Token: ', token);
|
||||
});
|
||||
```
|
||||
|
||||
### onTokenRefresh(listener: `Function<string>`)
|
||||
|
||||
On the event a devices FCM token is refreshed by Google, the new token is returned in a callback listener.
|
||||
|
||||
```javascript
|
||||
firebase.messaging().onTokenRefresh((token) => {
|
||||
console.log('Refreshed FCM token: ', token);
|
||||
});
|
||||
```
|
||||
|
||||
### onMessage(listener: `Function<Object>`)
|
||||
|
||||
On a new message, the payload object is passed to the listener callback. This method is only triggered when the app is
|
||||
running. Use `getInitialNotification` for notifications which cause the app to open.
|
||||
|
||||
```javascript
|
||||
firebase.messaging().onMessage((message) => {
|
||||
// TODO
|
||||
});
|
||||
```
|
||||
|
||||
### createLocalNotification(notification: Object)
|
||||
|
||||
Create a local notification from the device itself.
|
||||
|
||||
// TODO
|
||||
|
||||
### scheduleLocalNotification(notification: Object)
|
||||
|
||||
Schedule a local notification to be shown on the device.
|
||||
|
||||
### getScheduledLocalNotifications(): `Promise<Array>`
|
||||
|
||||
Returns an array of all currently scheduled notifications.
|
||||
|
||||
```javascript
|
||||
firebase.messaging().getScheduledLocalNotifications()
|
||||
.then((notifications) => {
|
||||
console.log('Current scheduled notifications: ', notifications);
|
||||
});
|
||||
```
|
||||
|
||||
### cancelLocalNotification(id: string)
|
||||
|
||||
Cancels a location notification by ID, or all notifications by `*`.
|
||||
|
||||
```javascript
|
||||
// Cancel all local notifications
|
||||
firebase.messaging().cancelLocalNotification('*');
|
||||
// Cancel a single local notification
|
||||
firebase.messaging().cancelLocalNotification('123');
|
||||
```
|
||||
|
||||
### removeDeliveredNotification(id: string)
|
||||
|
||||
Removes all delivered notifications from device by ID, or all notifications by `*`.
|
||||
|
||||
```javascript
|
||||
// Remove all notifications
|
||||
firebase.messaging().removeDeliveredNotification('*');
|
||||
// Removes a single local notification
|
||||
firebase.messaging().removeDeliveredNotification('123');
|
||||
```
|
||||
|
||||
### [iOS] requestPermissions()
|
||||
|
||||
Requests app notification permissions in an Alert dialog.
|
||||
|
||||
```javascript
|
||||
firebase.messaging().requestPermissions();
|
||||
```
|
||||
|
||||
### setBadgeNumber(value: number)
|
||||
|
||||
Sets the badge number on the iOS app icon.
|
||||
|
||||
```javascript
|
||||
firebase.messaging().setBadgeNumber(2);
|
||||
```
|
||||
|
||||
### getBadgeNumber(): `Promise<number>`
|
||||
|
||||
Returns the current badge number on the app icon.
|
||||
|
||||
```javascript
|
||||
firebase.messaging().getBadgeNumber()
|
||||
.then((badgeNumber) => {
|
||||
console.log('Current badge number: ', badgeNumber);
|
||||
});
|
||||
```
|
||||
149
docs/v2/modules/config.md
Normal file
149
docs/v2/modules/config.md
Normal file
@@ -0,0 +1,149 @@
|
||||
# Remote Config
|
||||
|
||||
?> Remote Config is not available on the web SDK. Please read the [documentation](https://firebase.google.com/docs/remote-config) on when & why Remote Config benefits your app.
|
||||
|
||||
## API
|
||||
|
||||
### enableDeveloperMode()
|
||||
|
||||
Enable Remote Config developer mode to allow for frequent refreshes of the cache.
|
||||
|
||||
```js
|
||||
firebase.config().enableDeveloperMode();
|
||||
```
|
||||
|
||||
### setDefaults(defaults: `Object`)
|
||||
|
||||
Sets default values for the app to use when accessing values. Any data fetched and activated will override any default values.
|
||||
Any values in the defaults but not on Firebase will be untouched.
|
||||
|
||||
```js
|
||||
firebase.config().setDefaults({
|
||||
hasExperimentalFeature: false,
|
||||
});
|
||||
```
|
||||
|
||||
### fetch(duration?: `number`): `Promise<String>`
|
||||
|
||||
Fetches the remote config data from Firebase, defined in the dashboard.
|
||||
If duration is defined (seconds), data will be locally cached for this duration.
|
||||
|
||||
The default duration is 43200 seconds (12 hours). To force a cache refresh call the method with a duration of 0.
|
||||
|
||||
Thrown errors can be one of the following:
|
||||
* config/failure - Config fetch failed.
|
||||
* config/no_fetch_yet - Config has never been fetched.
|
||||
* config/throttled - Config fetch was throttled.
|
||||
|
||||
```js
|
||||
firebase.config()
|
||||
.fetch()
|
||||
.then(() => {
|
||||
console.log('Successfully fetched data');
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Unable to fetch remote config data: ', error);
|
||||
});
|
||||
```
|
||||
|
||||
### activateFetched(): `Promise<Boolean>`
|
||||
|
||||
Moves fetched data in the apps active config. Always successfully resolves with a boolean value.
|
||||
|
||||
```js
|
||||
firebase.config()
|
||||
.activateFetched()
|
||||
.then((success) => {
|
||||
if (success) {
|
||||
console.log('Successfully activated fetched config into active config');
|
||||
} else {
|
||||
console.log('No fetched config was found or fetched config is already active');
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### getValue(key: `String`): `Promise<Object>`
|
||||
|
||||
Gets a config item by key. Returns an object containing source (default, remote or static) and val function.
|
||||
|
||||
```js
|
||||
firebase.config()
|
||||
.getValue('foobar')
|
||||
.then((snapshot) => {
|
||||
console.log('Got value from source: ', snapshot.source);
|
||||
console.log('Value of foobar: ', snapshot.val());
|
||||
})
|
||||
.catch(console.error);
|
||||
```
|
||||
|
||||
### getValues(keys: `Array<String>`): `Promise<Object>`
|
||||
|
||||
Gets multiple values by key. Returns an object of keys with the same object returned from `getValue`.
|
||||
|
||||
```js
|
||||
firebase.config()
|
||||
.getValues(['foobar', 'barbaz'])
|
||||
.then((snapshot) => {
|
||||
console.log('Value of foobar: ', snapshot.foobar.val());
|
||||
console.log('Value of barbaz: ', snapshot.barbaz.val());
|
||||
})
|
||||
.catch(console.error);
|
||||
```
|
||||
|
||||
### getKeysByPrefix(prefix?: `String`): `Promise <Array<String>>`
|
||||
|
||||
Returns all keys as an array by a prefix. If no prefix is defined all keys are returned.
|
||||
|
||||
```js
|
||||
firebase.config()
|
||||
.getKeysByPrefix()
|
||||
.then((keys) => {
|
||||
console.log('Current keys: ', keys);
|
||||
});
|
||||
```
|
||||
|
||||
### setDefaultsFromResource(filename: `String`)
|
||||
|
||||
Sets the default values from a resource:
|
||||
|
||||
* Android: Id for the XML resource, which should be in your application's res/xml folder.
|
||||
* iOS: The plist file name, with no file name extension
|
||||
|
||||
```js
|
||||
// Anrdoid
|
||||
firebase.config().setDefaultsFromResource(1337);
|
||||
// iOS
|
||||
firebase.config().setDefaultsFromResource('configDefaults');
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
if (__DEV__) {
|
||||
firebase.config().enableDeveloperMode();
|
||||
}
|
||||
|
||||
// Set default values
|
||||
firebase.config().setDefaults({
|
||||
hasExperimentalFeature: false,
|
||||
});
|
||||
|
||||
firebase.config().fetch()
|
||||
.then(() => {
|
||||
return firebase.config().activateFetched();
|
||||
})
|
||||
.then((activated) => {
|
||||
if (!activated) console.log('Fetched data not activated');
|
||||
return firebase.config().getValue('hasExperimentalFeature');
|
||||
})
|
||||
.then((snapshot) => {
|
||||
const hasExperimentalFeature = snapshot.val();
|
||||
|
||||
if(hasExperimentalFeature) {
|
||||
// enableSuperCoolFeature();
|
||||
}
|
||||
|
||||
// continue booting app
|
||||
})
|
||||
.catch(console.error);
|
||||
```
|
||||
54
docs/v2/modules/crash.md
Normal file
54
docs/v2/modules/crash.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# Crash Reporting
|
||||
|
||||
RNFirebase provides crash reporting for your app out of the box. Please note crashes do not appear in real-time on the console, they tend to take a number of hours to appear.
|
||||
|
||||
## Enabling/Disabling Crash Reporting
|
||||
|
||||
By default crash reporting is enabled. If you want to disable reporting, call `setCrashCollectionEnabled(enabled: Boolean)`:
|
||||
|
||||
```js
|
||||
firebase.crash().setCrashCollectionEnabled(false);
|
||||
```
|
||||
|
||||
To check if crash reporting is currently enabled, call `isCrashCollectionEnabled(): Promise<boolean>`:
|
||||
|
||||
```js
|
||||
firebase.crash().isCrashCollectionEnabled()
|
||||
.then((enabled) => {
|
||||
if (enabled) {
|
||||
console.log('Crash Reporting is currently enabled');
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Manual Crash Reporting
|
||||
|
||||
If you want to manually report a crash, such as a pre-caught exception this is possible by using the `report` method.
|
||||
|
||||
```javascript
|
||||
try {
|
||||
initSomeSDK();
|
||||
} catch (e) {
|
||||
firebase.crash().log('Some SDK failed to boot!');
|
||||
firebase.crash().report(e);
|
||||
}
|
||||
```
|
||||
|
||||
### log
|
||||
|
||||
Logs a message that will appear in a subsequent crash report.
|
||||
|
||||
`firebase.crash().log(String message);`
|
||||
|
||||
### logcat
|
||||
|
||||
- **Android**: Logs a message that will appear in a subsequent crash report as well as in [logcat](https://developer.android.com/studio/command-line/logcat.html).
|
||||
- **iOS**: Logs the message in the subsequest crash report only (same as `log`).
|
||||
|
||||
`firebase.crash().logcat(int level, String tag, String message);`
|
||||
|
||||
### report
|
||||
|
||||
Files a crash report, along with any previous logs to Firebase. An [Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) object must be passed into the report method.
|
||||
|
||||
`firebase.crash().report(Error, int maxStackSize)`.
|
||||
204
docs/v2/modules/database.md
Normal file
204
docs/v2/modules/database.md
Normal file
@@ -0,0 +1,204 @@
|
||||
|
||||
# Realtime Database
|
||||
|
||||
RNFirebase mimics the [Web Firebase SDK Realtime Database](https://firebase.google.com/docs/database/web/read-and-write), whilst
|
||||
providing support for devices in low/no data connection state.
|
||||
|
||||
All real time Database operations are accessed via `database()`.
|
||||
|
||||
Basic read example:
|
||||
```javascript
|
||||
firebase.database()
|
||||
.ref('posts')
|
||||
.on('value', (snapshot) => {
|
||||
const value = snapshot.val();
|
||||
});
|
||||
```
|
||||
|
||||
Basic write example:
|
||||
```javascript
|
||||
firebase.database()
|
||||
.ref('posts/1234')
|
||||
.set({
|
||||
title: 'My awesome post',
|
||||
content: 'Some awesome content',
|
||||
});
|
||||
```
|
||||
|
||||
## Unmounted components
|
||||
|
||||
Listening to database updates on unmounted components will trigger a warning:
|
||||
|
||||
> Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the undefined component.
|
||||
|
||||
It is important to always unsubscribe the reference from receiving new updates once the component is no longer in use.
|
||||
This can be achived easily using [Reacts Component Lifecycle](https://facebook.github.io/react/docs/react-component.html#the-component-lifecycle) events:
|
||||
|
||||
Always ensure the handler function provided is of the same reference so RNFirebase can unsubscribe the ref listener.
|
||||
|
||||
```javascript
|
||||
class MyComponent extends Component {
|
||||
constructor() {
|
||||
super();
|
||||
this.ref = null;
|
||||
}
|
||||
|
||||
// On mount, subscribe to ref updates
|
||||
componentDidMount() {
|
||||
this.ref = firebase.database().ref('posts/1234');
|
||||
this.ref.on('value', this.handlePostUpdate);
|
||||
}
|
||||
|
||||
// On unmount, ensure we no longer listen for updates
|
||||
componentWillUnmount() {
|
||||
if (this.ref) {
|
||||
this.ref.off('value', this.handlePostUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
// Bind the method only once to keep the same reference
|
||||
handlePostUpdate = (snapshot) => {
|
||||
console.log('Post Content', snapshot.val());
|
||||
}
|
||||
|
||||
render() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Usage in offline environments
|
||||
|
||||
### Reading data
|
||||
|
||||
Firebase allows the database instance to [persist on disk](https://firebase.google.com/docs/database/android/offline-capabilities) if enabled.
|
||||
To enable database persistence, pass the configuration option `persistence` before calls are made:
|
||||
|
||||
```javascript
|
||||
const configurationOptions = {
|
||||
persistence: true
|
||||
};
|
||||
const firebase = new RNFirebase(configurationOptions);
|
||||
```
|
||||
|
||||
Any subsequent calls to Firebase stores the data for the ref on disk.
|
||||
|
||||
### Writing data
|
||||
|
||||
Out of the box, Firebase has great support for writing operations in offline environments. Calling a write command whilst offline
|
||||
will always trigger any subscribed refs with new data. Once the device reconnects to Firebase, it will be synced with the server.
|
||||
|
||||
The following todo code snippet will work in both online and offline environments:
|
||||
|
||||
```javascript
|
||||
// Assume the todos are stored as an object value on Firebase as:
|
||||
// { name: string, complete: boolean }
|
||||
|
||||
class ToDos extends Component {
|
||||
constructor() {
|
||||
super();
|
||||
this.ref = null;
|
||||
this.listView = new ListView.DataSource({
|
||||
rowHasChanged: (r1, r2) => r1 !== r2,
|
||||
});
|
||||
|
||||
this.state = {
|
||||
todos: this.listView.cloneWithRows({}),
|
||||
};
|
||||
|
||||
// Keep a local reference of the TODO items
|
||||
this.todos = {};
|
||||
}
|
||||
|
||||
// Load the Todos on mount
|
||||
componentDidMount() {
|
||||
this.ref = firebase.database().ref('users/1234/todos');
|
||||
this.ref.on('value', this.handleToDoUpdate);
|
||||
}
|
||||
|
||||
// Unsubscribe from the todos on unmount
|
||||
componentWillUnmount() {
|
||||
if (this.ref) {
|
||||
this.ref.off('value', this.handleToDoUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle ToDo updates
|
||||
handleToDoUpdate = (snapshot) => {
|
||||
this.todos = snapshot.val() || {};
|
||||
|
||||
this.setState({
|
||||
todos: this.listView.cloneWithRows(this.todos),
|
||||
});
|
||||
}
|
||||
|
||||
// Add a new ToDo onto Firebase
|
||||
// If offline, this will still trigger an update to handleToDoUpdate
|
||||
addToDo() {
|
||||
firebase.database()
|
||||
.ref('users/1234/todos')
|
||||
.set({
|
||||
...this.todos, {
|
||||
name: 'Yet another todo...',
|
||||
complete: false,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Render a ToDo row
|
||||
renderToDo(todo) {
|
||||
// Dont render the todo if its complete
|
||||
if (todo.complete) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<View>
|
||||
<Text>{todo.name}</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
// Render the list of ToDos with a Button
|
||||
render() {
|
||||
return (
|
||||
<View>
|
||||
<ListView
|
||||
dataSource={this.state.todos}
|
||||
renderRow={(...args) => this.renderToDo(...args)}
|
||||
/>
|
||||
|
||||
<Button
|
||||
title={'Add ToDo'}
|
||||
onPress={() => this.addToDo}
|
||||
/>
|
||||
<View>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
#### Differences between `.on` & `.once`
|
||||
|
||||
With persistence enabled, any calls to a ref with `.once` will always read the data from disk and not contact the server.
|
||||
On behaves differently, by first checking for a connection and if none exists returns the persisted data. If it successfully connects
|
||||
to the server, the new data will be returned and the disk data will be updated.
|
||||
|
||||
The database refs has a `keepSynced()` function to tell the RNFirebase library to keep the data at the `ref` in sync.
|
||||
|
||||
```javascript
|
||||
const ref = firebase.database
|
||||
.ref('chat-messages')
|
||||
.child('roomId');
|
||||
ref.keepSynced(true);
|
||||
```
|
||||
|
||||
#### Security rules and offline persistence
|
||||
|
||||
Bear in mind that security rules live on the firebase server and **not in the client**. In other words, when offline, your app knows nothing about your database's security rules. This can lead to unexpected behaviour, which is explained in detail in the following blog post: https://firebase.googleblog.com/2016/11/what-happens-to-database-listeners-when-security-rules-reject-an-update.html
|
||||
|
||||
Some examples of behaviour you may not expect but may encounter are:
|
||||
|
||||
- Values that should not be readable, according to your security rules, are readable if they were created on the same device.
|
||||
- Values are readable even when not authenticated, if they were created on the same device.
|
||||
- Locations are writable even when they should not be, according to your security rules. This is more likely to cause unwanted behaviour when your app is offline, because when it is *online* the SDK will very quickly roll back the write once the server returns a permission error.
|
||||
66
docs/v2/modules/perf.md
Normal file
66
docs/v2/modules/perf.md
Normal file
@@ -0,0 +1,66 @@
|
||||
# Performance Monitoring
|
||||
|
||||
!> Performance monitoring requires react-native-firebase version 1.2.0.
|
||||
|
||||
?> Android: If you plan on using this module in your own application, please ensure the optional setup instructions for
|
||||
[Android](http://invertase.io/react-native-firebase/#/installation-android?id=_4-performance-monitoring-optional) have been followed.
|
||||
|
||||
Out of the box, [Firebase Performance Monitoring](https://firebase.google.com/docs/perf-mon/automatic) monitors a number of
|
||||
[automatic traces](https://firebase.google.com/docs/perf-mon/automatic) such as app start/background/foreground response times.
|
||||
You can easily trace your own events with RNFirebase:
|
||||
|
||||
## API
|
||||
|
||||
#### setPerformanceCollectionEnabled(enabled: `boolean`)
|
||||
|
||||
Globally enables or disables performance monitoring capture across the app.
|
||||
|
||||
```js
|
||||
firebase.perf().setPerformanceCollectionEnabled(false); // Disable
|
||||
```
|
||||
|
||||
#### newTrace(id: `string`): `Trace`
|
||||
|
||||
Returns a new instance of Trace (see API below). The id is the unique name of something you'd like to run performance
|
||||
monitoring against.
|
||||
|
||||
```js
|
||||
const trace = firebase.perf().newTrace("test_trace");
|
||||
```
|
||||
|
||||
### Trace
|
||||
|
||||
!> Once a trace has been started and stopped, you cannot re-start it in the same app lifecycle.
|
||||
|
||||
#### start()
|
||||
|
||||
Initializes the trace to start tracing performance to relay back to Firebase.
|
||||
|
||||
```js
|
||||
trace.start();
|
||||
```
|
||||
|
||||
#### incrementCounter(event: string)
|
||||
|
||||
Notifies Firebase an event has occured. These events will be visible on Firebase once your trace has stopped.
|
||||
|
||||
```js
|
||||
someCacheService.get('user:123')
|
||||
.then((user) => {
|
||||
if (user) {
|
||||
trace.incrementCounter('user_cache_hit');
|
||||
} else {
|
||||
trace.incrementCounter('user_cache_missed');
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
#### stop()
|
||||
|
||||
Stops performance tracing. The completed trace stats are now sent to Firebase.
|
||||
|
||||
?> Results are not realtime. They can take a number of hours to appear in the Firebase console.
|
||||
|
||||
```js
|
||||
trace.stop();
|
||||
```
|
||||
100
docs/v2/modules/storage.md
Normal file
100
docs/v2/modules/storage.md
Normal file
@@ -0,0 +1,100 @@
|
||||
# Storage
|
||||
|
||||
RNFirebase mimics the [Web Firebase SDK Storage](https://firebase.google.com/docs/storage/web/start), whilst
|
||||
providing some iOS and Android specific functionality.
|
||||
|
||||
## Uploading files
|
||||
|
||||
### Simple
|
||||
|
||||
```javascript
|
||||
firebase.storage()
|
||||
.ref('/files/1234')
|
||||
.putFile('/path/to/file/1234')
|
||||
.then(uploadedFile => {
|
||||
//success
|
||||
})
|
||||
.catch(err => {
|
||||
//Error
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
### With metadata
|
||||
|
||||
```javascript
|
||||
const metadata = {
|
||||
contentType: 'image/jpeg'
|
||||
}
|
||||
firebase.storage()
|
||||
.ref('/files/1234')
|
||||
.putFile('/path/to/file/1234', metadata)
|
||||
```
|
||||
|
||||
### Listen to upload state
|
||||
|
||||
```javascript
|
||||
const unsubscribe = firebase.storage()
|
||||
.ref('/files/1234')
|
||||
.putFile('/path/to/file/1234')
|
||||
.on('state_changed', snapshot => {
|
||||
//Current upload state
|
||||
}, err => {
|
||||
//Error
|
||||
unsubscribe();
|
||||
}, uploadedFile => {
|
||||
//Success
|
||||
unsubscribe();
|
||||
});
|
||||
```
|
||||
|
||||
## Downloading files
|
||||
|
||||
### Simple
|
||||
|
||||
```javascript
|
||||
firebase.storage()
|
||||
.ref('/files/1234')
|
||||
.downloadFile('/path/to/save/file')
|
||||
.then(downloadedFile => {
|
||||
//success
|
||||
})
|
||||
.catch(err => {
|
||||
//Error
|
||||
});
|
||||
```
|
||||
|
||||
### Listen to download state
|
||||
|
||||
```javascript
|
||||
const unsubscribe = firebase.storage()
|
||||
.ref('/files/1234')
|
||||
.downloadFile('/path/to/save/file')
|
||||
.on('state_changed', snapshot => {
|
||||
//Current download state
|
||||
}, err => {
|
||||
//Error
|
||||
unsubscribe();
|
||||
}, downloadedFile => {
|
||||
//Success
|
||||
unsubscribe();
|
||||
});
|
||||
```
|
||||
|
||||
## TODO
|
||||
|
||||
There are a few methods which have not yet been implemented for Storage:
|
||||
|
||||
### Reference
|
||||
- put()
|
||||
- putString()
|
||||
|
||||
### UploadTask
|
||||
- cancel()
|
||||
- pause()
|
||||
- resume()
|
||||
|
||||
### DownloadTask
|
||||
- cancel()
|
||||
- pause()
|
||||
- resume()
|
||||
35
docs/v2/modules/transactions.md
Normal file
35
docs/v2/modules/transactions.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# Transactions
|
||||
|
||||
?> For help on how to use firebase transactions please see the [Firebase Transaction Documentation](https://firebase.google.com/docs/reference/js/firebase.database.Reference#transaction).
|
||||
|
||||
### Android Implementation
|
||||
|
||||
The [android implementation](https://github.com/invertase/react-native-firebase/blob/master/android/src/main/java/io/invertase/firebase/database/RNFirebaseTransactionHandler.java) makes use of [Condition](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Condition.html) and [ReentrantLock](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantLock.html) locks to handle transactions across the React Native Bridge.
|
||||
|
||||
|
||||
### iOS Implementation
|
||||
|
||||
The [iOS implementation](https://github.com/invertase/react-native-firebase/blob/master/ios/RNFirebase/RNFirebaseDatabase.m#L279) makes use of GCD (Grand Central Dispatch) to handle transactions across the React Native Bridge without blocking the application thread. Check out [this](https://mikeash.com/pyblog/friday-qa-2011-10-14-whats-new-in-gcd.html) post for some 'light' reading about it.
|
||||
|
||||
!> Transactions that receive no response from react native's JS thread within 30 seconds are automatically aborted - this value is currently not configurable - PR welcome.
|
||||
|
||||
|
||||
## Example
|
||||
|
||||
```javascript
|
||||
const ref = firebase.database().ref('user/posts');
|
||||
|
||||
ref.transaction((posts) => {
|
||||
return (posts || 0) + 1;
|
||||
}, (error, committed, snapshot) => {
|
||||
if (error) {
|
||||
console.log('Something went wrong', error);
|
||||
} else if (!committed) {
|
||||
console.log('Aborted'); // Returning undefined will trigger this
|
||||
} else {
|
||||
console.log('User posts incremented by 1');
|
||||
}
|
||||
|
||||
console.log('User posts is now: ', snapshot.val());
|
||||
});
|
||||
```
|
||||
125
docs/v2/redux.md
Normal file
125
docs/v2/redux.md
Normal file
@@ -0,0 +1,125 @@
|
||||
# Usage with Redux
|
||||
|
||||
Although RNFirebase usage requires a React Native environment, it isn't tightly coupled which allows for full flexibility
|
||||
when it comes to integrating with other modules such a [`react-redux`](https://github.com/reactjs/react-redux). If you wish to use
|
||||
a Redux library designed for Firebase, we suggest taking a look at [`react-redux-firebase`](http://docs.react-redux-firebase.com/history/v2.0.0/docs/recipes/react-native.html)
|
||||
for implementation with this module.
|
||||
|
||||
## Standalone integration
|
||||
|
||||
Although the following example works for a basic redux setup, it may differ when integrating with other redux middleware.
|
||||
Imagine a simple TODO app, with redux we're able to abstract the Firebase logic out of components which allows for greater
|
||||
testability and maintainability.
|
||||
|
||||
?> We use [`redux-thunk`](https://github.com/gaearon/redux-thunk) to provide async actions.
|
||||
|
||||
### Action Creators
|
||||
|
||||
```js
|
||||
// Actions
|
||||
export const subscribe = () => {
|
||||
return (dispatch) => {
|
||||
firebase.database().ref('todos').on('value', (snapshot) => {
|
||||
const todos = [];
|
||||
|
||||
snapshot.forEach((childSnapshot) => {
|
||||
todos.push({
|
||||
id: childSnapshot.key,
|
||||
...(childSnapshot.val()),
|
||||
})
|
||||
})
|
||||
|
||||
dispatch({
|
||||
type: 'TODO_UPDATE',
|
||||
todos,
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Methods
|
||||
export const addTodo = text => {
|
||||
firebase.database().ref('todos').push({
|
||||
text,
|
||||
visible: true,
|
||||
})
|
||||
}
|
||||
|
||||
export const completeTodo = id => {
|
||||
firebase.database().ref(`todos/${id}`).update({
|
||||
visible: false,
|
||||
})
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Instead of creating multiple actions which the reducers handle, we instead subscribe to the database ref and on any changes,
|
||||
send a single action for the reducers to handle with the data which is constantly updating.
|
||||
|
||||
### Reducers
|
||||
|
||||
Our reducer now becomes really simple, as we're able to simply update the reducers state with whatever data has been returned
|
||||
from our Firebase subscription.
|
||||
|
||||
```js
|
||||
const todos = (state = {}, action) => {
|
||||
switch (action.type) {
|
||||
case 'TODO_UPDATE':
|
||||
return { ...action.todos };
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
export default todos;
|
||||
```
|
||||
|
||||
### Component
|
||||
|
||||
We can now easily subscribe to the todos in redux state and get live updates when Firebase updates.
|
||||
|
||||
```js
|
||||
import React from 'react';
|
||||
import { FlatList } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import { subscribe, addTodo, completeTodo } from '../actions/TodoActions.js';
|
||||
...
|
||||
|
||||
class Todos extends React.Component {
|
||||
|
||||
componentDidMount() {
|
||||
this.props.dispatch(
|
||||
subscribe()
|
||||
);
|
||||
}
|
||||
|
||||
onComplete = (id) => {
|
||||
this.props.dispatch(
|
||||
completeTodo(id)
|
||||
);
|
||||
};
|
||||
|
||||
onAdd = (text) => {
|
||||
this.props.dispatch(
|
||||
addTodo(text)
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<FlatList
|
||||
data={this.props.todos}
|
||||
...
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
todos: state.todos,
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(Todos);
|
||||
```
|
||||
38
docs/v2/usage.md
Normal file
38
docs/v2/usage.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# Usage
|
||||
|
||||
After creating a Firebase project and installing the library, we can use it in our project by importing the library in our JavaScript:
|
||||
|
||||
```javascript
|
||||
import RNFirebase from 'react-native-firebase'
|
||||
```
|
||||
|
||||
We need to tell the Firebase library we want to _configure_ the project. RNFirebase provides a way to configure both the native and the JavaScript side of the project at the same time with a single command:
|
||||
|
||||
```javascript
|
||||
const firebase = RNFirebase.initializeApp({
|
||||
// config options
|
||||
});
|
||||
```
|
||||
|
||||
## Configuration Options
|
||||
|
||||
| option | type | Default Value | Description |
|
||||
|----------------|----------|-------------------------|----------------------------------------|
|
||||
| debug | bool | false | When set to true, RNFirebase will log messages to the console and fire `debug` events we can listen to in `js` |
|
||||
| persistence | bool | false | When set to true, database persistence will be enabled. |
|
||||
| errorOnMissingPlayServices | bool | true | (Android only) When set to true, will throw an error if Google Play Services isn't installed. |
|
||||
| promptOnMissingPlayServices | bool | true | (Android only) When set to true, will prompt the user to install Google Play Services if it isn't installed. This takes precedence over `errorOnMissingPlayServices`.|
|
||||
|
||||
For instance:
|
||||
|
||||
```javascript
|
||||
import RNFirebase from 'react-native-firebase';
|
||||
|
||||
const configurationOptions = {
|
||||
debug: true
|
||||
};
|
||||
|
||||
const firebase = RNFirebase.initializeApp(configurationOptions);
|
||||
|
||||
export default firebase;
|
||||
```
|
||||
Reference in New Issue
Block a user