Commit 00c8a581 authored by Amit Davidi's avatar Amit Davidi

Extensibility refactor step 1

parent d6e68f5c
package com.wix.reactnativenotifications.core;
import android.support.annotation.Nullable;
public class InitialNotification {
private static PushNotificationProps sNotification;
public static void set(PushNotificationProps pushNotificationProps) {
sNotification = pushNotificationProps;
}
@Nullable
public static PushNotificationProps get() {
return sNotification;
}
}
package com.wix.reactnativenotifications.core;
public class InitialNotificationStore {
private static PushNotificationProps sInitialNotif;
public static void setInitialNotification(PushNotificationProps pushNotificationProps) {
sInitialNotif = pushNotificationProps;
}
public static PushNotificationProps getInitialNotification() {
return sInitialNotif;
}
}
......@@ -63,7 +63,7 @@ public class PushNotification {
launchOrResumeApp(activity);
notifyOpenedToJS(reactContext);
} else {
InitialNotificationStore.setInitialNotification(mNotificationProps);
InitialNotification.set(mNotificationProps);
launchOrResumeApp(activity);
}
}
......
package com.wix.reactnativenotifications.core;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import com.facebook.react.bridge.Arguments;
......@@ -9,7 +7,8 @@ import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.wix.reactnativenotifications.gcm.GcmInstanceIdRefreshHandlerService;
import com.wix.reactnativenotifications.gcm.GcmToken;
import com.wix.reactnativenotifications.gcm.IGcmToken;
import static com.wix.reactnativenotifications.Defs.LOGTAG;
......@@ -26,10 +25,9 @@ public class RNNotificationsModule extends ReactContextBaseJavaModule {
@Override
public void initialize() {
Log.d(LOGTAG, "native module init");
final Context appContext = getReactApplicationContext().getApplicationContext();
final Intent tokenFetchIntent = new Intent(appContext, GcmInstanceIdRefreshHandlerService.class);
appContext.startService(tokenFetchIntent);
Log.d(LOGTAG, "Native module init");
IGcmToken gcmToken = GcmToken.get(getReactApplicationContext().getApplicationContext());
gcmToken.onAppReady();
}
@ReactMethod
......@@ -37,7 +35,7 @@ public class RNNotificationsModule extends ReactContextBaseJavaModule {
Object result = null;
try {
final PushNotificationProps notification = InitialNotificationStore.getInitialNotification();
final PushNotificationProps notification = InitialNotification.get();
if (notification == null) {
return;
}
......
......@@ -2,20 +2,6 @@ package com.wix.reactnativenotifications.gcm;
import android.app.IntentService;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
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 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 GcmInstanceIdRefreshHandlerService extends IntentService {
......@@ -23,57 +9,11 @@ public class GcmInstanceIdRefreshHandlerService extends IntentService {
super(GcmInstanceIdRefreshHandlerService.class.getSimpleName());
}
public GcmInstanceIdRefreshHandlerService(String name) {
super(name);
}
@Override
protected void onHandleIntent(Intent intent) {
final InstanceID instanceId = InstanceID.getInstance(getApplicationContext());
Log.d(LOGTAG, "GCM is refreshing token... instanceId=" + instanceId.getId());
// TODO why is this needed?
GoogleCloudMessaging.getInstance(getApplicationContext()).close();
final String registrationToken;
try {
registrationToken = instanceId.getToken(getSenderId(), GoogleCloudMessaging.INSTANCE_ID_SCOPE);
Log.i(LOGTAG, "GCM has a new token: instanceId=" + instanceId.getId() + ", token=" + registrationToken);
} catch (Exception e) {
Log.e(LOGTAG, "FATAL: Failed to fetch a fresh new token, instanceId=" + instanceId.getId(), e);
return;
}
notifyTokenEvent(registrationToken);
}
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 = getPackageManager().getApplicationInfo(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;
}
}
protected void notifyTokenEvent(String registrationToken) {
final ReactInstanceManager instanceManager = ((ReactApplication) getApplication()).getReactNativeHost().getReactInstanceManager();
final ReactContext reactContext = instanceManager.getCurrentReactContext();
// Note: Cannot assume react-context exists cause this is an async dispatched service.
if (reactContext != null && reactContext.hasActiveCatalystInstance()) {
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(TOKEN_RECEIVED_EVENT_NAME, registrationToken);
IGcmToken gcmToken = GcmToken.get(this);
if (gcmToken != null) {
gcmToken.onNewTokenReady();
}
}
}
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 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 {
final protected Context mAppContext;
protected static String sToken;
public GcmToken(Context appContext) {
if (!(appContext instanceof ReactApplication)) {
throw new IllegalStateException("Application instance isn't a react-application");
}
mAppContext = appContext;
}
public static IGcmToken get(Context context) {
Context appContext = context.getApplicationContext();
if (appContext instanceof INotificationsGcmApplication) {
return ((INotificationsGcmApplication) appContext).getGcmToken(context);
}
return new GcmToken(appContext);
}
@Override
public void onNewTokenReady() {
synchronized (mAppContext) {
refreshToken();
}
}
@Override
public void onManualRefresh() {
synchronized (mAppContext) {
if (sToken == null) {
Log.i(LOGTAG, "Manual token refresh => asking for new token");
refreshToken();
} else {
Log.i(LOGTAG, "Manual token refresh => publishing existing token ("+sToken+")");
sendTokenToJS();
}
}
}
@Override
public void onAppReady() {
synchronized (mAppContext) {
if (sToken == null) {
Log.i(LOGTAG, "App initialized => asking for new token");
refreshToken();
} else {
// Except for first run, this should be the case.
Log.i(LOGTAG, "App initialized => publishing existing token ("+sToken+")");
sendTokenToJS();
}
}
}
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;
}
}
protected void sendTokenToJS() {
final ReactInstanceManager instanceManager = ((ReactApplication) mAppContext).getReactNativeHost().getReactInstanceManager();
final ReactContext reactContext = instanceManager.getCurrentReactContext();
// Note: Cannot assume react-context exists cause this is an async dispatched service.
if (reactContext != null && reactContext.hasActiveCatalystInstance()) {
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(TOKEN_RECEIVED_EVENT_NAME, sToken);
}
}
}
package com.wix.reactnativenotifications.gcm;
public interface IGcmToken {
/**
* Handle an event where we've been notified of a that a fresh token is now available from Google.
*/
void onNewTokenReady();
/**
* Handle an event where application is ready; typically used for sending token to JS.
*/
void onAppReady();
/**
* Handle a request to actively refresh the token on demand.
* This is in essence a workaround so as to allow apps to handle end-cases of token refreshing. It
* shouldn't be used by standard apps, as the token management is self sufficient.
*/
void onManualRefresh();
}
package com.wix.reactnativenotifications.gcm;
import android.content.Context;
public interface INotificationsGcmApplication {
IGcmToken getGcmToken(Context context);
}
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