Skip to content

Move fcm to github #2971

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 20 commits into from
Sep 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions firebase-messaging/api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,19 @@
package com.google.firebase.messaging {

public class FirebaseMessaging {
method @Deprecated public boolean deliveryMetricsExportToBigQueryEnabled();
method @NonNull public com.google.android.gms.tasks.Task<java.lang.Void> deleteToken();
method @NonNull public boolean deliveryMetricsExportToBigQueryEnabled();
method @NonNull public static com.google.firebase.messaging.FirebaseMessaging getInstance();
method @NonNull public com.google.android.gms.tasks.Task<java.lang.String> getToken();
method public boolean isAutoInitEnabled();
method public boolean isDeliveryMetricsExportToBigQueryEnabled();
method public boolean isNotificationDelegationEnabled();
method public void send(@NonNull com.google.firebase.messaging.RemoteMessage);
method public void setAutoInitEnabled(boolean);
method public void setDeliveryMetricsExportToBigQuery(boolean);
method public com.google.android.gms.tasks.Task<java.lang.Void> setNotificationDelegationEnabled(boolean);
method @NonNull public com.google.android.gms.tasks.Task<java.lang.Void> subscribeToTopic(@NonNull String);
method @NonNull public com.google.android.gms.tasks.Task<java.lang.Void> unsubscribeFromTopic(@NonNull String);
field public static final String INSTANCE_ID_SCOPE = "FCM";
field @Deprecated public static final String INSTANCE_ID_SCOPE = "FCM";
}

public class FirebaseMessagingService extends android.app.Service {
Expand Down
9 changes: 9 additions & 0 deletions firebase-messaging/code_gen_cfg.textproto
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# code_gen_cfg.textproto
# proto-file: google3/third_party/firebase/android/encoders/protoc_gen/proto/config.proto
# proto-message: CodeGenConfig

# all types will be vendored in this package
vendor_package: "com.google.firebase.messaging"

# marks a type as a "root" message
include: "reporting.MessagingClientEventExtension"
64 changes: 51 additions & 13 deletions firebase-messaging/firebase-messaging.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,40 @@

plugins {
id 'firebase-library'
id 'com.google.protobuf'
}

configurations.create("protobuild")
dependencies {
protobuild project(path: ":encoders:protoc-gen-firebase-encoders", configuration: "shadow")
}

protobuf {
protoc {
artifact = "com.google.protobuf:protoc:$protocVersion"
}
plugins {
firebaseEncoders {
path = configurations.protobuild.asPath
}
}
generateProtoTasks {
all().each { task ->
task.dependsOn configurations.protobuild
task.inputs.file 'code_gen_cfg.textproto'
task.plugins {
firebaseEncoders {
option file('code_gen_cfg.textproto').path
}
}
task.builtins {
remove java
}
}
}
}


firebaseLibrary {
testLab.enabled = false
}
Expand All @@ -25,6 +57,7 @@ android {
timeOutInMs 60 * 1000
}


lintOptions {
abortOnError false
}
Expand Down Expand Up @@ -55,18 +88,18 @@ dependencies {
implementation project(':transport:transport-backend-cct')
implementation project(':encoders:firebase-encoders')
implementation project(':encoders:firebase-encoders-json')
implementation project(":encoders:firebase-encoders-proto")
implementation project(":firebase-installations")
annotationProcessor project(":encoders:firebase-encoders-processor")

implementation 'androidx.annotation:annotation:1.1.0'
implementation "com.google.android.gms:play-services-tasks:17.0.2"
implementation "com.google.android.gms:play-services-basement:17.2.1"
implementation 'com.google.android.gms:play-services-base:17.2.1'
implementation 'com.google.firebase:firebase-measurement-connector:18.0.0'
implementation "com.google.firebase:firebase-iid-interop:17.0.0"
implementation ("com.google.firebase:firebase-iid:20.2.3") {
exclude group: "com.google.firebase", module: "firebase-common"
exclude group: "com.google.firebase", module: "firebase-components"
exclude group: "com.google.firebase", module: "firebase-installations-interop"
}
implementation 'androidx.annotation:annotation:1.2.0'
implementation "com.google.android.gms:play-services-tasks:17.2.1"
implementation "com.google.android.gms:play-services-basement:17.6.0"
implementation 'com.google.android.gms:play-services-base:17.6.0'
implementation 'com.google.android.gms:play-services-stats:17.0.1'
implementation 'com.google.firebase:firebase-measurement-connector:19.0.0'
implementation "com.google.firebase:firebase-iid-interop:17.1.0"
implementation 'com.google.android.gms:play-services-cloud-messaging:17.0.0'
implementation ("com.google.api-client:google-api-client:1.30.9") {
exclude group: "org.apache.httpcomponents", module: "httpclient"
}
Expand All @@ -76,13 +109,20 @@ dependencies {
javadocClasspath 'com.google.auto.value:auto-value-annotations:1.6.6'

testImplementation 'androidx.test:core:1.2.0'
testImplementation 'com.google.android.gms:play-services-cloud-messaging:17.0.0'
testImplementation 'androidx.test:rules:1.2.0'
testImplementation 'androidx.test:runner:1.2.0'
testImplementation "org.robolectric:robolectric:$robolectricVersion"
testImplementation 'junit:junit:4.13-beta-2'
testImplementation 'org.mockito:mockito-core:2.25.0'
testImplementation "com.google.truth:truth:$googleTruthVersion"
testImplementation 'com.google.android.gms:play-services-vision:19.0.0'
testImplementation ("com.google.firebase:firebase-iid:21.1.0") {
exclude group: "com.google.firebase", module: "firebase-common"
exclude group: "com.google.firebase", module: "firebase-components"
exclude group: "com.google.firebase", module: "firebase-installations-interop"
exclude group: "com.google.firebase", module: "firebase-installations"
}

testImplementation 'com.android.support.test:runner:1.0.2'
testImplementation 'com.fasterxml.jackson.core:jackson-databind:2.9.8'
Expand All @@ -91,6 +131,4 @@ dependencies {
testImplementation 'androidx.test:rules:1.2.0'
testImplementation 'androidx.test.ext:truth:1.2.0'
testImplementation 'androidx.test.services:test-services:1.2.0'


}
14 changes: 13 additions & 1 deletion firebase-messaging/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,21 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.firebase.messaging">
<!--<uses-sdk android:minSdkVersion="16"/>-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- Required by older versions of Google Play services to create IID tokens -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<application>

<receiver
android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</receiver>

<!-- FirebaseMessagingService performs security checks at runtime,
but set to not exported to explicitly avoid allowing another app to call it. -->
<service
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.firebase.iid;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.WorkerThread;
import com.google.android.gms.cloudmessaging.CloudMessage;
import com.google.android.gms.cloudmessaging.CloudMessagingReceiver;
import com.google.android.gms.cloudmessaging.CloudMessagingReceiver.IntentActionKeys;
import com.google.android.gms.tasks.Tasks;
import com.google.firebase.messaging.FcmBroadcastProcessor;
import com.google.firebase.messaging.MessagingAnalytics;
import com.google.firebase.messaging.ServiceStarter;
import java.util.concurrent.ExecutionException;

/**
* Implementation of {@code CloudMessagingReceiver} that passes Intents to the {@code
* FirebaseMessagingService}.
*
* @hide
*/
public final class FirebaseInstanceIdReceiver extends CloudMessagingReceiver {

private static final String TAG = "FirebaseMessaging";

private static Intent createServiceIntent(
@NonNull Context context, @NonNull String action, @NonNull Bundle data) {
return new Intent(action).putExtras(data);
}

/** @hide */
@Override
@WorkerThread
protected int onMessageReceive(@NonNull Context context, @NonNull CloudMessage message) {
try {
return Tasks.await(new FcmBroadcastProcessor(context).process(message.getIntent()));
} catch (ExecutionException | InterruptedException e) {
Log.e(TAG, "Failed to send message to service.", e);
return ServiceStarter.ERROR_UNKNOWN;
}
}

/** @hide */
@Override
@WorkerThread
protected void onNotificationDismissed(@NonNull Context context, @NonNull Bundle data) {
// Reconstruct the service intent from the data.
Intent notificationDismissedIntent =
createServiceIntent(context, IntentActionKeys.NOTIFICATION_DISMISS, data);
if (MessagingAnalytics.shouldUploadScionMetrics(notificationDismissedIntent)) {
MessagingAnalytics.logNotificationDismiss(notificationDismissedIntent);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,11 @@
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.core.app.NotificationCompat;
import androidx.core.content.ContextCompat;
import com.google.firebase.messaging.Constants.IntentActionKeys;
import com.google.firebase.messaging.Constants.IntentKeys;
import com.google.android.gms.cloudmessaging.CloudMessagingReceiver.IntentActionKeys;
import com.google.android.gms.cloudmessaging.CloudMessagingReceiver.IntentKeys;
import com.google.firebase.messaging.Constants.MessageNotificationKeys;
import java.util.concurrent.atomic.AtomicInteger;

Expand All @@ -66,6 +67,16 @@ public final class CommonNotificationBuilder {
public static final String FCM_FALLBACK_NOTIFICATION_CHANNEL_LABEL =
"fcm_fallback_notification_channel_label";

// FM's fallback channel name when neither channel name is explicitly provided nor FM's string
// resource file exists (possibly stripped by Progurad). Note this name is set purposefully
// different from FM's default resource channel name "Miscellaneous" for debugability.
private static final String FCM_FALLBACK_NOTIFICATION_CHANNEL_NAME_NO_RESOURCE = "Misc";
private static final String ACTION_MESSAGING_EVENT = "com.google.firebase.MESSAGING_EVENT";

// Getting illegal resouce id from context will throw NotFoundException.
// See: https://developer.android.com/reference/android/content/res/Resources#ID_NULL
private static final int ILLEGAL_RESOURCE_ID = 0;

/**
* Request code used by display notification pending intents.
*
Expand Down Expand Up @@ -369,16 +380,16 @@ private static PendingIntent createContentIntent(
// and google.n.).
intent.putExtras(params.paramsWithReservedKeysRemoved());

PendingIntent contentIntent =
PendingIntent.getActivity(
context, generatePendingIntentRequestCode(), intent, PendingIntent.FLAG_ONE_SHOT);

// We need to check metric options against the messageData bundle because we stripped the metric
// options from the clientVisibleData version
if (shouldUploadMetrics(params)) {
contentIntent = wrapContentIntent(context, params, contentIntent);
// store the analytics data in a sub-bundle
intent.putExtra(MessageNotificationKeys.ANALYTICS_DATA, params.paramsForAnalyticsIntent());
}
return contentIntent;

return PendingIntent.getActivity(
context,
generatePendingIntentRequestCode(),
intent,
getPendingIntentFlags(PendingIntent.FLAG_ONE_SHOT));
}

private static Intent createTargetIntent(
Expand Down Expand Up @@ -422,7 +433,8 @@ private static Bundle getManifestMetadata(PackageManager pm, String packageName)
}

@TargetApi(VERSION_CODES.O)
private static String getOrCreateChannel(
@VisibleForTesting
public static String getOrCreateChannel(
Context context, String msgChannel, Bundle manifestMetadata) {
if (Build.VERSION.SDK_INT < VERSION_CODES.O) {
return null;
Expand Down Expand Up @@ -483,12 +495,24 @@ private static String getOrCreateChannel(
.getIdentifier(
FCM_FALLBACK_NOTIFICATION_CHANNEL_LABEL, "string", context.getPackageName());

String defaultChannelName;
if (channelLabelResourceId == ILLEGAL_RESOURCE_ID) {
Log.e(
TAG,
"String resource \"fcm_fallback_notification_channel_label\" is not found. Using"
+ " default string channel name.");

defaultChannelName = FCM_FALLBACK_NOTIFICATION_CHANNEL_NAME_NO_RESOURCE;
} else {
defaultChannelName = context.getString(channelLabelResourceId);
}

notificationManager.createNotificationChannel(
new NotificationChannel(
// channel id
FCM_FALLBACK_NOTIFICATION_CHANNEL,
// user visible name of the channel
context.getString(channelLabelResourceId),
defaultChannelName,
// shows everywhere, makes noise, but does not visually intrude.
NotificationManager.IMPORTANCE_DEFAULT));
}
Expand All @@ -505,16 +529,15 @@ private static int generatePendingIntentRequestCode() {
return requestCodeProvider.incrementAndGet();
}

private static PendingIntent wrapContentIntent(
Context context, NotificationParams params, PendingIntent pi) {
// Need to send analytics, so wrap the activity intent in a PendingIntent that starts the
// FirebaseMessagingService. The service will launch the activity and send the analytics.
Intent openIntent =
new Intent(IntentActionKeys.NOTIFICATION_OPEN)
.putExtras(params.paramsForAnalyticsIntent())
.putExtra(IntentKeys.PENDING_INTENT, pi);

return createMessagingPendingIntent(context, openIntent);
/**
* Adds {@link PendingIntent#FLAG_IMMUTABLE} to a PendingIntent's flags since any PendingIntents
* used here don't need to be modified.
*/
private static int getPendingIntentFlags(int baseFlags) {
// Only add on platform levels that support FLAG_IMMUTABLE.
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
? baseFlags | PendingIntent.FLAG_IMMUTABLE
: baseFlags;
}

@Nullable
Expand All @@ -535,11 +558,11 @@ private static PendingIntent createMessagingPendingIntent(Context context, Inten
return PendingIntent.getBroadcast(
context,
generatePendingIntentRequestCode(),
new Intent(IntentActionKeys.MESSAGING_EVENT)
new Intent(ACTION_MESSAGING_EVENT)
.setComponent(
new ComponentName(context, "com.google.firebase.iid.FirebaseInstanceIdReceiver"))
.putExtra(IntentKeys.WRAPPED_INTENT, intent),
PendingIntent.FLAG_ONE_SHOT);
getPendingIntentFlags(PendingIntent.FLAG_ONE_SHOT));
}

/** Check whether we should upload metrics data. */
Expand Down
Loading