add Firebase Cloud Messaging support #702

Merged
akinwale merged 2 commits from fcm into master 2019-10-11 15:18:46 +02:00
8 changed files with 141 additions and 7 deletions

View file

@ -148,7 +148,7 @@ android.react_src = ./app
# (list) Gradle dependencies to add (currently works only with sdl2_gradle # (list) Gradle dependencies to add (currently works only with sdl2_gradle
# bootstrap) # bootstrap)
android.gradle_dependencies = com.android.support:support-v4:28.0.0, com.android.support:support-media-compat:28.0.0, com.android.support:appcompat-v7:28.0.0, com.facebook.react:react-native:0.59.10, com.google.android.gms:play-services-gcm:11.0.4+, com.facebook.fresco:fresco:1.9.0, com.facebook.fresco:animated-gif:1.9.0, com.squareup.picasso:picasso:2.71828, com.google.firebase:firebase-core:16.0.1, com.google.android.gms:play-services-base:16.1.0, com.android.support:exifinterface:28.0.0, com.facebook.fresco:animated-base-support:1.3.0, com.facebook.fresco:animated-gif:1.10.0 android.gradle_dependencies = com.android.support:support-v4:28.0.0, com.android.support:support-media-compat:28.0.0, com.android.support:appcompat-v7:28.0.0, com.facebook.react:react-native:0.59.10, com.google.android.gms:play-services-gcm:11.0.4+, com.facebook.fresco:fresco:1.9.0, com.facebook.fresco:animated-gif:1.9.0, com.squareup.picasso:picasso:2.71828, com.google.firebase:firebase-core:16.0.1, com.google.android.gms:play-services-base:16.1.0, com.android.support:exifinterface:28.0.0, com.facebook.fresco:animated-base-support:1.3.0, com.facebook.fresco:animated-gif:1.10.0, com.google.firebase:firebase-messaging:18.0.0
# (str) python-for-android branch to use, defaults to master # (str) python-for-android branch to use, defaults to master
#p4a.branch = stable #p4a.branch = stable

View file

@ -148,7 +148,7 @@ android.react_src = ./app
# (list) Gradle dependencies to add (currently works only with sdl2_gradle # (list) Gradle dependencies to add (currently works only with sdl2_gradle
# bootstrap) # bootstrap)
android.gradle_dependencies = com.android.support:support-v4:28.0.0, com.android.support:support-media-compat:28.0.0, com.android.support:appcompat-v7:28.0.0, com.facebook.react:react-native:0.59.10, com.google.android.gms:play-services-gcm:11.0.4+, com.facebook.fresco:fresco:1.9.0, com.facebook.fresco:animated-gif:1.9.0, com.squareup.picasso:picasso:2.71828, com.google.firebase:firebase-core:16.0.1, com.google.android.gms:play-services-base:16.1.0, com.android.support:exifinterface:28.0.0, com.facebook.fresco:animated-base-support:1.3.0, com.facebook.fresco:animated-gif:1.10.0 android.gradle_dependencies = com.android.support:support-v4:28.0.0, com.android.support:support-media-compat:28.0.0, com.android.support:appcompat-v7:28.0.0, com.facebook.react:react-native:0.59.10, com.google.android.gms:play-services-gcm:11.0.4+, com.facebook.fresco:fresco:1.9.0, com.facebook.fresco:animated-gif:1.9.0, com.squareup.picasso:picasso:2.71828, com.google.firebase:firebase-core:16.0.1, com.google.android.gms:play-services-base:16.1.0, com.android.support:exifinterface:28.0.0, com.facebook.fresco:animated-base-support:1.3.0, com.facebook.fresco:animated-gif:1.10.0, com.google.firebase:firebase-messaging:18.0.0
# (str) python-for-android branch to use, defaults to master # (str) python-for-android branch to use, defaults to master
#p4a.branch = stable #p4a.branch = stable

View file

@ -148,7 +148,7 @@ android.react_src = ./app
# (list) Gradle dependencies to add (currently works only with sdl2_gradle # (list) Gradle dependencies to add (currently works only with sdl2_gradle
# bootstrap) # bootstrap)
android.gradle_dependencies = com.android.support:support-v4:28.0.0, com.android.support:support-media-compat:28.0.0, com.android.support:appcompat-v7:28.0.0, com.facebook.react:react-native:0.59.10, com.google.android.gms:play-services-gcm:11.0.4+, com.facebook.fresco:fresco:1.9.0, com.facebook.fresco:animated-gif:1.9.0, com.squareup.picasso:picasso:2.71828, com.google.firebase:firebase-core:16.0.1, com.google.android.gms:play-services-base:16.1.0, com.android.support:exifinterface:28.0.0, com.facebook.fresco:animated-base-support:1.3.0, com.facebook.fresco:animated-gif:1.10.0 android.gradle_dependencies = com.android.support:support-v4:28.0.0, com.android.support:support-media-compat:28.0.0, com.android.support:appcompat-v7:28.0.0, com.facebook.react:react-native:0.59.10, com.google.android.gms:play-services-gcm:11.0.4+, com.facebook.fresco:fresco:1.9.0, com.facebook.fresco:animated-gif:1.9.0, com.squareup.picasso:picasso:2.71828, com.google.firebase:firebase-core:16.0.1, com.google.android.gms:play-services-base:16.1.0, com.android.support:exifinterface:28.0.0, com.facebook.fresco:animated-base-support:1.3.0, com.facebook.fresco:animated-gif:1.10.0, com.google.firebase:firebase-messaging:18.0.0
# (str) python-for-android branch to use, defaults to master # (str) python-for-android branch to use, defaults to master
#p4a.branch = stable #p4a.branch = stable

View file

@ -148,7 +148,7 @@ android.react_src = ./app
# (list) Gradle dependencies to add (currently works only with sdl2_gradle # (list) Gradle dependencies to add (currently works only with sdl2_gradle
# bootstrap) # bootstrap)
android.gradle_dependencies = com.android.support:support-v4:28.0.0, com.android.support:support-media-compat:28.0.0, com.android.support:appcompat-v7:28.0.0, com.facebook.react:react-native:0.59.10, com.google.android.gms:play-services-gcm:11.0.4+, com.facebook.fresco:fresco:1.9.0, com.facebook.fresco:animated-gif:1.9.0, com.squareup.picasso:picasso:2.71828, com.google.firebase:firebase-core:16.0.1, com.google.android.gms:play-services-base:16.1.0, com.android.support:exifinterface:28.0.0, com.facebook.fresco:animated-base-support:1.3.0, com.facebook.fresco:animated-gif:1.10.0 android.gradle_dependencies = com.android.support:support-v4:28.0.0, com.android.support:support-media-compat:28.0.0, com.android.support:appcompat-v7:28.0.0, com.facebook.react:react-native:0.59.10, com.google.android.gms:play-services-gcm:11.0.4+, com.facebook.fresco:fresco:1.9.0, com.facebook.fresco:animated-gif:1.9.0, com.squareup.picasso:picasso:2.71828, com.google.firebase:firebase-core:16.0.1, com.google.android.gms:play-services-base:16.1.0, com.android.support:exifinterface:28.0.0, com.facebook.fresco:animated-base-support:1.3.0, com.facebook.fresco:animated-gif:1.10.0, com.google.firebase:firebase-messaging:18.0.0
# (str) python-for-android branch to use, defaults to master # (str) python-for-android branch to use, defaults to master
#p4a.branch = stable #p4a.branch = stable

View file

@ -58,6 +58,16 @@
android:hardwareAccelerated="true" android:hardwareAccelerated="true"
android:usesCleartextTraffic="true"> android:usesCleartextTraffic="true">
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@drawable/ic_lbry" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="@color/lbryGreen" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="@string/default_notification_channel_id"/>
{% for m in args.meta_data %} {% for m in args.meta_data %}
<meta-data android:name="{{ m.split('=', 1)[0] }}" android:value="{{ m.split('=', 1)[-1] }}"/>{% endfor %} <meta-data android:name="{{ m.split('=', 1)[0] }}" android:value="{{ m.split('=', 1)[-1] }}"/>{% endfor %}
<meta-data android:name="wakelock" android:value="{% if args.wakelock %}1{% else %}0{% endif %}"/> <meta-data android:name="wakelock" android:value="{% if args.wakelock %}1{% else %}0{% endif %}"/>
@ -131,6 +141,14 @@
<service android:name="{{ args.package }}.LbrynetTestRunnerService" <service android:name="{{ args.package }}.LbrynetTestRunnerService"
android:process=":service_lbrynet_testrunner" /> android:process=":service_lbrynet_testrunner" />
<service
android:name="{{ args.package }}.LbrynetMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
{% if args.billing_pubkey %} {% if args.billing_pubkey %}
<service android:name="org.kivy.android.billing.BillingReceiver" <service android:name="org.kivy.android.billing.BillingReceiver"
android:process=":pythonbilling" /> android:process=":pythonbilling" />

View file

@ -4,7 +4,8 @@
<string name="private_version">{{ private_version }}</string> <string name="private_version">{{ private_version }}</string>
<string name="presplash_color">{{ args.presplash_color }}</string> <string name="presplash_color">{{ args.presplash_color }}</string>
<string name="urlScheme">{{ url_scheme }}</string> <string name="urlScheme">{{ url_scheme }}</string>
<string name="default_notification_channel_id">io.lbry.browser.LBRY_ENGAGEMENT_CHANNEL</string>
<string name="running">Running</string> <string name="running">Running</string>
<string name="service_status">Service Status</string> <string name="service_status">Service Status</string>
<string name="stopped">Stopped</string> <string name="stopped">Stopped</string>

View file

@ -0,0 +1,93 @@
package io.lbry.browser;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
public class LbrynetMessagingService extends FirebaseMessagingService {
private static final String TAG = "LbrynetMessagingService";
private static final String NOTIFICATION_CHANNEL_ID = "io.lbry.browser.LBRY_ENGAGEMENT_CHANNEL";
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(TAG, "From: " + remoteMessage.getFrom());
// Check if message contains a notification payload.
RemoteMessage.Notification remoteNotification = remoteMessage.getNotification();
if (remoteNotification != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
sendNotification(remoteNotification.getTitle(), remoteNotification.getBody());
}
}
@Override
public void onNewToken(String token) {
Log.d(TAG, "Refreshed token: " + token);
// If you want to send messages to this application instance or
// manage this apps subscriptions on the server side, send the
// Instance ID token to your app server.
sendRegistrationToServer(token);
}
/**
* Persist token to third-party servers.
*
* Modify this method to associate the user's FCM InstanceID token with any server-side account
* maintained by your application.
*
* @param token The new token.
*/
private void sendRegistrationToServer(String token) {
// TODO: Implement this method to send token to your app server.
}
/**
* Create and show a simple notification containing the received FCM message.
*
* @param messageBody FCM message body received.
*/
private void sendNotification(String title, String messageBody) {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
// TODO: Update pending intent based on notification data (eg. open a LBRY URI or the Rewards page?)
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
.setColor(ContextCompat.getColor(this, R.color.lbryGreen))
.setSmallIcon(R.drawable.ic_lbry)
.setContentTitle(title)
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Since android Oreo notification channel is needed.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
NOTIFICATION_CHANNEL_ID, "LBRY Engagement", NotificationManager.IMPORTANCE_DEFAULT);
notificationManager.createNotificationChannel(channel);
}
notificationManager.notify(9898, notificationBuilder.build());
}
}

View file

@ -11,6 +11,10 @@ import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.ReadableMap;
import com.google.firebase.analytics.FirebaseAnalytics; import com.google.firebase.analytics.FirebaseAnalytics;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.InstanceIdResult;
import io.lbry.browser.BuildConfig; import io.lbry.browser.BuildConfig;
import io.lbry.browser.MainActivity; import io.lbry.browser.MainActivity;
@ -37,7 +41,7 @@ public class FirebaseModule extends ReactContextBaseJavaModule {
public String getName() { public String getName() {
return "Firebase"; return "Firebase";
} }
@ReactMethod @ReactMethod
public void setCurrentScreen(String name, final Promise promise) { public void setCurrentScreen(String name, final Promise promise) {
final Activity activity = getCurrentActivity(); final Activity activity = getCurrentActivity();
@ -50,7 +54,7 @@ public class FirebaseModule extends ReactContextBaseJavaModule {
} }
promise.resolve(true); promise.resolve(true);
} }
@ReactMethod @ReactMethod
public void track(String name, ReadableMap payload) { public void track(String name, ReadableMap payload) {
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
@ -86,4 +90,22 @@ public class FirebaseModule extends ReactContextBaseJavaModule {
Toast.LENGTH_LONG).show(); Toast.LENGTH_LONG).show();
} }
} }
@ReactMethod
public void getMessagingToken(final Promise promise) {
FirebaseInstanceId.getInstance().getInstanceId()
.addOnCompleteListener(new OnCompleteListener<InstanceIdResult>() {
@Override
public void onComplete(Task<InstanceIdResult> task) {
if (!task.isSuccessful()) {
promise.reject("getInstanceId failed");
return;
}
// Get new Instance ID token
String token = task.getResult().getToken();
promise.resolve(token);
}
});
}
} }