├── .gitignore ├── .npmignore ├── LICENSE ├── README.md ├── android ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── oney │ └── gcm │ ├── GcmModule.java │ ├── GcmPackage.java │ ├── GcmRegistrationService.java │ ├── RNGcmInstanceIDListenerService.java │ └── RNGcmListenerService.java ├── index.android.js ├── index.ios.js ├── ios ├── RNGCM.h ├── RNGCM.m └── RNGCM.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── libinlu.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ └── libinlu.xcuserdatad │ └── xcschemes │ ├── RCTPushNotification.xcscheme │ └── xcschememanagement.plist └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Howard Yang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Upgrade NOTE 2 | As google introduced Firebase Cloud Messaging to replace GCM, it is better to start using [fcm API](https://github.com/evollu/react-native-fcm) 3 | 4 | # react-native-gcm-push-notification 5 | 6 | GCM for React Native Android and IOS 7 | 8 | ## Demo 9 | 10 | https://github.com/oney/TestGcm 11 | 12 | ## Installation 13 | 14 | - Run `npm install react-native-gcm-push-notification --save` 15 | - Run rnpm link 16 | - If you need to receive initial notification in Android, change `new GcmPackge()` to `new GcmPackage(getIntent()` in MainActivity.java 17 | 18 | ## Android Configuration 19 | 20 | - In `android/build.gradle` 21 | ```gradle 22 | dependencies { 23 | classpath 'com.android.tools.build:gradle:1.3.1' 24 | classpath 'com.google.gms:google-services:2.1.0-alpha3' // <- Add this line 25 | ``` 26 | 27 | - In `android/app/build.gradle` 28 | ```gradle 29 | apply plugin: "com.android.application" 30 | apply plugin: 'com.google.gms.google-services' // <- Add this line 31 | ... 32 | ``` 33 | 34 | - In `android/app/src/main/AndroidManifest.xml`, add these lines, be sure to change `com.xxx.yyy` to your package 35 | ```xml 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 46 | 47 | 48 | 49 | 50 | 51 | ... 52 | 53 | 55 | 56 | ... 57 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | ... 80 | ``` 81 | 82 | ### IOS Configuration 83 | in AppDelegate.m add 84 | ``` 85 | #import "RNGCM.h" 86 | ``` 87 | 88 | ``` 89 | - (void)application:(UIApplication *)application 90 | didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { 91 | NSDictionary *userInfo = @{@"deviceToken" : deviceToken}; 92 | [[NSNotificationCenter defaultCenter] postNotificationName:GCMRemoteNotificationRegistered 93 | object:self 94 | userInfo:userInfo]; 95 | } 96 | 97 | - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { 98 | NSDictionary *userInfo = @{@"error" :error.localizedDescription}; 99 | [[NSNotificationCenter defaultCenter] postNotificationName:GCMRemoteNotificationRegistered 100 | object:self 101 | userInfo:userInfo]; 102 | } 103 | 104 | - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)notification { 105 | [[NSNotificationCenter defaultCenter] postNotificationName: GCMRemoteNotificationReceived 106 | object:self 107 | userInfo:notification]; 108 | 109 | } 110 | 111 | - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)notification fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))handler { 112 | [[NSNotificationCenter defaultCenter] postNotificationName:GCMRemoteNotificationReceived 113 | object:self 114 | userInfo:notification]; 115 | handler(UIBackgroundFetchResultNoData); 116 | } 117 | ``` 118 | 119 | 120 | ### GCM API KEY 121 | By following [Cloud messaging](https://developers.google.com/cloud-messaging/android/client), you can get `google-services.json` file and place it in `android/app` directory 122 | By following [Cloud messaging](https://developers.google.com/cloud-messaging/ios/client), you can get `googleServices-info.plist` file and place it in `/ios` directory 123 | 124 | ### Usage 125 | 126 | ```javascript 127 | 'use strict'; 128 | 129 | var React = require('react'); // RN 0.25+ 130 | var { 131 | AppRegistry, 132 | View, 133 | DeviceEventEmitter, 134 | } = require('react-native'); 135 | 136 | var GCM = require('react-native-gcm-push-notification'); 137 | 138 | var notification = GCM.popInitialNotification(); 139 | if (notification) { 140 | var info = JSON.parse(notification.info); 141 | Notification.create({ 142 | subject: info.subject, 143 | message: info.message, 144 | }); 145 | GcmAndroid.stopService(); 146 | } else { 147 | 148 | var {Router, Route, Schema, Animations, TabBar} = require('react-native-router-flux'); 149 | var YourApp = React.createClass({ 150 | componentDidMount: function() { 151 | GCM.addEventListener('register', function(data){ 152 | if(!data.error){ 153 | console.log('send gcm token to server', data.registrationToken); 154 | } 155 | }); 156 | GCM.addEventListener('notification', function(notification){ 157 | console.log('receive gcm notification', notification); 158 | var info = JSON.parse(notification.data.info); 159 | if (!GcmAndroid.isInForeground) { 160 | Notification.create({ 161 | subject: info.subject, 162 | message: info.message, 163 | }); 164 | } 165 | }); 166 | 167 | GCM.requestPermissions(); 168 | }, 169 | render: function() { 170 | return ( 171 | ... 172 | ); 173 | } 174 | }); 175 | 176 | AppRegistry.registerComponent('YourApp', () => YourApp); 177 | } 178 | ``` 179 | 180 | * There are two situations. 181 | ##### The app is running on the foreground or background. 182 | `GcmAndroid.launchNotification` is `null`, you can get notification in `GcmAndroid.addEventListener('notification'` listenter. 183 | ##### The app is killed/closed 184 | `GcmAndroid.launchNotification` is your GCM data. You can create notification with resolving the data by using [react-native-system-notification module](https://github.com/Neson/react-native-system-notification). 185 | 186 | * You can get info when clicking notification in `DeviceEventEmitter.addListener('sysNotificationClick'`. See [react-native-system-notification](https://github.com/Neson/react-native-system-notification) to get more informations about how to create notification 187 | 188 | ## Troubleshoot 189 | 190 | - Do not add `multiDexEnabled true` in `android/app/build.gradle` even encounter `com.android.dex.DexException: Multiple dex files...` failure. 191 | - Make sure to install Google Play service in Genymotion simulator before testing. 192 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.1" 6 | 7 | defaultConfig { 8 | minSdkVersion 16 9 | targetSdkVersion 22 10 | versionCode 1 11 | versionName "1.0" 12 | ndk { 13 | abiFilters "armeabi-v7a", "x86" 14 | } 15 | } 16 | } 17 | 18 | dependencies { 19 | compile fileTree(include: ['*.jar'], dir: 'libs') 20 | compile 'com.facebook.react:react-native:0.17.+' 21 | compile 'com.google.android.gms:play-services-gcm:8.+' 22 | } 23 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /android/src/main/java/com/oney/gcm/GcmModule.java: -------------------------------------------------------------------------------- 1 | package com.oney.gcm; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.Intent; 5 | import android.content.IntentFilter; 6 | import android.content.SharedPreferences; 7 | import android.os.Build; 8 | import android.os.Bundle; 9 | 10 | import com.facebook.react.bridge.Arguments; 11 | import com.facebook.react.bridge.LifecycleEventListener; 12 | import com.facebook.react.bridge.ReactApplicationContext; 13 | import com.facebook.react.bridge.ReactContextBaseJavaModule; 14 | import com.facebook.react.bridge.ReactMethod; 15 | import com.facebook.react.bridge.WritableMap; 16 | import com.facebook.react.bridge.ReadableMap; 17 | import com.facebook.react.modules.core.DeviceEventManagerModule; 18 | import com.google.android.gms.gcm.GcmPubSub; 19 | 20 | import java.util.HashMap; 21 | import java.util.Map; 22 | import java.util.Set; 23 | import org.json.*; 24 | 25 | import android.preference.PreferenceManager; 26 | import android.util.Log; 27 | 28 | import android.content.Context; 29 | 30 | import android.graphics.Bitmap; 31 | import android.graphics.BitmapFactory; 32 | import android.content.res.Resources; 33 | import android.app.PendingIntent; 34 | import android.support.v4.app.NotificationCompat; 35 | import android.app.Notification; 36 | import android.app.NotificationManager; 37 | import android.media.RingtoneManager; 38 | import android.net.Uri; 39 | 40 | public class GcmModule extends ReactContextBaseJavaModule implements LifecycleEventListener { 41 | private final static String TAG = GcmModule.class.getCanonicalName(); 42 | private Intent mIntent; 43 | private boolean mIsInForeground; 44 | private String registrationToken; 45 | 46 | public GcmModule(ReactApplicationContext reactContext, Intent intent) { 47 | super(reactContext); 48 | mIntent = intent; 49 | 50 | Log.d(TAG, "mIntent is null: " + (mIntent == null)); 51 | 52 | if (getReactApplicationContext().hasCurrentActivity()) { 53 | SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(reactContext); 54 | SharedPreferences.Editor editor = preferences.edit(); 55 | editor.putString("GcmMainActivity", getCurrentActivity().getClass().getSimpleName()); 56 | editor.apply(); 57 | } 58 | 59 | if (mIntent == null) { 60 | listenGcmRegistration(); 61 | listenGcmReceiveNotification(); 62 | getReactApplicationContext().addLifecycleEventListener(this); 63 | } 64 | } 65 | 66 | @Override 67 | public String getName() { 68 | return "GcmModule"; 69 | } 70 | 71 | @Override 72 | public Map getConstants() { 73 | final Map constants = new HashMap<>(); 74 | if (mIntent != null) { 75 | Bundle bundle = mIntent.getBundleExtra("bundle"); 76 | String bundleString = convertJSON(bundle); 77 | Log.d(TAG, "bundleString: " + bundleString); 78 | constants.put("initialNotification", bundleString); 79 | } 80 | return constants; 81 | } 82 | 83 | private void sendEvent(String eventName, Object params) { 84 | getReactApplicationContext() 85 | .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) 86 | .emit(eventName, params); 87 | } 88 | 89 | private void listenGcmRegistration() { 90 | IntentFilter intentFilter = new IntentFilter("RNGcmRegistrationServiceResult"); 91 | 92 | getReactApplicationContext().registerReceiver(new BroadcastReceiver() { 93 | @Override 94 | public void onReceive(Context context, Intent intent) { 95 | Bundle bundle = intent.getExtras(); 96 | boolean success = bundle.getBoolean("success"); 97 | if (success) { 98 | String token = bundle.getString("token"); 99 | WritableMap params = Arguments.createMap(); 100 | params.putString("registrationToken", token); 101 | registrationToken = token; 102 | 103 | sendEvent("GCMRemoteNotificationRegistered", params); 104 | } else { 105 | String message = bundle.getString("message"); 106 | WritableMap params = Arguments.createMap(); 107 | params.putString("error", message); 108 | 109 | sendEvent("GCMRemoteNotificationRegistered", params); 110 | 111 | } 112 | } 113 | }, intentFilter); 114 | } 115 | 116 | private String convertJSON(Bundle bundle) { 117 | JSONObject json = new JSONObject(); 118 | Set keys = bundle.keySet(); 119 | for (String key : keys) { 120 | try { 121 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 122 | json.put(key, JSONObject.wrap(bundle.get(key))); 123 | } else { 124 | json.put(key, bundle.get(key)); 125 | } 126 | } catch(JSONException e) { 127 | return null; 128 | } 129 | } 130 | return json.toString(); 131 | } 132 | 133 | private void listenGcmReceiveNotification() { 134 | IntentFilter intentFilter = new IntentFilter("com.oney.gcm.GCMReceiveNotification"); 135 | 136 | getReactApplicationContext().registerReceiver(new BroadcastReceiver() { 137 | @Override 138 | public void onReceive(Context context, Intent intent) { 139 | Log.d(TAG, "GCMReceiveNotification BroadcastReceiver"); 140 | 141 | if (getReactApplicationContext().hasActiveCatalystInstance()) { 142 | Bundle bundle = intent.getBundleExtra("bundle"); 143 | 144 | String bundleString = convertJSON(bundle); 145 | 146 | WritableMap params = Arguments.createMap(); 147 | params.putString("dataJSON", bundleString); 148 | params.putBoolean("isInForeground", mIsInForeground); 149 | 150 | sendEvent("GCMRemoteNotificationReceived", params); 151 | abortBroadcast(); 152 | } else { 153 | } 154 | } 155 | }, intentFilter); 156 | } 157 | 158 | @ReactMethod 159 | public void requestPermissions() { 160 | getReactApplicationContext().startService(new Intent(getReactApplicationContext(), GcmRegistrationService.class)); 161 | } 162 | @ReactMethod 163 | public void stopService() { 164 | if (mIntent != null) { 165 | new android.os.Handler().postDelayed(new Runnable() { 166 | public void run() { 167 | getReactApplicationContext().stopService(mIntent); 168 | } 169 | }, 1000); 170 | } 171 | } 172 | private Class getMainActivityClass() { 173 | try { 174 | String packageName = getReactApplicationContext().getPackageName(); 175 | 176 | SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getReactApplicationContext()); 177 | String activityString = preferences.getString("GcmMainActivity", null); 178 | if (activityString == null) { 179 | Log.d(TAG, "GcmMainActivity is null"); 180 | return null; 181 | } else { 182 | return Class.forName(packageName + "." + activityString); 183 | } 184 | } catch (ClassNotFoundException e) { 185 | e.printStackTrace(); 186 | return null; 187 | } 188 | } 189 | 190 | @ReactMethod 191 | public void createNotification(ReadableMap infos) { 192 | Resources resources = getReactApplicationContext().getResources(); 193 | 194 | String packageName = getReactApplicationContext().getPackageName(); 195 | 196 | Class intentClass = getMainActivityClass(); 197 | 198 | Log.d(TAG, "packageName: " + packageName); 199 | 200 | if (intentClass == null) { 201 | Log.d(TAG, "intentClass is null"); 202 | return; 203 | } 204 | 205 | int largeIconResourceId = resources.getIdentifier(infos.getString("largeIcon"), "mipmap", packageName); 206 | int smallIconResourceId = android.R.drawable.ic_dialog_info; 207 | if(infos.hasKey("smallIcon")){ 208 | smallIconResourceId = resources.getIdentifier(infos.getString("smallIcon"), "mipmap", packageName); 209 | } 210 | Intent intent = new Intent(getReactApplicationContext(), intentClass); 211 | intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 212 | PendingIntent pendingIntent = PendingIntent.getActivity(getReactApplicationContext(), 0, intent, 213 | PendingIntent.FLAG_ONE_SHOT); 214 | 215 | Bitmap largeIcon = BitmapFactory.decodeResource(resources, largeIconResourceId); 216 | 217 | Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); 218 | 219 | NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(getReactApplicationContext()) 220 | .setLargeIcon(largeIcon) 221 | .setSmallIcon(smallIconResourceId) 222 | .setContentTitle(infos.getString("subject")) 223 | .setContentText(infos.getString("message")) 224 | .setAutoCancel(infos.getBoolean("autoCancel")) 225 | .setSound(defaultSoundUri) 226 | .setTicker(infos.getString("ticker")) 227 | .setCategory(NotificationCompat.CATEGORY_CALL) 228 | .setVisibility(NotificationCompat.VISIBILITY_PRIVATE) 229 | .setPriority(NotificationCompat.PRIORITY_HIGH) 230 | .setContentIntent(pendingIntent); 231 | 232 | NotificationManager notificationManager = 233 | (NotificationManager) getReactApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE); 234 | 235 | Notification notif = notificationBuilder.build(); 236 | notif.defaults |= Notification.DEFAULT_VIBRATE; 237 | notif.defaults |= Notification.DEFAULT_SOUND; 238 | notif.defaults |= Notification.DEFAULT_LIGHTS; 239 | 240 | notificationManager.notify(0, notif); 241 | } 242 | 243 | @ReactMethod 244 | public void subscribeTopic(String topic, com.facebook.react.bridge.Callback callback){ 245 | if(registrationToken != null && mIsInForeground){ 246 | GcmPubSub pubSub = GcmPubSub.getInstance(getReactApplicationContext()); 247 | try{ 248 | pubSub.subscribe(registrationToken, topic, null); 249 | } catch (Exception e){ 250 | callback.invoke(e.getMessage()); 251 | } 252 | callback.invoke(); 253 | } else { 254 | callback.invoke("Not connected to GCM"); 255 | } 256 | } 257 | 258 | @ReactMethod 259 | public void unsubscribeTopic(String topic, com.facebook.react.bridge.Callback callback){ 260 | if(registrationToken != null && mIsInForeground){ 261 | GcmPubSub pubSub = GcmPubSub.getInstance(getReactApplicationContext()); 262 | try{ 263 | pubSub.unsubscribe(registrationToken, topic); 264 | } catch (Exception e){ 265 | callback.invoke(e.getMessage()); 266 | } 267 | callback.invoke(null); 268 | } else { 269 | callback.invoke("Not connected to GCM"); 270 | } 271 | } 272 | 273 | @Override 274 | public void onHostResume() { 275 | mIsInForeground = true; 276 | } 277 | 278 | @Override 279 | public void onHostPause() { 280 | mIsInForeground = false; 281 | } 282 | 283 | @Override 284 | public void onHostDestroy() { 285 | 286 | } 287 | } 288 | -------------------------------------------------------------------------------- /android/src/main/java/com/oney/gcm/GcmPackage.java: -------------------------------------------------------------------------------- 1 | package com.oney.gcm; 2 | 3 | import android.content.Intent; 4 | 5 | import com.facebook.react.ReactPackage; 6 | import com.facebook.react.bridge.JavaScriptModule; 7 | import com.facebook.react.bridge.NativeModule; 8 | import com.facebook.react.bridge.ReactApplicationContext; 9 | import com.facebook.react.uimanager.ViewManager; 10 | import java.util.ArrayList; 11 | import java.util.Arrays; 12 | import java.util.Collections; 13 | import java.util.List; 14 | 15 | public class GcmPackage implements ReactPackage { 16 | private Intent mIntent = null; 17 | 18 | public GcmPackage() { 19 | } 20 | 21 | public GcmPackage(Intent intent) { 22 | mIntent = intent; 23 | } 24 | 25 | @Override 26 | public List createNativeModules( 27 | ReactApplicationContext reactContext) { 28 | List modules = new ArrayList<>(); 29 | 30 | modules.add(new GcmModule(reactContext, mIntent)); 31 | return modules; 32 | } 33 | 34 | @Override 35 | public List> createJSModules() { 36 | return Collections.emptyList(); 37 | } 38 | 39 | @Override 40 | public List createViewManagers(ReactApplicationContext reactContext) { 41 | return Arrays.asList(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /android/src/main/java/com/oney/gcm/GcmRegistrationService.java: -------------------------------------------------------------------------------- 1 | package com.oney.gcm; 2 | 3 | import android.app.IntentService; 4 | import android.content.Intent; 5 | import android.content.SharedPreferences; 6 | import android.content.res.Resources; 7 | import android.os.Bundle; 8 | import android.preference.PreferenceManager; 9 | import android.support.v4.content.LocalBroadcastManager; 10 | import android.util.Log; 11 | 12 | import com.google.android.gms.gcm.GoogleCloudMessaging; 13 | import com.google.android.gms.iid.InstanceID; 14 | 15 | import java.io.IOException; 16 | 17 | public class GcmRegistrationService extends IntentService { 18 | 19 | private static final String TAG = "GcmRegistrationService"; 20 | 21 | public GcmRegistrationService() { 22 | super(TAG); 23 | } 24 | 25 | @Override 26 | protected void onHandleIntent(Intent intent) { 27 | Resources resources = getApplication().getResources(); 28 | String packageName = getApplication().getPackageName(); 29 | 30 | int resourceId = resources.getIdentifier("gcm_defaultSenderId", "string", packageName); 31 | String projectNumber = getString(resourceId); 32 | Log.i(TAG, "projectNumber: " + projectNumber); 33 | 34 | if (projectNumber == null) { 35 | Intent i = new Intent("RNGcmRegistrationServiceResult"); 36 | Bundle bundle = new Bundle(); 37 | bundle.putBoolean("success", false); 38 | bundle.putString("message", "Failed to get gcm_defaultSenderId, please check if android/app/google-services.json exists"); 39 | i.putExtras(bundle); 40 | sendBroadcast(i); 41 | 42 | return; 43 | } 44 | 45 | try { 46 | InstanceID instanceID = InstanceID.getInstance(this); 47 | String token = instanceID.getToken(projectNumber, 48 | GoogleCloudMessaging.INSTANCE_ID_SCOPE, null); 49 | Log.i(TAG, "GCM Registration Token: " + token); 50 | 51 | registeredToken(token); 52 | 53 | } catch (Exception e) { 54 | Log.d(TAG, "Failed to complete token refresh", e); 55 | String message = e.getMessage(); 56 | 57 | Intent i = new Intent("RNGcmRegistrationServiceResult"); 58 | Bundle bundle = new Bundle(); 59 | bundle.putBoolean("success", false); 60 | bundle.putString("message", "Failed to get GCM token, error is " + message); 61 | i.putExtras(bundle); 62 | sendBroadcast(i); 63 | } 64 | } 65 | private void registeredToken(String token) { 66 | Intent i = new Intent("RNGcmRegistrationServiceResult"); 67 | Bundle bundle = new Bundle(); 68 | bundle.putBoolean("success", true); 69 | bundle.putString("token", token); 70 | i.putExtras(bundle); 71 | sendBroadcast(i); 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /android/src/main/java/com/oney/gcm/RNGcmInstanceIDListenerService.java: -------------------------------------------------------------------------------- 1 | package com.oney.gcm; 2 | 3 | import android.content.Intent; 4 | import android.util.Log; 5 | 6 | import com.google.android.gms.iid.InstanceIDListenerService; 7 | 8 | public class RNGcmInstanceIDListenerService extends InstanceIDListenerService{ 9 | 10 | private static final String TAG = "RNGcmInstanceID"; 11 | 12 | /** 13 | * Called if InstanceID token is updated. This may occur if the security of 14 | * the previous token had been compromised. This call is initiated by the 15 | * InstanceID provider. 16 | */ 17 | // [START refresh_token] 18 | @Override 19 | public void onTokenRefresh() { 20 | Log.i(TAG, "refresh token"); 21 | // Fetch updated Instance ID token and notify our app's server of any changes (if applicable). 22 | Intent intent = new Intent(this, GcmRegistrationService.class); 23 | startService(intent); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /android/src/main/java/com/oney/gcm/RNGcmListenerService.java: -------------------------------------------------------------------------------- 1 | package com.oney.gcm; 2 | 3 | import android.app.Notification; 4 | import android.app.NotificationManager; 5 | import android.app.PendingIntent; 6 | import android.content.Context; 7 | import android.content.Intent; 8 | import android.content.pm.PackageManager; 9 | import android.media.RingtoneManager; 10 | import android.net.Uri; 11 | import android.os.Bundle; 12 | import android.support.v4.app.NotificationCompat; 13 | import android.util.Log; 14 | import android.graphics.Bitmap; 15 | import android.graphics.BitmapFactory; 16 | import android.content.res.Resources; 17 | import android.app.ActivityManager; 18 | import android.app.ActivityManager.RunningAppProcessInfo; 19 | import android.app.ActivityManager.RunningServiceInfo; 20 | import java.util.List; 21 | 22 | import com.google.android.gms.gcm.GcmListenerService; 23 | 24 | public class RNGcmListenerService extends GcmListenerService { 25 | 26 | private static final String TAG = "RNGcmListenerService"; 27 | 28 | @Override 29 | public void onMessageReceived(String from, Bundle bundle) { 30 | sendNotification(bundle); 31 | } 32 | 33 | private void sendNotification(Bundle bundle) { 34 | Log.d(TAG, "sendNotification"); 35 | 36 | Intent i = new Intent("com.oney.gcm.GCMReceiveNotification"); 37 | i.putExtra("bundle", bundle); 38 | sendOrderedBroadcast(i, null); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /index.android.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var { 4 | NativeModules, 5 | DeviceEventEmitter, 6 | } = require('react-native'); 7 | 8 | var GcmModule = NativeModules.GcmModule; 9 | 10 | var _notifHandlers = new Map(); 11 | var _initialNotification = GcmModule && GcmModule.initialNotification; 12 | 13 | var DEVICE_NOTIF_EVENT = 'GCMRemoteNotificationReceived'; 14 | var NOTIF_REGISTER_EVENT = 'GCMRemoteNotificationRegistered'; 15 | 16 | class GCMClass { 17 | static addEventListener(type: string, handler: Function) { 18 | var listener; 19 | if (type === 'notification') { 20 | listener = DeviceEventEmitter.addListener( 21 | DEVICE_NOTIF_EVENT, 22 | (notifData) => { 23 | GCMClass.isInForeground = notifData.isInForeground; 24 | var data = JSON.parse(notifData.dataJSON); 25 | handler(new GCMClass(data)); 26 | } 27 | ); 28 | } else if (type === 'register') { 29 | listener = DeviceEventEmitter.addListener( 30 | NOTIF_REGISTER_EVENT, 31 | (registrationInfo) => { 32 | handler(registrationInfo); 33 | } 34 | ); 35 | } 36 | _notifHandlers.set(handler, listener); 37 | } 38 | 39 | static removeEventListener(type: string, handler: Function) { 40 | var listener = _notifHandlers.get(handler); 41 | if (!listener) { 42 | return; 43 | } 44 | listener.remove(); 45 | _notifHandlers.delete(handler); 46 | } 47 | 48 | static requestPermissions() { 49 | GcmModule.requestPermissions(); 50 | } 51 | 52 | static stopService() { 53 | GcmModule.stopService(); 54 | } 55 | static createNotification(infos) { 56 | GcmModule.createNotification(infos); 57 | } 58 | 59 | static popInitialNotification() { 60 | var initialNotification = _initialNotification && 61 | new GCMClass(JSON.parse(_initialNotification)); 62 | _initialNotification = null; 63 | return initialNotification; 64 | } 65 | 66 | static subscribeTopic(topic, callback){ 67 | GcmModule.subscribeTopic(topic, callback) 68 | } 69 | 70 | static unsubscribeTopic(topic, callback){ 71 | GcmModule.unsubscribeTopic(topic, callback) 72 | } 73 | 74 | constructor(data) { 75 | this.data = data; 76 | } 77 | } 78 | 79 | GCMClass.isInForeground = true; 80 | 81 | module.exports = GCMClass; 82 | -------------------------------------------------------------------------------- /index.ios.js: -------------------------------------------------------------------------------- 1 | 2 | 'use strict'; 3 | 4 | var React = require('react-native'); 5 | var { 6 | DeviceEventEmitter, 7 | NativeModules 8 | } = React; 9 | 10 | var RNGCM = NativeModules.RNGCM; 11 | 12 | var _notifHandlers = new Map(); 13 | var _initialNotification = RNGCM && RNGCM.initialNotification; 14 | 15 | var DEVICE_NOTIF_EVENT = 'GCMRemoteNotificationReceived'; 16 | var NOTIF_REGISTER_EVENT = 'GCMRemoteNotificationRegistered'; 17 | 18 | class GCMClass { 19 | static addEventListener(type: string, handler: Function) { 20 | var listener; 21 | if (type === 'notification') { 22 | listener = DeviceEventEmitter.addListener( 23 | DEVICE_NOTIF_EVENT, 24 | (notifData) => { 25 | handler(new GCMClass(notifData)); 26 | } 27 | ); 28 | } else if (type === 'register') { 29 | listener = DeviceEventEmitter.addListener( 30 | NOTIF_REGISTER_EVENT, 31 | (registrationInfo) => { 32 | handler(registrationInfo); 33 | } 34 | ); 35 | } 36 | _notifHandlers.set(handler, listener); 37 | } 38 | 39 | static removeEventListener(type: string, handler: Function) { 40 | var listener = _notifHandlers.get(handler); 41 | if (!listener) { 42 | return; 43 | } 44 | listener.remove(); 45 | _notifHandlers.delete(handler); 46 | } 47 | 48 | static requestPermissions() { 49 | RNGCM.requestPermissions(); 50 | } 51 | 52 | static popInitialNotification() { 53 | var initialNotification = _initialNotification && 54 | new GCMClass(_initialNotification); 55 | _initialNotification = null; 56 | return initialNotification; 57 | } 58 | 59 | static subscribeTopic(topic, callback){ 60 | RNGCM.subscribeTopic(topic, callback) 61 | } 62 | 63 | static unsubscribeTopic(topic, callback){ 64 | RNGCM.unsubscribeTopic(topic, callback) 65 | } 66 | 67 | constructor(data) { 68 | this.data = data; 69 | } 70 | } 71 | 72 | module.exports = GCMClass; 73 | -------------------------------------------------------------------------------- /ios/RNGCM.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | 12 | #import 13 | 14 | #import "RCTBridgeModule.h" 15 | 16 | 17 | extern NSString *const GCMRemoteNotificationReceived; 18 | extern NSString *const GCMRemoteNotificationRegistered; 19 | 20 | @interface RNGCM : NSObject 21 | 22 | @property (nonatomic, assign) bool connectedToGCM; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /ios/RNGCM.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import "RNGCM.h" 11 | 12 | #import "RCTBridge.h" 13 | #import "RCTConvert.h" 14 | #import "RCTEventDispatcher.h" 15 | #import "RCTUtils.h" 16 | 17 | #if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0 18 | 19 | #define UIUserNotificationTypeAlert UIRemoteNotificationTypeAlert 20 | #define UIUserNotificationTypeBadge UIRemoteNotificationTypeBadge 21 | #define UIUserNotificationTypeSound UIRemoteNotificationTypeSound 22 | #define UIUserNotificationTypeNone UIRemoteNotificationTypeNone 23 | #define UIUserNotificationType UIRemoteNotificationType 24 | 25 | #endif 26 | 27 | NSString *const GCMRemoteNotificationReceived = @"GCMRemoteNotificationReceived"; 28 | NSString *const GCMRemoteNotificationRegistered = @"GCMRemoteNotificationRegistered"; 29 | NSString *const GCMTopicSubscribed = @"GCMTopicSubscribed"; 30 | 31 | 32 | @implementation RNGCM 33 | 34 | NSString* registrationToken; 35 | 36 | RCT_EXPORT_MODULE() 37 | 38 | @synthesize bridge = _bridge; 39 | 40 | - (NSDictionary *)constantsToExport 41 | { 42 | NSDictionary *initialNotification = 43 | [_bridge.launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey] copy]; 44 | return @{@"initialNotification": RCTNullIfNil(initialNotification)}; 45 | } 46 | 47 | - (void)dealloc 48 | { 49 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 50 | } 51 | 52 | - (void)setBridge:(RCTBridge *)bridge 53 | { 54 | _bridge = bridge; 55 | 56 | NSError* configureError; 57 | [[GGLContext sharedInstance] configureWithError:&configureError]; 58 | NSAssert(!configureError, @"Error configuring Google services: %@", configureError); 59 | 60 | GCMConfig *gcmConfig = [GCMConfig defaultConfig]; 61 | gcmConfig.receiverDelegate = self; 62 | [[GCMService sharedInstance] startWithConfig:gcmConfig]; 63 | 64 | GGLInstanceIDConfig *instanceIDConfig = [GGLInstanceIDConfig defaultConfig]; 65 | instanceIDConfig.delegate = self; 66 | // Start the GGLInstanceID shared instance with the that config and request a registration 67 | // token to enable reception of notifications 68 | [[GGLInstanceID sharedInstance] startWithConfig:instanceIDConfig]; 69 | 70 | 71 | [[NSNotificationCenter defaultCenter] addObserver:self 72 | selector:@selector(handleRemoteNotificationReceived:) 73 | name:GCMRemoteNotificationReceived 74 | object:nil]; 75 | [[NSNotificationCenter defaultCenter] addObserver:self 76 | selector:@selector(handleRemoteNotificationsRegistered:) 77 | name:GCMRemoteNotificationRegistered 78 | object:nil]; 79 | 80 | [[NSNotificationCenter defaultCenter] addObserver:self 81 | selector:@selector(disconnectGCM) 82 | name:UIApplicationDidEnterBackgroundNotification 83 | object:nil]; 84 | [[NSNotificationCenter defaultCenter] addObserver:self 85 | selector:@selector(connectToGCM) 86 | name:UIApplicationDidBecomeActiveNotification 87 | object:nil]; 88 | } 89 | 90 | - (void)connectToGCM 91 | { 92 | [[GCMService sharedInstance] connectWithHandler:^(NSError *error) { 93 | if (error) { 94 | NSLog(@"Could not connect to GCM: %@", error.localizedDescription); 95 | } else { 96 | self.connectedToGCM = YES; 97 | NSLog(@"Connected to GCM"); 98 | } 99 | }]; 100 | } 101 | 102 | - (void)disconnectGCM 103 | { 104 | [[GCMService sharedInstance] disconnect]; 105 | self.connectedToGCM = NO; 106 | } 107 | 108 | RCT_EXPORT_METHOD(requestPermissions) 109 | { 110 | if (RCTRunningInAppExtension()) { 111 | return; 112 | } 113 | 114 | //UIApplication *app = RCTSharedApplication(); 115 | 116 | if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1) { 117 | // iOS 7.1 or earlier 118 | UIRemoteNotificationType allNotificationTypes = 119 | (UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge); 120 | [[UIApplication sharedApplication] registerForRemoteNotificationTypes:allNotificationTypes]; 121 | } else { 122 | // iOS 8 or later 123 | // [END_EXCLUDE] 124 | UIUserNotificationType allNotificationTypes = 125 | (UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge); 126 | UIUserNotificationSettings *settings = 127 | [UIUserNotificationSettings settingsForTypes:allNotificationTypes categories:nil]; 128 | [[UIApplication sharedApplication] registerUserNotificationSettings:settings]; 129 | [[UIApplication sharedApplication] registerForRemoteNotifications]; 130 | } 131 | 132 | } 133 | 134 | - (void)handleRemoteNotificationReceived:(NSNotification *)notification 135 | { 136 | [[GCMService sharedInstance] appDidReceiveMessage:notification.userInfo]; 137 | [_bridge.eventDispatcher sendDeviceEventWithName:GCMRemoteNotificationReceived 138 | body:notification.userInfo]; 139 | } 140 | 141 | - (void)handleRemoteNotificationsRegistered:(NSNotification *)notification 142 | { 143 | if([notification.userInfo objectForKey:@"deviceToken"] != nil){ 144 | NSData* deviceToken = [notification.userInfo objectForKey:@"deviceToken"]; 145 | __weak typeof(self) weakSelf = self;; 146 | 147 | NSDictionary *registrationOptions = @{kGGLInstanceIDRegisterAPNSOption:deviceToken, 148 | kGGLInstanceIDAPNSServerTypeSandboxOption:@YES}; 149 | 150 | NSString* gcmSenderID = [[[GGLContext sharedInstance] configuration] gcmSenderID]; 151 | 152 | [[GGLInstanceID sharedInstance] tokenWithAuthorizedEntity:gcmSenderID scope:kGGLInstanceIDScopeGCM options:registrationOptions 153 | handler:^(NSString *token, NSError *error){ 154 | if (token != nil) { 155 | NSLog(@"Registration Token: %@", token); 156 | 157 | weakSelf.connectedToGCM = YES; 158 | registrationToken = token; 159 | 160 | NSDictionary *userInfo = @{@"registrationToken":token}; 161 | [_bridge.eventDispatcher sendDeviceEventWithName:GCMRemoteNotificationRegistered 162 | body:userInfo]; 163 | } else { 164 | NSLog(@"Registration to GCM failed with error: %@", error.localizedDescription); 165 | NSDictionary *userInfo = @{@"error":error.localizedDescription}; 166 | [_bridge.eventDispatcher sendDeviceEventWithName:GCMRemoteNotificationRegistered 167 | body:userInfo]; 168 | } 169 | }]; 170 | } else { 171 | [_bridge.eventDispatcher sendDeviceEventWithName:GCMRemoteNotificationRegistered 172 | body:notification.userInfo]; 173 | } 174 | 175 | } 176 | 177 | -(void)onTokenRefresh { 178 | [self requestPermissions]; 179 | } 180 | 181 | 182 | RCT_EXPORT_METHOD(subscribeTopic:(NSString*) topic callback: (RCTResponseSenderBlock)callback) { 183 | // If the app has a registration token and is connected to GCM, proceed to subscribe to the 184 | // topic 185 | if (self.connectedToGCM && registrationToken) { 186 | [[GCMPubSub sharedInstance] subscribeWithToken:registrationToken 187 | topic:topic 188 | options:nil 189 | handler:^(NSError *error) { 190 | if(error == nil || error.code == 3001){ 191 | callback(@[]); 192 | }else{ 193 | callback(@[error.localizedDescription]); 194 | } 195 | }]; 196 | }else{ 197 | callback(@[@"GCM not connected"]); 198 | } 199 | } 200 | 201 | RCT_EXPORT_METHOD(unsubscribeTopic:(NSString*) topic callback: (RCTResponseSenderBlock)callback) { 202 | // If the app has a registration token and is connected to GCM, proceed to subscribe to the 203 | // topic 204 | if (self.connectedToGCM && registrationToken) { 205 | [[GCMPubSub sharedInstance] unsubscribeWithToken:registrationToken 206 | topic:topic 207 | options:nil 208 | handler:^(NSError *error) { 209 | if(error == nil || error.code == 3001){ 210 | callback(@[]); 211 | }else{ 212 | callback(@[error.localizedDescription]); 213 | } 214 | }]; 215 | }else{ 216 | callback(@[@"GCM not connected"]); 217 | } 218 | } 219 | 220 | @end 221 | -------------------------------------------------------------------------------- /ios/RNGCM.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 148699CF1ABD045300480536 /* RNGCM.m in Sources */ = {isa = PBXBuildFile; fileRef = 148699CE1ABD045300480536 /* RNGCM.m */; }; 11 | /* End PBXBuildFile section */ 12 | 13 | /* Begin PBXCopyFilesBuildPhase section */ 14 | 58B511D91A9E6C8500147676 /* CopyFiles */ = { 15 | isa = PBXCopyFilesBuildPhase; 16 | buildActionMask = 2147483647; 17 | dstPath = "include/$(PRODUCT_NAME)"; 18 | dstSubfolderSpec = 16; 19 | files = ( 20 | ); 21 | runOnlyForDeploymentPostprocessing = 0; 22 | }; 23 | /* End PBXCopyFilesBuildPhase section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | 134814201AA4EA6300B7C361 /* libRNGCM.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNGCM.a; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | 148699CD1ABD045300480536 /* RNGCM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNGCM.h; sourceTree = ""; }; 28 | 148699CE1ABD045300480536 /* RNGCM.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNGCM.m; sourceTree = ""; }; 29 | /* End PBXFileReference section */ 30 | 31 | /* Begin PBXFrameworksBuildPhase section */ 32 | 58B511D81A9E6C8500147676 /* Frameworks */ = { 33 | isa = PBXFrameworksBuildPhase; 34 | buildActionMask = 2147483647; 35 | files = ( 36 | ); 37 | runOnlyForDeploymentPostprocessing = 0; 38 | }; 39 | /* End PBXFrameworksBuildPhase section */ 40 | 41 | /* Begin PBXGroup section */ 42 | 134814211AA4EA7D00B7C361 /* Products */ = { 43 | isa = PBXGroup; 44 | children = ( 45 | 134814201AA4EA6300B7C361 /* libRNGCM.a */, 46 | ); 47 | name = Products; 48 | sourceTree = ""; 49 | }; 50 | 58B511D21A9E6C8500147676 = { 51 | isa = PBXGroup; 52 | children = ( 53 | 148699CD1ABD045300480536 /* RNGCM.h */, 54 | 148699CE1ABD045300480536 /* RNGCM.m */, 55 | 134814211AA4EA7D00B7C361 /* Products */, 56 | ); 57 | indentWidth = 2; 58 | sourceTree = ""; 59 | tabWidth = 2; 60 | }; 61 | /* End PBXGroup section */ 62 | 63 | /* Begin PBXNativeTarget section */ 64 | 58B511DA1A9E6C8500147676 /* RNGCM */ = { 65 | isa = PBXNativeTarget; 66 | buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNGCM" */; 67 | buildPhases = ( 68 | 58B511D71A9E6C8500147676 /* Sources */, 69 | 58B511D81A9E6C8500147676 /* Frameworks */, 70 | 58B511D91A9E6C8500147676 /* CopyFiles */, 71 | ); 72 | buildRules = ( 73 | ); 74 | dependencies = ( 75 | ); 76 | name = RNGCM; 77 | productName = RCTDataManager; 78 | productReference = 134814201AA4EA6300B7C361 /* libRNGCM.a */; 79 | productType = "com.apple.product-type.library.static"; 80 | }; 81 | /* End PBXNativeTarget section */ 82 | 83 | /* Begin PBXProject section */ 84 | 58B511D31A9E6C8500147676 /* Project object */ = { 85 | isa = PBXProject; 86 | attributes = { 87 | LastUpgradeCheck = 0610; 88 | ORGANIZATIONNAME = Facebook; 89 | TargetAttributes = { 90 | 58B511DA1A9E6C8500147676 = { 91 | CreatedOnToolsVersion = 6.1.1; 92 | }; 93 | }; 94 | }; 95 | buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNGCM" */; 96 | compatibilityVersion = "Xcode 3.2"; 97 | developmentRegion = English; 98 | hasScannedForEncodings = 0; 99 | knownRegions = ( 100 | en, 101 | ); 102 | mainGroup = 58B511D21A9E6C8500147676; 103 | productRefGroup = 58B511D21A9E6C8500147676; 104 | projectDirPath = ""; 105 | projectRoot = ""; 106 | targets = ( 107 | 58B511DA1A9E6C8500147676 /* RNGCM */, 108 | ); 109 | }; 110 | /* End PBXProject section */ 111 | 112 | /* Begin PBXSourcesBuildPhase section */ 113 | 58B511D71A9E6C8500147676 /* Sources */ = { 114 | isa = PBXSourcesBuildPhase; 115 | buildActionMask = 2147483647; 116 | files = ( 117 | 148699CF1ABD045300480536 /* RNGCM.m in Sources */, 118 | ); 119 | runOnlyForDeploymentPostprocessing = 0; 120 | }; 121 | /* End PBXSourcesBuildPhase section */ 122 | 123 | /* Begin XCBuildConfiguration section */ 124 | 58B511ED1A9E6C8500147676 /* Debug */ = { 125 | isa = XCBuildConfiguration; 126 | buildSettings = { 127 | ALWAYS_SEARCH_USER_PATHS = NO; 128 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 129 | CLANG_CXX_LIBRARY = "libc++"; 130 | CLANG_ENABLE_MODULES = YES; 131 | CLANG_ENABLE_OBJC_ARC = YES; 132 | CLANG_WARN_BOOL_CONVERSION = YES; 133 | CLANG_WARN_CONSTANT_CONVERSION = YES; 134 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 135 | CLANG_WARN_EMPTY_BODY = YES; 136 | CLANG_WARN_ENUM_CONVERSION = YES; 137 | CLANG_WARN_INT_CONVERSION = YES; 138 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 139 | CLANG_WARN_UNREACHABLE_CODE = YES; 140 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 141 | COPY_PHASE_STRIP = NO; 142 | ENABLE_STRICT_OBJC_MSGSEND = YES; 143 | GCC_C_LANGUAGE_STANDARD = gnu99; 144 | GCC_DYNAMIC_NO_PIC = NO; 145 | GCC_OPTIMIZATION_LEVEL = 0; 146 | GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1"; 147 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 148 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 149 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 150 | GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; 151 | GCC_WARN_SHADOW = YES; 152 | GCC_WARN_UNDECLARED_SELECTOR = YES; 153 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 154 | GCC_WARN_UNUSED_FUNCTION = YES; 155 | GCC_WARN_UNUSED_VARIABLE = YES; 156 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 157 | MTL_ENABLE_DEBUG_INFO = YES; 158 | ONLY_ACTIVE_ARCH = YES; 159 | SDKROOT = iphoneos; 160 | WARNING_CFLAGS = ( 161 | "-Wextra", 162 | "-Wall", 163 | ); 164 | }; 165 | name = Debug; 166 | }; 167 | 58B511EE1A9E6C8500147676 /* Release */ = { 168 | isa = XCBuildConfiguration; 169 | buildSettings = { 170 | ALWAYS_SEARCH_USER_PATHS = NO; 171 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 172 | CLANG_CXX_LIBRARY = "libc++"; 173 | CLANG_ENABLE_MODULES = YES; 174 | CLANG_ENABLE_OBJC_ARC = YES; 175 | CLANG_WARN_BOOL_CONVERSION = YES; 176 | CLANG_WARN_CONSTANT_CONVERSION = YES; 177 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 178 | CLANG_WARN_EMPTY_BODY = YES; 179 | CLANG_WARN_ENUM_CONVERSION = YES; 180 | CLANG_WARN_INT_CONVERSION = YES; 181 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 182 | CLANG_WARN_UNREACHABLE_CODE = YES; 183 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 184 | COPY_PHASE_STRIP = YES; 185 | ENABLE_NS_ASSERTIONS = NO; 186 | ENABLE_STRICT_OBJC_MSGSEND = YES; 187 | GCC_C_LANGUAGE_STANDARD = gnu99; 188 | GCC_PREPROCESSOR_DEFINITIONS = ""; 189 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 190 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 191 | GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; 192 | GCC_WARN_SHADOW = YES; 193 | GCC_WARN_UNDECLARED_SELECTOR = YES; 194 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 195 | GCC_WARN_UNUSED_FUNCTION = YES; 196 | GCC_WARN_UNUSED_VARIABLE = YES; 197 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 198 | MTL_ENABLE_DEBUG_INFO = NO; 199 | SDKROOT = iphoneos; 200 | VALIDATE_PRODUCT = YES; 201 | WARNING_CFLAGS = ( 202 | "-Wextra", 203 | "-Wall", 204 | ); 205 | }; 206 | name = Release; 207 | }; 208 | 58B511F01A9E6C8500147676 /* Debug */ = { 209 | isa = XCBuildConfiguration; 210 | buildSettings = { 211 | CLANG_STATIC_ANALYZER_MODE = deep; 212 | GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)"; 213 | HEADER_SEARCH_PATHS = ( 214 | "$(SRCROOT)/../../react-native/React/**", 215 | "$(SRCROOT)/../../../ios/Pods/**", 216 | ); 217 | LIBRARY_SEARCH_PATHS = "$(inherited)"; 218 | OTHER_LDFLAGS = "-ObjC"; 219 | PRODUCT_NAME = RNGCM; 220 | RUN_CLANG_STATIC_ANALYZER = YES; 221 | SKIP_INSTALL = YES; 222 | }; 223 | name = Debug; 224 | }; 225 | 58B511F11A9E6C8500147676 /* Release */ = { 226 | isa = XCBuildConfiguration; 227 | buildSettings = { 228 | CLANG_STATIC_ANALYZER_MODE = deep; 229 | HEADER_SEARCH_PATHS = ( 230 | "$(SRCROOT)/../../react-native/React/**", 231 | "$(SRCROOT)/../../../ios/Pods/**", 232 | ); 233 | LIBRARY_SEARCH_PATHS = "$(inherited)"; 234 | OTHER_LDFLAGS = "-ObjC"; 235 | PRODUCT_NAME = RNGCM; 236 | SKIP_INSTALL = YES; 237 | }; 238 | name = Release; 239 | }; 240 | /* End XCBuildConfiguration section */ 241 | 242 | /* Begin XCConfigurationList section */ 243 | 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNGCM" */ = { 244 | isa = XCConfigurationList; 245 | buildConfigurations = ( 246 | 58B511ED1A9E6C8500147676 /* Debug */, 247 | 58B511EE1A9E6C8500147676 /* Release */, 248 | ); 249 | defaultConfigurationIsVisible = 0; 250 | defaultConfigurationName = Release; 251 | }; 252 | 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNGCM" */ = { 253 | isa = XCConfigurationList; 254 | buildConfigurations = ( 255 | 58B511F01A9E6C8500147676 /* Debug */, 256 | 58B511F11A9E6C8500147676 /* Release */, 257 | ); 258 | defaultConfigurationIsVisible = 0; 259 | defaultConfigurationName = Release; 260 | }; 261 | /* End XCConfigurationList section */ 262 | }; 263 | rootObject = 58B511D31A9E6C8500147676 /* Project object */; 264 | } 265 | -------------------------------------------------------------------------------- /ios/RNGCM.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/RNGCM.xcodeproj/project.xcworkspace/xcuserdata/libinlu.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/evollu/react-native-gcm-push-notification/38aaa8ae7235048138bb69f8a4fae1d16c229cfb/ios/RNGCM.xcodeproj/project.xcworkspace/xcuserdata/libinlu.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /ios/RNGCM.xcodeproj/xcuserdata/libinlu.xcuserdatad/xcschemes/RCTPushNotification.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /ios/RNGCM.xcodeproj/xcuserdata/libinlu.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | RCTPushNotification.xcscheme 8 | 9 | orderHint 10 | 9 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 58B511DA1A9E6C8500147676 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-gcm-push-notification", 3 | "version": "1.0.3", 4 | "description": "React Native component for Google Cloud Messaging for IOS and Android", 5 | "scripts": { 6 | "test": "echo \"Error: no test specified\" && exit 1" 7 | }, 8 | "repository": { 9 | "type": "git", 10 | "url": "git+https://github.com/evollu/react-native-gcm-push-notification.git" 11 | }, 12 | "keywords": [ 13 | "React-Native", 14 | "ios", 15 | "android", 16 | "gcm" 17 | ], 18 | "author": "Libin Lu", 19 | "license": "MIT", 20 | "bugs": { 21 | "url": "https://github.com/evollu/react-native-gcm-push-notification/issues" 22 | }, 23 | "homepage": "https://github.com/evollu/react-native-gcm-push-notification#readme" 24 | } 25 | --------------------------------------------------------------------------------