Commit 1fb887d9 authored by Yogev Ben David's avatar Yogev Ben David Committed by GitHub

Merge branch 'master' into 1.1.24

parents c0936868 731cc93b
......@@ -20,8 +20,8 @@ android {
dependencies {
// Google's GCM.
compile 'com.google.android.gms:play-services-gcm:15.0.1'
// compile 'com.google.android.gms:play-services-gcm:15.0.1'
compile "com.google.firebase:firebase-messaging:17.3.0"
compile 'com.facebook.react:react-native:+'
testCompile 'junit:junit:4.12'
......
......@@ -21,39 +21,16 @@
-->
<service android:name=".core.ProxyService"/>
<!--
Google's ready-to-use GcmReceiver.
1. Awaits actual GCM messages (e.g. push notifications) and invokes the GCM service with the concrete content.
2. Awaits instance-ID/token refresh requests from the GCM and invokes the Instance-ID listener service.
-->
<receiver
android:name="com.google.android.gms.gcm.GcmReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="${applicationId}" />
</intent-filter>
</receiver>
<!-- Dispatched by the GcmReceiver when messages are received. -->
<service
android:name="com.wix.reactnativenotifications.gcm.GcmMessageHandlerService"
android:exported="false">
android:name=".gcm.FcmInstanceIdListenerService">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
<!-- Dispatched by the GcmReceiver. Starts the designated refresh-handling service. -->
<service
android:name=".gcm.GcmInstanceIdListenerService"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.gms.iid.InstanceID" />
<action android:name="com.google.firebase.MESSAGING_EVENT" />
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
<service
android:name=".gcm.GcmInstanceIdRefreshHandlerService"
android:name=".gcm.FcmInstanceIdRefreshHandlerService"
android:exported="false" />
</application>
......
......@@ -8,6 +8,7 @@ import android.os.Bundle;
import android.support.v4.app.NotificationManagerCompat;
import android.util.Log;
import com.facebook.react.bridge.ActivityEventListener;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
......@@ -23,20 +24,21 @@ import com.wix.reactnativenotifications.core.notification.PushNotification;
import com.wix.reactnativenotifications.core.notification.PushNotificationProps;
import com.wix.reactnativenotifications.core.notificationdrawer.IPushNotificationsDrawer;
import com.wix.reactnativenotifications.core.notificationdrawer.PushNotificationsDrawer;
import com.wix.reactnativenotifications.gcm.GcmInstanceIdRefreshHandlerService;
import com.wix.reactnativenotifications.gcm.FcmInstanceIdRefreshHandlerService;
import com.google.firebase.FirebaseApp;
import static com.wix.reactnativenotifications.Defs.LOGTAG;
public class RNNotificationsModule extends ReactContextBaseJavaModule implements AppLifecycleFacade.AppVisibilityListener, Application.ActivityLifecycleCallbacks {
public class RNNotificationsModule extends ReactContextBaseJavaModule implements ActivityEventListener {
public RNNotificationsModule(Application application, ReactApplicationContext reactContext) {
super(reactContext);
if (AppLifecycleFacadeHolder.get() instanceof ReactAppLifecycleFacade) {
((ReactAppLifecycleFacade) AppLifecycleFacadeHolder.get()).init(reactContext);
}
AppLifecycleFacadeHolder.get().addVisibilityListener(this);
application.registerActivityLifecycleCallbacks(this);
reactContext.addActivityEventListener(this);
}
@Override
......@@ -47,16 +49,32 @@ public class RNNotificationsModule extends ReactContextBaseJavaModule implements
@Override
public void initialize() {
Log.d(LOGTAG, "Native module init");
startGcmIntentService(GcmInstanceIdRefreshHandlerService.EXTRA_IS_APP_INIT);
startGcmIntentService(FcmInstanceIdRefreshHandlerService.EXTRA_IS_APP_INIT);
final IPushNotificationsDrawer notificationsDrawer = PushNotificationsDrawer.get(getReactApplicationContext().getApplicationContext());
notificationsDrawer.onAppInit();
}
@Override
public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
}
@Override
public void onNewIntent(Intent intent) {
Bundle notificationData = intent.getExtras();
if (notificationData != null) {
final IPushNotification notification = PushNotification.get(getReactApplicationContext().getApplicationContext(), notificationData);
if (notification != null) {
notification.onOpened();
}
}
}
@ReactMethod
public void refreshToken() {
Log.d(LOGTAG, "Native method invocation: refreshToken()");
startGcmIntentService(GcmInstanceIdRefreshHandlerService.EXTRA_MANUAL_REFRESH);
startGcmIntentService(FcmInstanceIdRefreshHandlerService.EXTRA_MANUAL_REFRESH);
}
@ReactMethod
......@@ -96,49 +114,9 @@ public class RNNotificationsModule extends ReactContextBaseJavaModule implements
promise.resolve(new Boolean(hasPermission));
}
@Override
public void onAppVisible() {
final IPushNotificationsDrawer notificationsDrawer = PushNotificationsDrawer.get(getReactApplicationContext().getApplicationContext());
notificationsDrawer.onAppVisible();
}
@Override
public void onAppNotVisible() {
}
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
final IPushNotificationsDrawer notificationsDrawer = PushNotificationsDrawer.get(getReactApplicationContext().getApplicationContext());
notificationsDrawer.onNewActivity(activity);
}
@Override
public void onActivityStarted(Activity activity) {
}
@Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
}
protected void startGcmIntentService(String extraFlag) {
final Context appContext = getReactApplicationContext().getApplicationContext();
final Intent tokenFetchIntent = new Intent(appContext, GcmInstanceIdRefreshHandlerService.class);
final Intent tokenFetchIntent = new Intent(appContext, FcmInstanceIdRefreshHandlerService.class);
tokenFetchIntent.putExtra(extraFlag, true);
appContext.startService(tokenFetchIntent);
}
......
package com.wix.reactnativenotifications;
import android.app.Activity;
import android.app.Application;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.ActivityEventListener;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import com.google.firebase.FirebaseApp;
import com.wix.reactnativenotifications.core.AppLifecycleFacade;
import com.wix.reactnativenotifications.core.AppLifecycleFacadeHolder;
import com.wix.reactnativenotifications.core.notification.IPushNotification;
import com.wix.reactnativenotifications.core.notification.PushNotification;
import com.wix.reactnativenotifications.core.notificationdrawer.IPushNotificationsDrawer;
import com.wix.reactnativenotifications.core.notificationdrawer.PushNotificationsDrawer;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
public class RNNotificationsPackage implements ReactPackage {
import static com.wix.reactnativenotifications.Defs.LOGTAG;
public class RNNotificationsPackage implements ReactPackage, AppLifecycleFacade.AppVisibilityListener, Application.ActivityLifecycleCallbacks {
private final Application mApplication;
public RNNotificationsPackage(Application application) {
mApplication = application;
FirebaseApp.initializeApp(application.getApplicationContext());
AppLifecycleFacadeHolder.get().addVisibilityListener(this);
application.registerActivityLifecycleCallbacks(this);
}
@Override
......@@ -28,4 +47,55 @@ public class RNNotificationsPackage implements ReactPackage {
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
@Override
public void onAppVisible() {
final IPushNotificationsDrawer notificationsDrawer = PushNotificationsDrawer.get(mApplication.getApplicationContext());
notificationsDrawer.onAppVisible();
}
@Override
public void onAppNotVisible() {
}
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
final IPushNotificationsDrawer notificationsDrawer = PushNotificationsDrawer.get(mApplication.getApplicationContext());
notificationsDrawer.onNewActivity(activity);
Intent intent = activity.getIntent();
if (intent != null) {
Bundle notificationData = intent.getExtras();
if (notificationData != null) {
final IPushNotification pushNotification = PushNotification.get(mApplication.getApplicationContext(), notificationData);
if (pushNotification != null) {
pushNotification.onOpened();
}
}
}
}
@Override
public void onActivityStarted(Activity activity) {
}
@Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
}
}
......@@ -43,6 +43,10 @@ public class PushNotification implements IPushNotification {
};
public static IPushNotification get(Context context, Bundle bundle) {
if (verifyNotificationBundle(bundle) == false) {
return null;
}
Context appContext = context.getApplicationContext();
if (appContext instanceof INotificationsApplication) {
return ((INotificationsApplication) appContext).getPushNotification(context, bundle, AppLifecycleFacadeHolder.get(), new AppLaunchHelper());
......@@ -58,6 +62,14 @@ public class PushNotification implements IPushNotification {
mNotificationProps = createProps(bundle);
}
private static boolean verifyNotificationBundle(Bundle bundle) {
if (bundle.getString("google.message_id") != null) {
return true;
}
return false;
}
@Override
public void onReceived() throws InvalidNotificationException {
postNotification(null);
......@@ -92,7 +104,6 @@ public class PushNotification implements IPushNotification {
protected void digestNotification() {
if (!mAppLifecycleFacade.isReactInitialized()) {
setAsInitialNotification();
launchOrResumeApp();
return;
}
......@@ -122,10 +133,6 @@ public class PushNotification implements IPushNotification {
protected void dispatchUponVisibility() {
mAppLifecycleFacade.addVisibilityListener(getIntermediateAppVisibilityListener());
// Make the app visible so that we'll dispatch the notification opening when visibility changes to 'true' (see
// above listener registration).
launchOrResumeApp();
}
protected AppVisibilityListener getIntermediateAppVisibilityListener() {
......@@ -197,9 +204,4 @@ public class PushNotification implements IPushNotification {
private void notifyOpenedToJS() {
mJsIOHelper.sendEventToJS(NOTIFICATION_OPENED_EVENT_NAME, mNotificationProps.asBundle(), mAppLifecycleFacade.getRunningReactContext());
}
protected void launchOrResumeApp() {
final Intent intent = mAppLaunchHelper.getLaunchIntent(mContext);
mContext.startActivity(intent);
}
}
......@@ -3,16 +3,25 @@ package com.wix.reactnativenotifications.gcm;
import android.os.Bundle;
import android.util.Log;
import com.google.android.gms.gcm.GcmListenerService;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
import com.wix.reactnativenotifications.core.notification.IPushNotification;
import com.wix.reactnativenotifications.core.notification.PushNotification;
import java.util.Map;
import static com.wix.reactnativenotifications.Defs.LOGTAG;
public class GcmMessageHandlerService extends GcmListenerService {
/**
* Instance-ID + token refreshing handling service. Contacts the GCM to fetch the updated token.
*
* @author amitd
*/
public class FcmInstanceIdListenerService extends FirebaseMessagingService {
@Override
public void onMessageReceived(String s, Bundle bundle) {
public void onMessageReceived(RemoteMessage message){
Bundle bundle = message.toIntent().getExtras();
Log.d(LOGTAG, "New message from GCM: " + bundle);
try {
......
......@@ -3,18 +3,18 @@ package com.wix.reactnativenotifications.gcm;
import android.app.IntentService;
import android.content.Intent;
public class GcmInstanceIdRefreshHandlerService extends IntentService {
public class FcmInstanceIdRefreshHandlerService extends IntentService {
public static String EXTRA_IS_APP_INIT = "isAppInit";
public static String EXTRA_MANUAL_REFRESH = "doManualRefresh";
public GcmInstanceIdRefreshHandlerService() {
super(GcmInstanceIdRefreshHandlerService.class.getSimpleName());
public FcmInstanceIdRefreshHandlerService() {
super(FcmInstanceIdRefreshHandlerService.class.getSimpleName());
}
@Override
protected void onHandleIntent(Intent intent) {
IGcmToken gcmToken = GcmToken.get(this);
IFcmToken gcmToken = FcmToken.get(this);
if (gcmToken == null) {
return;
}
......
package com.wix.reactnativenotifications.gcm;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.support.annotation.NonNull;
import android.util.Log;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.google.android.gms.gcm.GoogleCloudMessaging;
import com.google.android.gms.iid.InstanceID;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.InstanceIdResult;
import static com.wix.reactnativenotifications.Defs.GCM_SENDER_ID_ATTR_NAME;
import static com.wix.reactnativenotifications.Defs.LOGTAG;
import static com.wix.reactnativenotifications.Defs.TOKEN_RECEIVED_EVENT_NAME;
public class GcmToken implements IGcmToken {
public class FcmToken implements IFcmToken {
final protected Context mAppContext;
protected static String sToken;
protected GcmToken(Context appContext) {
protected FcmToken(Context appContext) {
if (!(appContext instanceof ReactApplication)) {
throw new IllegalStateException("Application instance isn't a react-application");
}
mAppContext = appContext;
}
public static IGcmToken get(Context context) {
public static IFcmToken get(Context context) {
Context appContext = context.getApplicationContext();
if (appContext instanceof INotificationsGcmApplication) {
return ((INotificationsGcmApplication) appContext).getGcmToken(context);
return ((INotificationsGcmApplication) appContext).getFcmToken(context);
}
return new GcmToken(appContext);
return new FcmToken(appContext);
}
@Override
......@@ -73,51 +70,14 @@ public class GcmToken implements IGcmToken {
}
protected void refreshToken() {
try {
sToken = getNewToken();
} catch (Exception e) {
Log.e(LOGTAG, "Failed to retrieve new token", e);
return;
}
sendTokenToJS();
}
@NonNull
protected String getNewToken() throws Exception {
final InstanceID instanceId = InstanceID.getInstance(mAppContext);
Log.d(LOGTAG, "GCM is refreshing token... instanceId=" + instanceId.getId());
// TODO why is this needed?
GoogleCloudMessaging.getInstance(mAppContext).close();
try {
final String registrationToken = instanceId.getToken(getSenderId(), GoogleCloudMessaging.INSTANCE_ID_SCOPE);
Log.i(LOGTAG, "GCM has a new token: instanceId=" + instanceId.getId() + ", token=" + registrationToken);
return registrationToken;
} catch (Exception e) {
throw new Exception("FATAL: Failed to fetch a fresh new token, instanceId=" + instanceId.getId(), e);
}
}
protected String getSenderId() {
final String senderId = getSenderIdFromManifest();
if (senderId == null) {
throw new IllegalStateException("Sender ID not found in manifest. Did you forget to add it as the value of a '"+GCM_SENDER_ID_ATTR_NAME+"' meta-data field?");
}
return senderId;
}
protected String getSenderIdFromManifest() {
final ApplicationInfo appInfo;
try {
appInfo = mAppContext.getPackageManager().getApplicationInfo(mAppContext.getPackageName(), PackageManager.GET_META_DATA);
return appInfo.metaData.getString(GCM_SENDER_ID_ATTR_NAME);
} catch (PackageManager.NameNotFoundException e) {
// Should REALLY never happen cause we're querying for our own package.
Log.e(LOGTAG, "Failed to resolve sender ID from manifest", e);
return null;
}
FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener( new OnSuccessListener<InstanceIdResult>() {
@Override
public void onSuccess(InstanceIdResult instanceIdResult) {
sToken = instanceIdResult.getToken();
Log.i(LOGTAG, "FCM has a new token" + "=" + sToken);
sendTokenToJS();
}
});
}
protected void sendTokenToJS() {
......
package com.wix.reactnativenotifications.gcm;
import android.content.Intent;
import com.google.android.gms.iid.InstanceIDListenerService;
/**
* Instance-ID + token refreshing handling service. Contacts the GCM to fetch the updated token.
*
* @author amitd
*/
public class GcmInstanceIdListenerService extends InstanceIDListenerService {
@Override
public void onTokenRefresh() {
// Fetch updated Instance ID token and notify our app's server of any changes (if applicable).
// Google recommends running this from an intent service.
Intent intent = new Intent(this, GcmInstanceIdRefreshHandlerService.class);
startService(intent);
}
}
package com.wix.reactnativenotifications.gcm;
public interface IGcmToken {
public interface IFcmToken {
/**
* Handle an event where we've been notified of a that a fresh token is now available from Google.
......
......@@ -3,5 +3,5 @@ package com.wix.reactnativenotifications.gcm;
import android.content.Context;
public interface INotificationsGcmApplication {
IGcmToken getGcmToken(Context context);
IFcmToken getFcmToken(Context context);
}
{
"name": "react-native-notifications",
"version": "1.1.24",
"version": "1.2.52",
"description": "Advanced Push Notifications (Silent, interactive notifications) for iOS & Android",
"author": "Lidan Hifi <lidan.hifi@gmail.com>",
"license": "MIT",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment