Implement Firebase inside of a Library - android

I want to implement Firebase notifications system inside a library that I want to use as SDK in many apps.
Firebase is asking now for an App ID, but I'm implementing it inside a library, thus no App Id.
How could I achieve my goal to be able to send notifications to my apps that use my library ?
Thanks in advance.

These are all kinda hacky or too much work, here’s a nice n simple example (ironic though, cause it’s a long post -- but worth it).
It is possible to use FireBase code in your library project, of course the consuming application will need to register the app and get the app ID / google-services.json file.
But your library doesn’t, and shouldn’t care about about that, it’s the consuming applications job to do that, not your library.
Here’s a brief example using the firebase-messaging module inside of a library project.
YourLibrary module’s build.gradle:
// Other typical library set up
apply plugin: 'com.android.library'
android {
compileSdkVersion 27
defaultConfig {
minSdkVersion 16
targetSdkVersion 27
versionCode 1
versionName '1.0'
// Don’t for get your library’s proguard file!
consumerProguardFiles 'proguard-rules.pro'
}
}
ext {
currentFirebaseVersion = "11.8.0"
}
dependencies {
/*
Here we depend on the firebase messaging dependency (via compileOnly),
allowing us to use the FireBase API within our library module.
I exclude that org.json module because it may cause build warnings, this
step isn’t totally necessary.
NOTE: You should use `compileOnly` here so the dependency is
not added to the build output You will be allowed to use the
dependency in your library. If the consuming app wants to use firebase
they’ll need to depend on it (using `implementation`).
*/
compileOnly("com.google.firebase:firebase-messaging:$currentFirebaseVersion") {
exclude group: 'org.json', module: 'json'
}
}
// Other typical library set up. But nothing else relating Firebase.
This is all you need to do in your library project. DON’T apply the gms plug in here, and don’t add the google-services classpath to the libraries build.gradle.
Now here’s how you set up your consuming app:
MyClientApp’s top-level build.gradle:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google() // You know the drill...
}
// Any other set up you might have...
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
/*
Here in your client app’s top-level build.gradle you add the
google-services to the app’s classpath.
*/
classpath 'com.google.gms:google-services:3.2.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
// Other basic stuff...
allprojects {
apply plugin: 'maven'
apply plugin: 'maven-publish'
repositories {
jcenter()
google()
}
}
Now we need to set up the consuming applications module build.gradle, it’s simple. We pretty much just need to apply the plug-in, and depend on the library module that we create that has all the FireBase code in it.
MyClientApp’s module level build.gradle:
buildscript {
repositories {
google()
mavenLocal()
}
}
apply plugin: 'com.android.application'
android {
compileSdkVersion 27
defaultConfig {
applicationId "com.your.application.that.can.use.firebase"
minSdkVersion 16
targetSdkVersion 27
versionCode 1
versionName '1.0'
}
//other typical set up
}
ext {
currentFirebaseVersion = "11.8.0"
}
dependencies {
implementation('com.your.library:YourLibrary:1.0#aar') {
transitive = true
// Use the consuming application's FireBase module, so exclude it
// from the dependency. (not totally necessary if you use compileOnly
// when declaring the dependency in the library project).
exclude group: 'com.google.firebase'
// Exclude the "plain java" json module to fix build warnings.
exclude group: 'org.json', module: 'json'
}
implementation("com.google.firebase:firebase-messaging:$currentFirebaseVersion") {
// Exclude the "plain java" json module to fix build warnings.
exclude group: 'org.json', module: 'json'
}
}
// Needs to be at the bottom of file.
apply plugin: 'com.google.gms.google-services'
Some things to note:
Must apply google-services plugin at the bottom (only in the client module build.gradle).
Depend on the library module that has the FireBase code in it, but exclude it’s version of the FireBase module, in favor of your own dependency version.
App depends on it's own FireBase version.
classpath 'com.google.gms:google-services:3.1.1’ only goes in the client app’s top level build.gradle.
Of course you will need to register the client app and put the google-services.json in your client app’s project.
Define the necessary Firebase Services in your app’s manifest (or use manifest merger and merge them in from your library project)
Add the google_play_services_version meta-data tag to your client app’s Manifest.
The library can/should use compileOnly when declaring the FireBase dependency.
Now you’ll be able to use FireBase code in your app that you defined in your library that uses FireBase. Or you could let your library module do all the FireBase work!
Of course this is typically used for internal libraries, as frameworks like Firebase weren’t designed to be implemented in library modules, but sometimes you need to, so this is a simple non-hacky/sane solution to the issue. It can be used on projects that are distributed through maven -- my library uses this, and it’s never caused any issues.
Update:
You should use compileOnly when declaring the library module's Firebase dependency. By doing so the dependency will not be added to the build output. But you will be allowed to use the dependency in your library. If the consuming app wants to use firebase they’ll need to depend on it manually (using implementation). This will help cut down on unneeded dependencies/bloat in applications and the “right” way to declare a dependency like this. Note: You may need to perform runtime checks to make sure the library is available before using it’s code in your module.

Yes you can actually do this, on your library build.gradle put this inside the defaultConfig field
buildConfigField("String", "FIREBASE_APP_KEY", "\"${firebaseAppKey}\"")
Then inside your project's gradle.properties
firebaseAppKey = <yourFirebaseAppSecret>;
For each project/app you must define this variable on your gradle.properties.
You'll have to create a firebase app for each project, but your library can now have the Firebase SDK.
When you want to access this environment variable value use BuildConfig.FIREBASE_APP_KEY
(e.g. instantiate firebase).

I know this is an old question with an accepted answer but all the answers have a big disadvantage - they require the user of your library to do work besides adding your library to their application. There is a way to do it without troubling the user of your library at all if your library is being downloaded from a Maven repository.
Note: this method is a hack and is not supported by Firebase. When asked Firebase Support, I got the following reply:
Firebase SDKs are not intended for library projects. The features available on Firebase were integrated in an application level and not
on a per module or per library basis so, the use case for having this
integrated on a library project is not possible or not supported.
Nevertheless, I've found a way to do it and maybe someone will find it useful so here it is:
This is an example of using Realtime Database but it should work for all the Firebase SDKs.
In your project's main build.gradle add mavenCentral repository:
allprojects {
repositories {
...
mavenCentral()
}
}
In your library project's build.gradle, add Google Play Services (as a dependency, not as a plugin):
compile 'com.google.android.gms:play-services-gcm:11.0.4'
Add the relevant Firebase SDKs (with the same version as Google Play Services):
compile 'com.google.firebase:firebase-core:11.0.4'
compile 'com.google.firebase:firebase-database:11.0.4'
Register your SDK as a project on Firebase, download it's google-services.json and open it with any text editor.
In your library's strings.xml add the following lines and fill these lines with data from google-services.json
<string name="gcm_defaultSenderId">project_number</string>
<string name="google_api_key">current_key</string>
<string name="google_app_id">mobilesdk_app_id</string>
<string name="google_crash_reporting_api_key">current_key</string>
<string name="google_storage_bucket">storage_bucket</string>
<string name="firebase_database_url">firebase_url</string>
<string name="default_web_client_id">client_id</string>
<string name="project_id">project_id</string>
This is it. You can use Firebase Realtime Database in your libaray, then build it and publish it to Maven (publishing to Maven is essential, otherwise the user of your library will have to add the dependencies manually). When activated from inside an application, your database will be used.
Note that this method may cause exceptions and unexpected behavior if the user of your library will use Google Play Services or Firebase so use at your own risk!

One option is to have the user of your library create a Firebase project and then pass in the resulting google-services.json file into their application then your library can depend on that.

Firebase Multiple Project
Please refer to the link it has all the information

Related

Adding a library as an aar file in gradle not able to implement interfaces

It would be easier for me to show you but the long story short.
Main Application
Created a Library lets call it SECOND
Created a Shopping List Library call it THIRD
When I add my THIRD dependency to my SECOND library when using implementation in the gradle file, I am not able to implement interfaces for some reason. When using api it works just fine.
Also, we are adding this by importing the aar and pom file manually.
Project Level Gradle For SECOND
allprojects {
repositories {
google()
jcenter()
maven { url "$projectDir/../THIRD" }
}
}
Only way to actually allow access to the interfaces is to use API
api('com.THIRD.#aar')
This is quite as expected: declarations from implementation dependencies of a library are not visible during compilation of the library usages and are only available at runtime.
On contrary, api dependencies are visible during compilation of the library usages, too.
You should only use the implementation configuration if you don't want the library users to see the declaration from a dependency, which is certainly not the case if you expect the user to implement an interface from the dependency.
See: Gradle dependency configuration: implementation vs api vs runtimeonly vs compileonly

Using Firebase in a multi-module project

I have a multi-module multi-flavor android project, the modules are as follows:
core module, which is an android library that holds common stuff, including library dependencies.
authentication module, which is as the name suggests, a module that contains a bunch of UI activities and is responsible for authenticating users. It's also the module that has the launcher activity.
user module, which is another android library module. It is responsible for handling user profile UI, user data, along with Firebase database. But it also has to deal with Firebase authentication to get the Uid as it's used as key in the database.
Other modules that are irrelevant right now
The module core does nothing with respect to Firebase, except just include it as a dependency for other modules. So I have this in my project build.gradle:
dependencies {
classpath 'com.android.tools.build:gradle:3.2.0'
classpath 'com.google.gms:google-services:4.1.0'
}
and I also have this in my core build.gradle:
apply plugin: 'com.android.library'
apply plugin: 'com.google.gms.google-services'
android {
compileSdkVersion 28
defaultConfig {
minSdkVersion 19
targetSdkVersion 28
versionCode 1
versionName "1.0"
otherstuff
}
otherStuff
}
dependencies {
otherStuff
api 'com.google.android.gms:play-services-base:16.1.0'
api 'com.google.firebase:firebase-core:16.0.6'
api 'com.google.firebase:firebase-auth:16.1.0'
api 'com.google.firebase:firebase-database:16.0.6'
api 'com.google.firebase:firebase-storage:16.0.5'
api 'com.hbb20:ccp:2.2.3'
api 'com.google.android.libraries.places:places:1.0.0'
}
The user module does nothing except import the core library, and use authentication right away. So I have the following in my user build.gradle:
dependencies {
otherStuff
implementation project(':core')
}
and then I proceed to use it in my classes like so:
FirebaseAuth auth = FirebaseAuth.getInstance();
boolean isLoggedIn()
{
assert(auth != null);
return (auth.getCurrentUser() != null);
}
void uploadUserImpl()
{
assert(isLoggedIn());
db.getReference("users").child(auth.getCurrentUser().getUid()).setValue(this);
}
etc
The authentication module is the one that defines the app name, the launcher activity, etc. So, in my mind at least, it's also the one that should have the google-services.json file. So it has it under the authentication folder.
It includes both core and user libraries, so in my authentication build.gradle I have the following:
dependencies {
otherStuff
implementation project(':core')
implementation project(':user')
}
It also proceeds to use Firebase authentication for logging in and signing up users.
Now with the problem:
trying to build the project, I get the following error:
File google-services.json is missing. The Google Services Plugin cannot function without it.
Searched Location:
/work/mewais/CompanyName/ProjectName/core/src/FlavorName/debug/google-services.json
/work/mewais/CompanyName/ProjectName/core/google-services.json
and if I try to copy the google-services.json under core too, I get the following error:
No matching client found for package name 'com.companyname.projectname.core'
the google-services.json file has the app name defined inside it as:
"package_name": "com.companyname.projectname.appname"
which obviously expects the app name and not core.
So how to include Firebase in this setting? I want to keep the firebase dependencies defined inside core because multiple modules will use it. At the same time, authentication is the one that actually defines the appname and is also the one that has the launcher activity in which I start to use Firebase. I also expect user and any other modules to be able to use Firebase after that. It doesn't make sense to me to register all modules with Firebase (not even sure if it's possible since Firebase expects an app not a library?!). So is there anyway to fix this issue?
I managed to wrap firebase dependencies into a library module without polluting the main module. Here is what I did:
google-play-services plugin requires the module that includes it to have applicationId and its JSON file(or it won't compile).
If you're sure you don't use special functions that google-play-services plugin provides, you can delete them.
https://developers.google.com/android/guides/google-services-plugin
Then you can follow this article's instructions:
https://medium.com/#samstern_58566/how-to-use-firebase-on-android-without-the-google-services-plugin-93ecc7dc6c4
Update: Another Link
https://firebase.google.com/docs/projects/multiprojects#support_multiple_environments_in_your_android_application
Because this provider is just reading resources with known names, another option is to add the string resources directly to your app instead of using the Google Services gradle plugin.
you may put a google-services.json file in flavor accoding to use:-
check this link
android {
// set build flavor here to get the right gcm configuration.
//def myFlavor = "flavor1"
def myFlavor = "flavor2"
if (myFlavor.equals("flavor1")) {
println "--> flavor1 copy!"
copy {
from 'src/flavor1/'
include '*.json'
into '.'
}
} else {
println "--> flavor2 copy!"
copy {
from 'src/flavor2/'
include '*.json'
into '.'
}
}
// other stuff
}

Why firebase-core has so many dependendencies?

I added only one line to app.gradle:
implementation 'com.google.firebase:firebase-core:11.6.2'
As a result, these libraries have added:
Does firebase really use them all? I didn't use support libraries before, but now I have to.
Can I get rid these deps?
UPDATE: I conducted an investigation to find out the cause of all the dependencies:
As you can see the most of dependencies have come from firebase-core.
No, they are not all related to firebase, the libraries with versions 25.2.0 are support libraries from android. To learn more read this:
https://developer.android.com/topic/libraries/support-library/packages.html
You cannot remove them, as they are inside maven which is declared in your build.gradle file:
allprojects {
repositories {
jcenter()
maven {
url "https://maven.google.com"
}
}
}
The libraries with version 11.6.2 are all related to firebase, since firebase has to have all libraries with same version number. According to this Firebase Libraries the firebase core are used to add analytics services, but also for firebase to work it uses the other libraries like com.google.android.gms:play-services-task-11.6.2

How to obtain firebase libraries, e.g. firebase-messaging-9.4.0.jar

I am trying to do an automated android build in a local network segment (ie. without access to public jcenter or maven repositories). In order to do that I need to provide all dependencies in a local maven repository which is referenced from the root build.gradle. (NB: if I use the android-maven-plugin instead of gradle the situation is the same).
This works fine, only I have difficulties locating the firebase libraries like firebase-core-9.4.0.jar or firebase-messaging-9.4.0.jar. According to the gradle console output they are searched in a location
<server>/com/google/firebase/firebase-messaging/9.4.0/firebase-messaging-9.4.0.jar
This location does not exist in the public jcenter or maven repositories.
Does anyone know where to find them?
edit: I have observed Android Studio on empty caches using Wireshark (using http for the jcenter repository). The results are rather mysterious. It issues a GET request for
http://jcenter.bintray.com/com/google/firebase/firebase-messaging/9.4.0/firebase-messaging-9.4.0.jar
This request is redirected to
http://repo.jfrog.org/artifactory/libs-release-bintray/com/google/firebase/firebase-messaging/9.4.0/firebase-messaging-9.4.0.jar?referrer
The latter GET request results in HTTP 404 as the repo.jfrog.org repository has no content in the firebase-messaging/ directory. However, Android Studio extracts the jar files in the build directory and continues to build the project.It is unclear, where the jar files come from.
You can show all librarys in the oficial support.
https://firebase.google.com/docs/android/setup
Found this link, hope this help
https://github.com/unity-plugins/Google-Firebase-SDK
According to this, you should add to you build.gradle:
buildscript {
// ...
dependencies {
// ...
classpath 'com.google.gms:google-services:3.1.1'
and that to your app/build.gradle:
apply plugin: 'com.android.application'
android {
// ...
}
dependencies {
// ...
compile 'com.google.firebase:firebase-core:11.8.0'
// Getting a "Could not find" error? Make sure you have
// the latest Google Repository in the Android SDK manager
}
// ADD THIS AT THE BOTTOM
apply plugin: 'com.google.gms.google-services'
Update 2020
Firebase aar are now available on maven repository at https://mvnrepository.com/artifact/com.google.firebase
For example, firebase-core aar is at https://maven.google.com/com/google/firebase/firebase-core/17.4.4/firebase-core-17.4.4.aar

Android Studio - Build AAR to combine multiple modules/libraries [duplicate]

I am building android library project, which has a dependency on another internal library project.
I am wondering if there is a way to package a single AAR library, which already contains internal library inside it. I would like to share only 1 AAR library package to my application developers.
This is how my build.gradle files look currently, but currently they produce separate AAR files and both needs to be included in Application's build.gradle. As application is being built by another company, we need to share the final AAR file with them and not the complete library projects.
----- internalLib -------->>>>>>>>>>
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.7.+'
}
}
apply plugin: 'android-library'
repositories {
mavenCentral()
}
android {
compileSdkVersion 18
buildToolsVersion '18.1.1'
}
dependencies {
compile 'com.android.support:support-v4:18.0.0'
}
----- externalLib --------
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.7.+'
}
}
apply plugin: 'android-library'
repositories {
mavenCentral()
}
android {
compileSdkVersion 18
buildToolsVersion '18.1.1'
}
dependencies {
compile 'com.android.support:support-v4:18.0.0'
compile project(':internalLib')
}
There is no mechanism to combine library. It's a bit complicated as you probably want to control which dependencies get merged (for instance you probably don't want to include support-v4 in there). Also you'd need to merge the resources and Android manifest.
At this time there's no way to easily hack something, unless you are sure the resources have no conflicts between the two res folders (for instance you could have strings_a.xml in one lib and strings_b.xml in the other lib). This way you can just "merge" the two res folders by copying them both into the same location (as opposed to do a merge at the android res level).
For the Manifest it'd be more complicated, but doable with some custom code.
Providing a built-in mechanism for this is very low on our priority so don't expect it anytime soon.
For the sake you have to upload each library as separately on maven and use its implementation in parent library modules till the main library module. Only then when you publish your main library on maven will include your all child dependencies.
As far as we have only one option add aar as api dependency inside the module.
For that we have to generate aar file and publish it to Maven and make it accessible by another module and consume it in app.
https://developer.android.com/studio/projects/android-library
As mentioned above android developer document.
The library module with source code is copied to your project, so you can actually edit the library code. If you want to maintain a single version of the library code, then this is probably not what you want and you should instead add the compiled AAR file as described above.
If there anything else we can do, please let us know by jot down in the command section.
It is not supported
It is not recommended to include one library into another because it leads to a serious issues with managing versions and complexity of creating and supporting such solution.
You should stick to native approaches like dependency manager or rearchitect your codebase
[iOS Umbrella framework]

Categories

Resources