在库中实现Firebase

31

我希望在一个库中实现Firebase通知系统,该库将用作许多应用程序的SDK。

Firebase现在要求提供应用程序ID,但我正在库内部实现它,因此没有应用程序ID。

我该如何实现我的目标,以便能够向使用我的库的应用程序发送通知?

提前感谢您的帮助。


我认为可以通过将应用程序ID通过库的初始化从主应用程序传递到库中来实现。 - Steven Scott
嘿@Sekai,如果我的答案解决了你的问题,请将其标记为已接受(SO政策)。 - Joaquim Ley
5个回答

21
这些方法都有点取巧或需要付出太多努力,这里有一个简单明了的例子(虽然有点讽刺,因为它是一篇长帖子——但是值得一读)。
可以在库项目中使用FireBase代码,当然,消费应用程序需要注册应用程序并获取应用程序ID/google-services.json文件。
但是您的库不需要也不应该关心这个问题,这是消费应用程序的工作,而不是您的库的工作。
下面是一个简短的示例,演示如何在库项目中使用firebase-messaging模块。 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.

这是您在库项目中需要做的全部内容。不要在此应用gms插件,也不要将google-services类路径添加到库的build.gradle中。
现在,以下是如何设置使用应用程序:
MyClientApp的顶级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()
    }
}

现在我们需要设置消费应用程序模块build.gradle,这很简单。我们只需要应用插件,并依赖于我们创建的包含所有FireBase代码的库模块即可。 MyClientApp的模块级别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'

需要注意的一些事项:

  • 必须在客户端模块的build.gradle文件底部应用google-services插件。
  • 依赖包含Firebase代码的库模块,但要排除它自己的Firebase模块版本,而使用你自己的依赖版本。
  • 应用依赖于自己的Firebase版本。
  • classpath 'com.google.gms:google-services:3.1.1’只需放在客户端应用的顶层build.gradle中。
  • 当然,您需要注册客户端应用并将google-services.json放入客户端应用项目中。
  • 在应用程序的清单文件中定义必要的Firebase Service(或者使用清单合并从库项目中合并它们)。
  • 向客户端应用的清单文件添加google_play_services_version元数据标签。
  • 在声明Firebase依赖时,库可以/应该使用compileOnly

现在,您将能够在您定义了使用Firebase的库中使用Firebase代码。或者,您可以让您的库模块完成所有的Firebase工作!

当然,这通常用于内部库,因为像Firebase这样的框架并不是设计为在库模块中实现的,但有时您需要这样做,因此这是一个简单的非hacky/sane解决方案。它可以在通过maven分发的项目上使用--我的库使用了这个,从来没有引起任何问题。

更新:

在声明库模块的Firebase依赖时,应使用compileOnly。这样做将不会将依赖项添加到构建输出中。但是您仍然可以在库中使用该依赖项。如果使用方希望使用Firebase,则需要手动依赖(使用implementation)。这将有助于减少应用程序中不必要的依赖项/膨胀,并且是声明此类依赖项的“正确”方式。注意:在使用模块中的代码之前,您可能需要执行运行时检查以确保库可用。


感谢您提供的解决方案。 一些注释。我遇到了classpath 'com.google.gms:google-services:4.0.0'的问题。我得到了Could not find google-services.json while looking in [src/nullnull/debug, src/debug/nullnull, src/nullnull, src/debug, src/nullnullDebug] registerResGeneratingTask is deprecated, use registerGeneratedResFolders(FileCollection)的错误提示。 我不得不回滚到版本3.2.1。然后它编译成功了。 - sasha_trn

16

是的,你实际上可以这样做,在你的库的 build.gradle 文件中,在 defaultConfig 字段中添加下面的内容。

buildConfigField("String", "FIREBASE_APP_KEY", "\"${firebaseAppKey}\"")

然后在你的项目的gradle.properties文件中添加以下内容:

firebaseAppKey = <yourFirebaseAppSecret>;

对于每个项目/应用程序,您都必须在gradle.properties文件中定义此变量。

您将需要为每个项目创建一个 Firebase 应用,但您的库现在可以使用 Firebase SDK。

当您想要访问此环境变量的值时,请使用 BuildConfig.FIREBASE_APP_KEY (例如实例化 Firebase)。


我希望有一个解决方案,需要最少的开发人员操作。我们会尝试这个方案,如果不行,我们会尝试实现套接字通知。 - Aysennoussi
@Sekai,我认为只需要配置gradle文件就足够了。如果您像这样预设您的库,作为开发人员,我会非常高兴。您的“客户”唯一需要做的就是创建自己的Firebase应用程序(无论如何都要这样做),并使用自己的密钥,这样密钥就不会暴露在任何地方,假设您没有上传您的gradle.properties文件(您不应该这样做)。 - Joaquim Ley

10

我知道这是一个旧问题,并且有一个已接受的答案,但所有的答案都有一个很大的缺点——它们需要你的库的用户除了将你的库添加到他们的应用程序中之外还要做一些工作。如果从Maven存储库下载你的库,有一种方法可以不需要干扰你的库的用户

注意:这种方法是一种 hack,不受 Firebase 支持。当问及 Firebase 支持时,我得到了以下回复:

Firebase SDK 不适用于库项目。 Firebase 上可用的功能是按应用级别集成的,而不是按模块或库的基础上, 因此在库项目上集成这个功能场景是不可能或不被支持的。

尽管如此,我找到了一种方法来实现它,也许有人会发现它有用,所以在这里分享如下:

这是使用实时数据库的示例,但对于所有 Firebase SDK 都应该适用。

在您的项目的主要 build.gradle 文件中添加 mavenCentral 存储库:

allprojects {
    repositories {
        ...
        mavenCentral()
    }
}
在您的库项目的build.gradle中,添加Google Play服务(作为依赖项而非插件):
compile 'com.google.android.gms:play-services-gcm:11.0.4'

添加相关的Firebase SDK(版本与Google Play服务相同):

compile 'com.google.firebase:firebase-core:11.0.4'
compile 'com.google.firebase:firebase-database:11.0.4'

在 Firebase 上将您的 SDK 注册为一个项目,下载其 google-services.json 文件,并用任何文本编辑器打开它。

在您的库的 strings.xml 中添加以下行,并使用来自 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>

就是这样。您可以在库中使用Firebase实时数据库,然后构建并发布到Maven(发布到Maven很重要,否则库的用户将不得不手动添加依赖项)。当从应用程序内部激活时,将使用您的数据库。

请注意,如果您的库的用户将使用Google Play服务或Firebase,则此方法可能会导致异常和意外行为,因此请自行承担风险!


我已经尝试使用最新的库(gcm 16.0.0,firebase-core 16.0.7)来解决这个问题。但是它并没有起作用。出现了“Default FirebaseApp failed to initialize because no default options were found. This usually means that com.google.gms:google-services was not applied to your gradle project.”和“Missing google_app_id. Firebase Analytics disabled.”的错误提示,即使在库和应用程序中都添加了这些字符串。似乎现在没有办法避免在Firebase中注册应用程序了。 - Alix

7

一种选项是让您库的用户创建一个Firebase项目,然后将生成的google-services.json文件传递到他们的应用程序中,然后您的库可以依赖于该文件。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接