├── sample ├── .watchmanconfig ├── .gitattributes ├── babel.config.js ├── app.json ├── android │ ├── app │ │ ├── debug.keystore │ │ ├── src │ │ │ ├── main │ │ │ │ ├── res │ │ │ │ │ ├── values │ │ │ │ │ │ ├── strings.xml │ │ │ │ │ │ └── styles.xml │ │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ └── mipmap-xxxhdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── java │ │ │ │ │ └── com │ │ │ │ │ │ └── reactnativeazurenotificationhubsample │ │ │ │ │ │ ├── MainActivity.java │ │ │ │ │ │ └── MainApplication.java │ │ │ │ └── AndroidManifest.xml │ │ │ └── debug │ │ │ │ └── AndroidManifest.xml │ │ ├── proguard-rules.pro │ │ ├── build_defs.bzl │ │ ├── google-services.json │ │ ├── BUCK │ │ ├── jacoco.gradle │ │ └── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── settings.gradle │ ├── gradle.properties │ ├── build.gradle │ ├── gradlew.bat │ └── gradlew ├── .buckconfig ├── .prettierrc.js ├── ios │ ├── ReactNativeAzureNotificationHubSample │ │ ├── Images.xcassets │ │ │ ├── Contents.json │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ ├── ReactNativeAzureNotificationHubSample.entitlements │ │ ├── AppDelegate.h │ │ ├── main.m │ │ ├── Info.plist │ │ ├── AppDelegate.m │ │ └── Base.lproj │ │ │ └── LaunchScreen.xib │ ├── ReactNativeAzureNotificationHubSample.xcworkspace │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── contents.xcworkspacedata │ ├── ReactNativeAzureNotificationHubSampleTests │ │ ├── Info.plist │ │ ├── RCTAzureNotificationHubUtilTests.m │ │ └── RCTAzureNotificationHandlerTests.m │ ├── ReactNativeAzureNotificationHubSample-tvOSTests │ │ └── Info.plist │ ├── ReactNativeAzureNotificationHubSample-tvOS │ │ └── Info.plist │ ├── Podfile │ └── ReactNativeAzureNotificationHubSample.xcodeproj │ │ └── xcshareddata │ │ └── xcschemes │ │ ├── ReactNativeAzureNotificationHubSample-tvOS.xcscheme │ │ └── ReactNativeAzureNotificationHubSample.xcscheme ├── .eslintrc.js ├── index.js ├── __tests__ │ └── App-test.js ├── metro.config.js ├── README.md ├── .gitignore ├── LICENSE ├── package.json ├── .flowconfig ├── cover2cover.py └── App.js ├── android ├── .gitignore ├── .npmignore ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── com │ │ └── azure │ │ └── reactnative │ │ └── notificationhub │ │ ├── ReactNativeNotificationHubPackage.java │ │ ├── ReactNativeNotificationChannelBuilder.java │ │ ├── ReactNativeFirebaseMessagingService.java │ │ ├── ReactNativeRegistrationIntentService.java │ │ └── ReactNativeConstants.java ├── proguard-rules.pro └── build.gradle ├── index.ios.js ├── .gitignore ├── .npmignore ├── index.js ├── docs ├── img │ ├── EditApp.jpg │ ├── ChooseCsr.jpg │ ├── ConfirmApp.jpg │ ├── CreateApp.jpg │ ├── ExportCert.jpg │ ├── OpenCert.jpg │ ├── SelectApp.jpg │ ├── AddPushNotif.png │ ├── AddReference.png │ ├── ConfigureGCM.png │ ├── ConfigureWNS.png │ ├── DownloadCert.jpg │ ├── RegisterApp.jpg │ ├── SelectDevice.jpg │ ├── SelectIOSApp.jpg │ ├── CertificateInfo.png │ ├── ClickCreateCert.jpg │ ├── ConfigPushNotif.jpg │ ├── CreateAppCont.jpg │ ├── CreateProfile.jpg │ ├── GenerateProfile.jpg │ ├── ProfileCreated.jpg │ ├── SaveCertificate.png │ ├── SelectCodeCert.jpg │ ├── AssociateAppStore.png │ ├── LiveServicesSite.png │ ├── PushNotifEnabled.png │ ├── AddExistingProject.png │ ├── AddFirebaseToAndroid.png │ ├── ApplicationSecrets.png │ ├── GetConnectionString.png │ ├── RequestCertificate.png │ ├── SelectCapabilities.png │ ├── SelectXCodeProfile.png │ ├── CreateNotificationHub.png │ ├── FirebaseProjectSettings.png │ └── AzureNotificationHubAPNSConfig.png └── windows-installation.md ├── windows ├── ReactWindowsAzureNotificationHub │ ├── .npmignore │ ├── project.json │ ├── ReactAzureNotificationHubPackage.cs │ ├── Properties │ │ ├── AssemblyInfo.cs │ │ └── ReactWindowsAzureNotificationHub.rd.xml │ ├── ReactAzureNotificationHubModule.cs │ └── ReactWindowsAzureNotificationHub.csproj ├── ReactWindowsAzureNotificationHub.sln └── .gitignore ├── ios ├── RCTAzureNotificationHubManager.xcodeproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── phongcao.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── phongcao.xcuserdatad │ │ └── xcschemes │ │ ├── xcschememanagement.plist │ │ └── RCTAzureNotificationHubManager.xcscheme └── RCTAzureNotificationHubManager │ ├── RCTAzureNotificationHubUtil.h │ ├── RCTAzureNotificationHandler.h │ ├── RCTAzureNotificationHub.h │ ├── RCTAzureNotificationHandler.m │ ├── RCTAzureNotificationHub.m │ ├── RCTAzureNotificationHubManager.h │ └── RCTAzureNotificationHubUtil.m ├── .slather.yml ├── RNAzureNotificationHub.podspec ├── package.json ├── .github └── issue-template.md ├── LICENSE ├── index.d.ts ├── README.md ├── .gitattributes ├── azure-pipelines.yml └── index.ios.d.ts /sample/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /android/.npmignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /sample/.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | -------------------------------------------------------------------------------- /index.ios.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./ios/AzureNotificationHubIOS'); 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | android/.gradle 2 | android/.idea 3 | android/android.iml 4 | android/local.properties 5 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .gitattributes 2 | .gitignore 3 | .github 4 | .slather.yml 5 | azure-pipelines.yml 6 | sample -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import {NativeModules} from 'react-native'; 2 | module.exports = NativeModules.AzureNotificationHub; 3 | -------------------------------------------------------------------------------- /sample/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:metro-react-native-babel-preset'], 3 | }; 4 | -------------------------------------------------------------------------------- /docs/img/EditApp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/EditApp.jpg -------------------------------------------------------------------------------- /windows/ReactWindowsAzureNotificationHub/.npmignore: -------------------------------------------------------------------------------- 1 | # Make sure we never publish ReactNative build to NPM 2 | bin/ 3 | obj/ -------------------------------------------------------------------------------- /docs/img/ChooseCsr.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/ChooseCsr.jpg -------------------------------------------------------------------------------- /docs/img/ConfirmApp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/ConfirmApp.jpg -------------------------------------------------------------------------------- /docs/img/CreateApp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/CreateApp.jpg -------------------------------------------------------------------------------- /docs/img/ExportCert.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/ExportCert.jpg -------------------------------------------------------------------------------- /docs/img/OpenCert.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/OpenCert.jpg -------------------------------------------------------------------------------- /docs/img/SelectApp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/SelectApp.jpg -------------------------------------------------------------------------------- /docs/img/AddPushNotif.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/AddPushNotif.png -------------------------------------------------------------------------------- /docs/img/AddReference.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/AddReference.png -------------------------------------------------------------------------------- /docs/img/ConfigureGCM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/ConfigureGCM.png -------------------------------------------------------------------------------- /docs/img/ConfigureWNS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/ConfigureWNS.png -------------------------------------------------------------------------------- /docs/img/DownloadCert.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/DownloadCert.jpg -------------------------------------------------------------------------------- /docs/img/RegisterApp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/RegisterApp.jpg -------------------------------------------------------------------------------- /docs/img/SelectDevice.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/SelectDevice.jpg -------------------------------------------------------------------------------- /docs/img/SelectIOSApp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/SelectIOSApp.jpg -------------------------------------------------------------------------------- /docs/img/CertificateInfo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/CertificateInfo.png -------------------------------------------------------------------------------- /docs/img/ClickCreateCert.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/ClickCreateCert.jpg -------------------------------------------------------------------------------- /docs/img/ConfigPushNotif.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/ConfigPushNotif.jpg -------------------------------------------------------------------------------- /docs/img/CreateAppCont.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/CreateAppCont.jpg -------------------------------------------------------------------------------- /docs/img/CreateProfile.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/CreateProfile.jpg -------------------------------------------------------------------------------- /docs/img/GenerateProfile.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/GenerateProfile.jpg -------------------------------------------------------------------------------- /docs/img/ProfileCreated.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/ProfileCreated.jpg -------------------------------------------------------------------------------- /docs/img/SaveCertificate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/SaveCertificate.png -------------------------------------------------------------------------------- /docs/img/SelectCodeCert.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/SelectCodeCert.jpg -------------------------------------------------------------------------------- /sample/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ReactNativeAzureNotificationHubSample", 3 | "displayName": "ReactNativeAzureNotificationHubSample" 4 | } -------------------------------------------------------------------------------- /docs/img/AssociateAppStore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/AssociateAppStore.png -------------------------------------------------------------------------------- /docs/img/LiveServicesSite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/LiveServicesSite.png -------------------------------------------------------------------------------- /docs/img/PushNotifEnabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/PushNotifEnabled.png -------------------------------------------------------------------------------- /docs/img/AddExistingProject.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/AddExistingProject.png -------------------------------------------------------------------------------- /docs/img/AddFirebaseToAndroid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/AddFirebaseToAndroid.png -------------------------------------------------------------------------------- /docs/img/ApplicationSecrets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/ApplicationSecrets.png -------------------------------------------------------------------------------- /docs/img/GetConnectionString.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/GetConnectionString.png -------------------------------------------------------------------------------- /docs/img/RequestCertificate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/RequestCertificate.png -------------------------------------------------------------------------------- /docs/img/SelectCapabilities.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/SelectCapabilities.png -------------------------------------------------------------------------------- /docs/img/SelectXCodeProfile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/SelectXCodeProfile.png -------------------------------------------------------------------------------- /sample/android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/sample/android/app/debug.keystore -------------------------------------------------------------------------------- /docs/img/CreateNotificationHub.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/CreateNotificationHub.png -------------------------------------------------------------------------------- /docs/img/FirebaseProjectSettings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/FirebaseProjectSettings.png -------------------------------------------------------------------------------- /sample/.buckconfig: -------------------------------------------------------------------------------- 1 | 2 | [android] 3 | target = Google Inc.:Google APIs:23 4 | 5 | [maven_repositories] 6 | central = https://repo1.maven.org/maven2 7 | -------------------------------------------------------------------------------- /sample/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | ReactNativeAzureNotificationHubSample 3 | 4 | -------------------------------------------------------------------------------- /docs/img/AzureNotificationHubAPNSConfig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/docs/img/AzureNotificationHubAPNSConfig.png -------------------------------------------------------------------------------- /sample/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | bracketSpacing: false, 3 | jsxBracketSameLine: true, 4 | singleQuote: true, 5 | trailingComma: 'all', 6 | }; 7 | -------------------------------------------------------------------------------- /sample/ios/ReactNativeAzureNotificationHubSample/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /sample/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/sample/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /sample/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/sample/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/sample/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/sample/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/sample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/sample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/sample/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /sample/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/sample/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /sample/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/sample/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /sample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/sample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /sample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/sample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /sample/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: [ 4 | '@react-native-community/eslint-config', 5 | 'eslint-config-prettier', 6 | ], 7 | rules: { 8 | 'prettier/prettier': 0, 9 | }, 10 | }; -------------------------------------------------------------------------------- /sample/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import {AppRegistry} from 'react-native'; 6 | import App from './App'; 7 | import {name as appName} from './app.json'; 8 | 9 | AppRegistry.registerComponent(appName, () => App); 10 | -------------------------------------------------------------------------------- /sample/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.2-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /ios/RCTAzureNotificationHubManager.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/RCTAzureNotificationHubManager.xcodeproj/project.xcworkspace/xcuserdata/phongcao.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/react-native-azurenotificationhub/HEAD/ios/RCTAzureNotificationHubManager.xcodeproj/project.xcworkspace/xcuserdata/phongcao.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /sample/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /sample/__tests__/App-test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import 'react-native'; 6 | import React from 'react'; 7 | import App from '../App'; 8 | 9 | // Note: test renderer must be required after react-native. 10 | import renderer from 'react-test-renderer'; 11 | 12 | it('renders correctly', () => { 13 | renderer.create(); 14 | }); 15 | -------------------------------------------------------------------------------- /sample/ios/ReactNativeAzureNotificationHubSample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /sample/ios/ReactNativeAzureNotificationHubSample/ReactNativeAzureNotificationHubSample.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | aps-environment 6 | development 7 | 8 | 9 | -------------------------------------------------------------------------------- /sample/ios/ReactNativeAzureNotificationHubSample.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /sample/metro.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Metro configuration for React Native 3 | * https://github.com/facebook/react-native 4 | * 5 | * @format 6 | */ 7 | 8 | module.exports = { 9 | transformer: { 10 | getTransformOptions: async () => ({ 11 | transform: { 12 | experimentalImportSupport: false, 13 | inlineRequires: false, 14 | }, 15 | }), 16 | }, 17 | }; 18 | -------------------------------------------------------------------------------- /sample/README.md: -------------------------------------------------------------------------------- 1 | # How to use 2 | 3 | Install npm modules: 4 | 5 | `npm install` 6 | 7 | For Android 8 | 9 | * Update `google-services.json` file and your app's package name. 10 | * Import project with Android Studio to build and run. 11 | 12 | For iOS 13 | 14 | * Run `pod install` to install dependencies. 15 | * Open `ReactNativeAzureNotificationHubSample.xcworkspace` in XCode to build and run. 16 | -------------------------------------------------------------------------------- /sample/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'ReactNativeAzureNotificationHubSample' 2 | apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) 3 | include ':app' 4 | include ':react-native-azurenotificationhub' 5 | project(':react-native-azurenotificationhub').projectDir = file('../node_modules/react-native-azurenotificationhub/android') -------------------------------------------------------------------------------- /sample/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /windows/ReactWindowsAzureNotificationHub/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "Microsoft.NETCore.UniversalWindowsPlatform": "5.2.2", 4 | "WindowsAzure.Messaging.Managed": "0.1.7.9" 5 | }, 6 | "frameworks": { 7 | "uap10.0": {} 8 | }, 9 | "runtimes": { 10 | "win10-arm": {}, 11 | "win10-arm-aot": {}, 12 | "win10-x86": {}, 13 | "win10-x86-aot": {}, 14 | "win10-x64": {}, 15 | "win10-x64-aot": {} 16 | } 17 | } -------------------------------------------------------------------------------- /sample/android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | -------------------------------------------------------------------------------- /.slather.yml: -------------------------------------------------------------------------------- 1 | coverage_service: cobertura_xml 2 | xcodeproj: ios/ReactNativeAzureNotificationHubSample.xcodeproj 3 | workspace: ios/ReactNativeAzureNotificationHubSample.xcworkspace 4 | scheme: ReactNativeAzureNotificationHubSample 5 | output_directory: . 6 | ignore: 7 | - node_modules/* 8 | - ios/Pods/Folly/* 9 | - ios/Pods/DoubleConversion/* 10 | - ios/Pods/glog/* 11 | - ios/Pods/WindowsAzureMessaging/* 12 | - ios/Pods/boost-for-react-native/* 13 | - ios/ReactNativeAzureNotificationHubSample/* 14 | -------------------------------------------------------------------------------- /sample/ios/ReactNativeAzureNotificationHubSample/AppDelegate.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #import 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (nonatomic, strong) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /sample/ios/ReactNativeAzureNotificationHubSample/main.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #import 9 | 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /sample/android/app/src/main/java/com/reactnativeazurenotificationhubsample/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.reactnativeazurenotificationhubsample; 2 | 3 | import com.facebook.react.ReactActivity; 4 | 5 | public class MainActivity extends ReactActivity { 6 | 7 | /** 8 | * Returns the name of the main component registered from JavaScript. This is used to schedule 9 | * rendering of the component. 10 | */ 11 | @Override 12 | protected String getMainComponentName() { 13 | return "ReactNativeAzureNotificationHubSample"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ios/RCTAzureNotificationHubManager.xcodeproj/xcuserdata/phongcao.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | RCTAzureNotificationHubManager.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 458BD4181D9EDE5E007E3F13 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /sample/android/app/build_defs.bzl: -------------------------------------------------------------------------------- 1 | """Helper definitions to glob .aar and .jar targets""" 2 | 3 | def create_aar_targets(aarfiles): 4 | for aarfile in aarfiles: 5 | name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")] 6 | lib_deps.append(":" + name) 7 | android_prebuilt_aar( 8 | name = name, 9 | aar = aarfile, 10 | ) 11 | 12 | def create_jar_targets(jarfiles): 13 | for jarfile in jarfiles: 14 | name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")] 15 | lib_deps.append(":" + name) 16 | prebuilt_jar( 17 | name = name, 18 | binary_jar = jarfile, 19 | ) 20 | -------------------------------------------------------------------------------- /RNAzureNotificationHub.podspec: -------------------------------------------------------------------------------- 1 | require 'json' 2 | 3 | package = JSON.parse(File.read(File.join(__dir__, 'package.json'))) 4 | 5 | Pod::Spec.new do |s| 6 | s.name = "RNAzureNotificationHub" 7 | s.version = package['version'] 8 | s.summary = package['description'] 9 | s.license = package['license'] 10 | 11 | s.authors = package['author'] 12 | s.homepage = package['homepage'] 13 | 14 | s.platform = :ios, "7.0" 15 | s.source = { :git => "https://github.com/CatalystCode/react-native-azurenotificationhub.git", :tag => "master" } 16 | s.source_files = "ios/**/*.{h,m}" 17 | s.requires_arc = true 18 | s.ios.dependency 'WindowsAzureMessaging' 19 | s.dependency "React" 20 | end 21 | -------------------------------------------------------------------------------- /android/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.4.1/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /sample/ios/ReactNativeAzureNotificationHubSample/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /sample/ios/ReactNativeAzureNotificationHubSampleTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /sample/ios/ReactNativeAzureNotificationHubSample-tvOSTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-azurenotificationhub", 3 | "version": "0.9.5-Patched.1", 4 | "description": "React Native module to support Azure Notification Hub push notifications on Android, iOS, and Windows.", 5 | "main": "index.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/CatalystCode/react-native-azurenotificationhub.git" 9 | }, 10 | "keywords": [ 11 | "Azure", 12 | "React", 13 | "Native", 14 | "Push", 15 | "Notifications", 16 | "Hub" 17 | ], 18 | "author": "rozele", 19 | "license": "MIT", 20 | "bugs": { 21 | "url": "https://github.com/CatalystCode/react-native-azurenotificationhub/issues" 22 | }, 23 | "homepage": "https://github.com/CatalystCode/react-native-azurenotificationhub#readme", 24 | "devDependencies": { 25 | "react": "^15.3.0", 26 | "react-native": "^0.32.0", 27 | "react-native-windows": "^0.32.0" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /windows/ReactWindowsAzureNotificationHub/ReactAzureNotificationHubPackage.cs: -------------------------------------------------------------------------------- 1 | using ReactNative.Bridge; 2 | using ReactNative.Modules.Core; 3 | using ReactNative.UIManager; 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | namespace ReactWindowsAzureNotificationHub 8 | { 9 | public class ReactAzureNotificationHubPackage : IReactPackage 10 | { 11 | public IReadOnlyList CreateJavaScriptModulesConfig() 12 | { 13 | return new List(0); 14 | } 15 | 16 | public IReadOnlyList CreateNativeModules(ReactContext reactContext) 17 | { 18 | return new List 19 | { 20 | new ReactAzureNotificationHubModule(reactContext), 21 | }; 22 | } 23 | 24 | public IReadOnlyList CreateViewManagers(ReactContext reactContext) 25 | { 26 | return new List(0); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /sample/android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | android.useAndroidX=true 21 | android.enableJetifier=true 22 | -------------------------------------------------------------------------------- /.github/issue-template.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Issue template 3 | about: Issue template 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Report 11 | 12 | - [ ] I have searched [existing issues](https://github.com/CatalystCode/react-native-azurenotificationhub/issues) and this is not a duplicate. 13 | 14 | ## Environment 15 | 16 | 17 | - Platforms: 18 | 19 | - Android version: 20 | 21 | - iOS version: 22 | 23 | ## Issues and Steps to Reproduce 24 | ***Replaces this with steps to repro your issue, if applicable.*** 25 | 26 | ## Expected Behavior 27 | ***Describe what you expected would happen.*** 28 | 29 | ## Actual Behavior 30 | ***Describe what actually happened. Include screenshots, if applicable.*** 31 | 32 | ## Link to Code 33 | ***If you have some code that maintainers can clone/test for themselves, bugs can be resolved much faster. Please paste a link here.*** 34 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 28 5 | 6 | defaultConfig { 7 | minSdkVersion 16 8 | targetSdkVersion 28 9 | versionCode 1 10 | versionName "1.0" 11 | ndk { 12 | abiFilters "armeabi-v7a", "x86" 13 | } 14 | } 15 | buildTypes { 16 | release { 17 | minifyEnabled false 18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 19 | } 20 | } 21 | } 22 | 23 | dependencies { 24 | implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar']) 25 | implementation 'com.facebook.react:react-native:+' 26 | implementation 'com.google.firebase:firebase-messaging:17.6.0' 27 | implementation 'com.android.support:appcompat-v7:28.0.0' 28 | implementation 'com.microsoft.azure:notification-hubs-android-sdk:0.6@aar' 29 | } 30 | 31 | repositories { 32 | maven { 33 | url "http://dl.bintray.com/microsoftazuremobile/SDK" 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /sample/.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | 24 | # Android/IntelliJ 25 | # 26 | build/ 27 | .idea 28 | .gradle 29 | local.properties 30 | *.iml 31 | 32 | # node.js 33 | # 34 | node_modules/ 35 | npm-debug.log 36 | yarn-error.log 37 | 38 | # BUCK 39 | buck-out/ 40 | \.buckd/ 41 | *.keystore 42 | !debug.keystore 43 | 44 | # fastlane 45 | # 46 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 47 | # screenshots whenever they are needed. 48 | # For more information about the recommended setup visit: 49 | # https://docs.fastlane.tools/best-practices/source-control/ 50 | 51 | */fastlane/report.xml 52 | */fastlane/Preview.html 53 | */fastlane/screenshots 54 | 55 | # Bundle artifact 56 | *.jsbundle 57 | 58 | # CocoaPods 59 | /ios/Pods/ 60 | -------------------------------------------------------------------------------- /android/src/main/java/com/azure/reactnative/notificationhub/ReactNativeNotificationHubPackage.java: -------------------------------------------------------------------------------- 1 | package com.azure.reactnative.notificationhub; 2 | 3 | import com.facebook.react.ReactPackage; 4 | import com.facebook.react.bridge.JavaScriptModule; 5 | import com.facebook.react.bridge.NativeModule; 6 | import com.facebook.react.bridge.ReactApplicationContext; 7 | import com.facebook.react.uimanager.ViewManager; 8 | 9 | import java.util.Collections; 10 | import java.util.List; 11 | 12 | public class ReactNativeNotificationHubPackage implements ReactPackage { 13 | @Override 14 | public List createNativeModules( 15 | ReactApplicationContext reactContext) { 16 | return Collections.singletonList(new ReactNativeNotificationHubModule(reactContext)); 17 | } 18 | 19 | public List> createJSModules() { 20 | return Collections.emptyList(); 21 | } 22 | 23 | @Override 24 | public List createViewManagers(ReactApplicationContext reactContext) { 25 | return Collections.emptyList(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /sample/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Phong Cao 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 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Microsoft Partner Catalyst Team 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 | -------------------------------------------------------------------------------- /sample/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ReactNativeAzureNotificationHubSample", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "android": "react-native run-android", 7 | "ios": "react-native run-ios", 8 | "start": "react-native start", 9 | "test": "jest", 10 | "lint": "eslint . && eslint --no-ignore node_modules/react-native-azurenotificationhub/index.js && eslint --no-ignore node_modules/react-native-azurenotificationhub/index.ios.js && eslint --no-ignore node_modules/react-native-azurenotificationhub/ios/AzureNotificationHubIOS.js" 11 | }, 12 | "dependencies": { 13 | "mem": "^4.0.0", 14 | "react": "16.9.0", 15 | "react-native": "0.61.5", 16 | "react-native-azurenotificationhub": "^0.9.5" 17 | }, 18 | "devDependencies": { 19 | "@babel/core": "7.8.4", 20 | "@babel/runtime": "7.8.4", 21 | "@react-native-community/eslint-config": "0.0.5", 22 | "babel-jest": "24.9.0", 23 | "eslint": "6.8.0", 24 | "eslint-config-prettier": "^6.10.0", 25 | "jest": "24.9.0", 26 | "metro-react-native-babel-preset": "0.56.4", 27 | "react-test-renderer": "16.9.0" 28 | }, 29 | "jest": { 30 | "preset": "react-native" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /windows/ReactWindowsAzureNotificationHub/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ReactWindowsAzureNotificationHub")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ReactWindowsAzureNotificationHub")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Version information for an assembly consists of the following four values: 18 | // 19 | // Major Version 20 | // Minor Version 21 | // Build Number 22 | // Revision 23 | // 24 | // You can specify all the values or you can default the Build and Revision Numbers 25 | // by using the '*' as shown below: 26 | // [assembly: AssemblyVersion("1.0.*")] 27 | [assembly: AssemblyVersion("1.0.0.0")] 28 | [assembly: AssemblyFileVersion("1.0.0.0")] 29 | [assembly: ComVisible(false)] -------------------------------------------------------------------------------- /sample/android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext { 5 | buildToolsVersion = "28.0.3" 6 | minSdkVersion = 16 7 | compileSdkVersion = 28 8 | targetSdkVersion = 28 9 | } 10 | repositories { 11 | google() 12 | jcenter() 13 | } 14 | dependencies { 15 | classpath("com.android.tools.build:gradle:3.4.2") 16 | classpath("com.google.gms:google-services:4.2.0") 17 | 18 | // NOTE: Do not place your application dependencies here; they belong 19 | // in the individual module build.gradle files 20 | } 21 | } 22 | 23 | allprojects { 24 | repositories { 25 | mavenLocal() 26 | maven { 27 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 28 | url("$rootDir/../node_modules/react-native/android") 29 | } 30 | maven { 31 | // Android JSC is installed from npm 32 | url("$rootDir/../node_modules/jsc-android/dist") 33 | } 34 | 35 | google() 36 | jcenter() 37 | maven { url 'https://jitpack.io' } 38 | maven { url 'https://dl.bintray.com/microsoftazuremobile/SDK' } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | declare namespace AzureNotificationHub { 2 | export interface RegistrationConfig { 3 | connectionString: string; 4 | hubName: string; 5 | senderID: string; 6 | tags: string[]; 7 | channelName: string; 8 | channelImportance: boolean; 9 | channelShowBadge: boolean; 10 | channelEnableLights: boolean; 11 | channelEnableVibration: boolean; 12 | } 13 | 14 | export interface TemplateRegistrationConfig extends RegistrationConfig { 15 | templateName: string; 16 | template: string; 17 | } 18 | 19 | export interface RegistrationResponse { 20 | uuid: string; 21 | } 22 | } 23 | 24 | declare class AzureNotificationHub { 25 | static register(config: AzureNotificationHub.RegistrationConfig): Promise; 26 | static registerTemplate(config: AzureNotificationHub.TemplateRegistrationConfig): Promise; 27 | static unregister(): Promise; 28 | static unregisterTemplate(templateName: string): Promise; 29 | static getUUID(autoGen: boolean): Promise; 30 | static getInitialNotification(): Promise; 31 | static isNotificationEnabledOnOSLevel(): Promise; 32 | } 33 | 34 | export = AzureNotificationHub; 35 | -------------------------------------------------------------------------------- /sample/android/app/google-services.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_info": { 3 | "project_number": "123456789000", 4 | "firebase_url": "https://reactnativeazurenotificationhubsample-1234.firebaseio.com", 5 | "project_id": "reactnativeazurenotificationhubsample-1234", 6 | "storage_bucket": "reactnativeazurenotificationhubsample-1234.appspot.com" 7 | }, 8 | "client": [ 9 | { 10 | "client_info": { 11 | "mobilesdk_app_id": "1:123456789000:android:f1bf012572b04063", 12 | "android_client_info": { 13 | "package_name": "com.reactnativeazurenotificationhubsample" 14 | } 15 | }, 16 | "oauth_client": [ 17 | { 18 | "client_id": "123456789000-hjugbg6ud799v4c49dim8ce2usclthar.apps.googleusercontent.com", 19 | "client_type": 3 20 | } 21 | ], 22 | "api_key": [ 23 | { 24 | "current_key": "AIzbSzCn1N6LWIe6wthYyrgUUSAlUsdqMb-wvTo" 25 | } 26 | ], 27 | "services": { 28 | "appinvite_service": { 29 | "other_platform_oauth_client": [ 30 | { 31 | "client_id": "123456789000-hjugbg6ud799v4c49dim8ce2usclthar.apps.googleusercontent.com", 32 | "client_type": 3 33 | } 34 | ] 35 | } 36 | } 37 | } 38 | ], 39 | "configuration_version": "1" 40 | } -------------------------------------------------------------------------------- /ios/RCTAzureNotificationHubManager/RCTAzureNotificationHubUtil.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 | #ifndef RCTAzureNotificationHubUtil_h 11 | #define RCTAzureNotificationHubUtil_h 12 | 13 | #import 14 | 15 | @import UserNotifications; 16 | 17 | @interface RCTAzureNotificationHubUtil : NSObject 18 | 19 | // Format UNNotification 20 | + (nonnull NSDictionary *)formatUNNotification:(nonnull UNNotification *)notification; 21 | 22 | // Format local notification 23 | + (nonnull NSDictionary *)formatLocalNotification:(nonnull UILocalNotification *)notification; 24 | 25 | // Create Azure Notification Hub 26 | + (nonnull SBNotificationHub *)createAzureNotificationHub:(nonnull NSString *)connectionString 27 | hubName:(nonnull NSString *)hubName; 28 | 29 | // Convert device token to string 30 | + (nonnull NSString *)convertDeviceTokenToString:(nonnull NSData *)deviceToken; 31 | 32 | // Get notification types with permissions 33 | + (UNAuthorizationOptions)getNotificationTypesWithPermissions:(nullable NSDictionary *)permissions; 34 | 35 | // Run block on the main thread 36 | + (void)runOnMainThread:(nonnull dispatch_block_t)block; 37 | 38 | @end 39 | 40 | #endif /* RCTAzureNotificationHubUtil_h */ 41 | -------------------------------------------------------------------------------- /ios/RCTAzureNotificationHubManager/RCTAzureNotificationHandler.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 | #ifndef RCTAzureNotificationHandler_h 11 | #define RCTAzureNotificationHandler_h 12 | 13 | #import "React/RCTEventEmitter.h" 14 | 15 | @interface RCTAzureNotificationHandler : NSObject 16 | 17 | // Class initializer 18 | - (nullable instancetype)initWithEventEmitter:(nonnull RCTEventEmitter *)eventEmitter; 19 | 20 | // Handle local notifications 21 | - (void)localNotificationReceived:(nonnull NSNotification *)notification; 22 | 23 | // Handle remote notifications 24 | - (void)remoteNotificationReceived:(nonnull NSNotification *)notification; 25 | 26 | // Handle successful registration for remote notifications 27 | - (void)remoteNotificationRegistered:(nonnull NSNotification *)notification; 28 | 29 | // Handle registration error for remote notifications 30 | - (void)remoteNotificationRegisteredError:(nonnull NSNotification *)notification; 31 | 32 | // Handle successful registration for Azure Notification Hub 33 | - (void)azureNotificationHubRegistered:(nonnull NSNotification *)notification; 34 | 35 | // Handle registration error for Azure Notification Hub 36 | - (void)azureNotificationHubRegisteredError:(nonnull NSNotification *)notification; 37 | 38 | @end 39 | 40 | #endif /* RCTAzureNotificationHandler_h */ 41 | -------------------------------------------------------------------------------- /sample/android/app/BUCK: -------------------------------------------------------------------------------- 1 | # To learn about Buck see [Docs](https://buckbuild.com/). 2 | # To run your application with Buck: 3 | # - install Buck 4 | # - `npm start` - to start the packager 5 | # - `cd android` 6 | # - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"` 7 | # - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck 8 | # - `buck install -r android/app` - compile, install and run application 9 | # 10 | 11 | load(":build_defs.bzl", "create_aar_targets", "create_jar_targets") 12 | 13 | lib_deps = [] 14 | 15 | create_aar_targets(glob(["libs/*.aar"])) 16 | 17 | create_jar_targets(glob(["libs/*.jar"])) 18 | 19 | android_library( 20 | name = "all-libs", 21 | exported_deps = lib_deps, 22 | ) 23 | 24 | android_library( 25 | name = "app-code", 26 | srcs = glob([ 27 | "src/main/java/**/*.java", 28 | ]), 29 | deps = [ 30 | ":all-libs", 31 | ":build_config", 32 | ":res", 33 | ], 34 | ) 35 | 36 | android_build_config( 37 | name = "build_config", 38 | package = "com.reactnativeazurenotificationhubsample", 39 | ) 40 | 41 | android_resource( 42 | name = "res", 43 | package = "com.reactnativeazurenotificationhubsample", 44 | res = "src/main/res", 45 | ) 46 | 47 | android_binary( 48 | name = "app", 49 | keystore = "//android/keystores:debug", 50 | manifest = "src/main/AndroidManifest.xml", 51 | package_type = "debug", 52 | deps = [ 53 | ":app-code", 54 | ], 55 | ) 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React Native Azure Notification Hub 2 | 3 | React Native module to support Azure Notification Hub push notifications on Android, iOS, and Windows. 4 | 5 | [![npm version](https://badge.fury.io/js/react-native-azurenotificationhub.svg)](https://badge.fury.io/js/react-native-azurenotificationhub) 6 | ![npm](https://img.shields.io/npm/dm/react-native-azurenotificationhub) 7 | [![Build Status](https://dev.azure.com/phongthaicao/react-native-azurenotificationhub/_apis/build/status/CatalystCode.react-native-azurenotificationhub?branchName=master)](https://dev.azure.com/phongthaicao/react-native-azurenotificationhub/_apis/build/status/CatalystCode.react-native-azurenotificationhub?branchName=master) 8 | 9 | ![Platform Android](https://img.shields.io/badge/-Android-blue) 10 | ![Platform iOS](https://img.shields.io/badge/-iOS-blue) 11 | ![Azure DevOps coverage (branch)](https://img.shields.io/azure-devops/coverage/phongthaicao/react-native-azurenotificationhub/1/master) 12 | 13 | # Platform-specific Guides 14 | - [Android](docs/android-installation.md) 15 | - [iOS](docs/ios-installation.md) 16 | - [Windows](docs/windows-installation.md) 17 | 18 | # License 19 | 20 | The React Native Azure Notification Hub plugin is provided under the [MIT License](LICENSE). 21 | 22 | # Code of Conduct 23 | 24 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 25 | -------------------------------------------------------------------------------- /sample/ios/ReactNativeAzureNotificationHubSample-tvOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | NSAppTransportSecurity 26 | 27 | NSExceptionDomains 28 | 29 | localhost 30 | 31 | NSExceptionAllowsInsecureHTTPLoads 32 | 33 | 34 | 35 | 36 | NSLocationWhenInUseUsageDescription 37 | 38 | UILaunchStoryboardName 39 | LaunchScreen 40 | UIRequiredDeviceCapabilities 41 | 42 | armv7 43 | 44 | UISupportedInterfaceOrientations 45 | 46 | UIInterfaceOrientationPortrait 47 | UIInterfaceOrientationLandscapeLeft 48 | UIInterfaceOrientationLandscapeRight 49 | 50 | UIViewControllerBasedStatusBarAppearance 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /windows/ReactWindowsAzureNotificationHub/Properties/ReactWindowsAzureNotificationHub.rd.xml: -------------------------------------------------------------------------------- 1 | 2 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /sample/ios/ReactNativeAzureNotificationHubSample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ReactNativeAzureNotificationHubSample 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSRequiresIPhoneOS 26 | 27 | NSAppTransportSecurity 28 | 29 | NSAllowsArbitraryLoads 30 | 31 | NSExceptionDomains 32 | 33 | localhost 34 | 35 | NSExceptionAllowsInsecureHTTPLoads 36 | 37 | 38 | 39 | 40 | NSLocationWhenInUseUsageDescription 41 | 42 | UILaunchStoryboardName 43 | LaunchScreen 44 | UIRequiredDeviceCapabilities 45 | 46 | armv7 47 | 48 | UISupportedInterfaceOrientations 49 | 50 | UIInterfaceOrientationPortrait 51 | UIInterfaceOrientationLandscapeLeft 52 | UIInterfaceOrientationLandscapeRight 53 | 54 | UIViewControllerBasedStatusBarAppearance 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /sample/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 17 | 20 | 24 | 27 | 28 | 29 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /android/src/main/java/com/azure/reactnative/notificationhub/ReactNativeNotificationChannelBuilder.java: -------------------------------------------------------------------------------- 1 | package com.azure.reactnative.notificationhub; 2 | 3 | import android.app.NotificationChannel; 4 | import android.app.NotificationManager; 5 | 6 | public class ReactNativeNotificationChannelBuilder { 7 | private String mID = ReactNativeConstants.NOTIFICATION_CHANNEL_ID; 8 | private CharSequence mName = "rn-push-notification-channel-name"; 9 | private int mImportance = NotificationManager.IMPORTANCE_DEFAULT; 10 | private boolean mShowBadge = true; 11 | private boolean mEnableLights = true; 12 | private boolean mEnableVibration = true; 13 | private String mDesc = null; 14 | 15 | public static class Factory { 16 | public static ReactNativeNotificationChannelBuilder create() { 17 | return new ReactNativeNotificationChannelBuilder(); 18 | } 19 | } 20 | 21 | private ReactNativeNotificationChannelBuilder() { 22 | } 23 | 24 | public NotificationChannel build() { 25 | NotificationChannel channel = new NotificationChannel(mID, mName, mImportance); 26 | channel.setShowBadge(mShowBadge); 27 | channel.enableLights(mEnableLights); 28 | channel.enableVibration(mEnableVibration); 29 | 30 | if (mDesc != null) { 31 | channel.setDescription(mDesc); 32 | } 33 | 34 | return channel; 35 | } 36 | 37 | public ReactNativeNotificationChannelBuilder setName(CharSequence name) { 38 | this.mName = name; 39 | return this; 40 | } 41 | 42 | public ReactNativeNotificationChannelBuilder setImportance(int importance) { 43 | this.mImportance = importance; 44 | return this; 45 | } 46 | 47 | public ReactNativeNotificationChannelBuilder setDescription(String desc) { 48 | this.mDesc = desc; 49 | return this; 50 | } 51 | 52 | public ReactNativeNotificationChannelBuilder setShowBadge(boolean showBadge) { 53 | this.mShowBadge = showBadge; 54 | return this; 55 | } 56 | 57 | public ReactNativeNotificationChannelBuilder enableLights(boolean enableLights) { 58 | this.mEnableLights = enableLights; 59 | return this; 60 | } 61 | 62 | public ReactNativeNotificationChannelBuilder enableVibration(boolean enableVibration) { 63 | this.mEnableVibration = enableVibration; 64 | return this; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /sample/.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | ; We fork some components by platform 3 | .*/*[.]android.js 4 | 5 | ; Ignore "BUCK" generated dirs 6 | /\.buckd/ 7 | 8 | ; Ignore polyfills 9 | node_modules/react-native/Libraries/polyfills/.* 10 | 11 | ; These should not be required directly 12 | ; require from fbjs/lib instead: require('fbjs/lib/warning') 13 | node_modules/warning/.* 14 | 15 | ; Flow doesn't support platforms 16 | .*/Libraries/Utilities/LoadingView.js 17 | 18 | [untyped] 19 | .*/node_modules/@react-native-community/cli/.*/.* 20 | 21 | [include] 22 | 23 | [libs] 24 | node_modules/react-native/Libraries/react-native/react-native-interface.js 25 | node_modules/react-native/flow/ 26 | 27 | [options] 28 | emoji=true 29 | 30 | esproposal.optional_chaining=enable 31 | esproposal.nullish_coalescing=enable 32 | 33 | module.file_ext=.js 34 | module.file_ext=.json 35 | module.file_ext=.ios.js 36 | 37 | munge_underscores=true 38 | 39 | module.name_mapper='^react-native$' -> '/node_modules/react-native/Libraries/react-native/react-native-implementation' 40 | module.name_mapper='^react-native/\(.*\)$' -> '/node_modules/react-native/\1' 41 | module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> '/node_modules/react-native/Libraries/Image/RelativeImageStub' 42 | 43 | suppress_type=$FlowIssue 44 | suppress_type=$FlowFixMe 45 | suppress_type=$FlowFixMeProps 46 | suppress_type=$FlowFixMeState 47 | 48 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\) 49 | suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\)?:? #[0-9]+ 50 | suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError 51 | 52 | [lints] 53 | sketchy-null-number=warn 54 | sketchy-null-mixed=warn 55 | sketchy-number=warn 56 | untyped-type-import=warn 57 | nonstrict-import=warn 58 | deprecated-type=warn 59 | unsafe-getters-setters=warn 60 | inexact-spread=warn 61 | unnecessary-invariant=warn 62 | signature-verification-failure=warn 63 | deprecated-utility=error 64 | 65 | [strict] 66 | deprecated-type 67 | nonstrict-import 68 | sketchy-null 69 | unclear-type 70 | unsafe-getters-setters 71 | untyped-import 72 | untyped-type-import 73 | 74 | [version] 75 | ^0.105.0 76 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /ios/RCTAzureNotificationHubManager/RCTAzureNotificationHub.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 | #ifndef RCTAzureNotificationHub_h 11 | #define RCTAzureNotificationHub_h 12 | 13 | @import UserNotifications; 14 | 15 | // Notification Hub events 16 | extern NSString *const RCTLocalNotificationReceived; 17 | extern NSString *const RCTRemoteNotificationReceived; 18 | extern NSString *const RCTRemoteNotificationRegistered; 19 | extern NSString *const RCTRemoteNotificationRegisteredError; 20 | extern NSString *const RCTAzureNotificationHubRegistered; 21 | extern NSString *const RCTAzureNotificationHubRegisteredError; 22 | extern NSString *const RCTUserNotificationSettingsRegistered; 23 | 24 | // Config keys used when registering 25 | extern NSString *const RCTConnectionStringKey; 26 | extern NSString *const RCTHubNameKey; 27 | extern NSString *const RCTTagsKey; 28 | extern NSString *const RCTTemplateNameKey; 29 | extern NSString *const RCTTemplateKey; 30 | 31 | // User info 32 | extern NSString *const RCTUserInfoDeviceToken; 33 | extern NSString *const RCTUserInfoRemote; 34 | extern NSString *const RCTUserInfoResolveBlock; 35 | extern NSString *const RCTUserInfoRejectBlock; 36 | extern NSString *const RCTUserInfoSuccess; 37 | extern NSString *const RCTUserInfoError; 38 | 39 | // Notification types 40 | extern NSString *const RCTNotificationTypeBadge; 41 | extern NSString *const RCTNotificationTypeSound; 42 | extern NSString *const RCTNotificationTypeAlert; 43 | 44 | // Messages 45 | extern NSString *const RCTPromiseResolveUnregiseredSuccessfully; 46 | 47 | // Errors 48 | extern NSString *const RCTErrorUnableToRequestPermissions; 49 | extern NSString *const RCTErrorUnableToRequestPermissionsAppExt; 50 | extern NSString *const RCTErrorUnableToRequestPermissionsTwice; 51 | extern NSString *const RCTErrorUnableToRequestPermissionsUserReject; 52 | extern NSString *const RCTErrorInvalidArguments; 53 | extern NSString *const RCTErrorMissingConnectionString; 54 | extern NSString *const RCTErrorMissingHubName; 55 | extern NSString *const RCTErrorMissingTemplateName; 56 | extern NSString *const RCTErrorMissingTemplate; 57 | extern NSString *const RCTErrorUnableToUnregister; 58 | extern NSString *const RCTErrorUnableToUnregisterNoRegistration; 59 | 60 | // Completion types 61 | typedef void (^RCTNativeCompletion)(NSError *error); 62 | typedef void (^RCTNotificationCompletion)(BOOL granted, NSError * _Nullable error); 63 | typedef void (^RCTNotificationSettingsCompletion)(UNNotificationSettings * _Nonnull settings); 64 | 65 | #endif /* RCTAzureNotificationHub_h */ 66 | -------------------------------------------------------------------------------- /sample/android/app/src/main/java/com/reactnativeazurenotificationhubsample/MainApplication.java: -------------------------------------------------------------------------------- 1 | package com.reactnativeazurenotificationhubsample; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | import com.facebook.react.PackageList; 6 | import com.facebook.react.ReactApplication; 7 | import com.facebook.react.ReactNativeHost; 8 | import com.facebook.react.ReactPackage; 9 | import com.facebook.soloader.SoLoader; 10 | import java.lang.reflect.InvocationTargetException; 11 | import java.util.List; 12 | import com.azure.reactnative.notificationhub.ReactNativeNotificationHubPackage; 13 | 14 | public class MainApplication extends Application implements ReactApplication { 15 | 16 | private final ReactNativeHost mReactNativeHost = 17 | new ReactNativeHost(this) { 18 | @Override 19 | public boolean getUseDeveloperSupport() { 20 | return BuildConfig.DEBUG; 21 | } 22 | 23 | @Override 24 | protected List getPackages() { 25 | @SuppressWarnings("UnnecessaryLocalVariable") 26 | List packages = new PackageList(this).getPackages(); 27 | // Packages that cannot be autolinked yet can be added manually here, for example: 28 | // packages.add(new MyReactNativePackage()); 29 | packages.add(new ReactNativeNotificationHubPackage()); 30 | return packages; 31 | } 32 | 33 | @Override 34 | protected String getJSMainModuleName() { 35 | return "index"; 36 | } 37 | }; 38 | 39 | @Override 40 | public ReactNativeHost getReactNativeHost() { 41 | return mReactNativeHost; 42 | } 43 | 44 | @Override 45 | public void onCreate() { 46 | super.onCreate(); 47 | SoLoader.init(this, /* native exopackage */ false); 48 | initializeFlipper(this); // Remove this line if you don't want Flipper enabled 49 | } 50 | 51 | /** 52 | * Loads Flipper in React Native templates. 53 | * 54 | * @param context 55 | */ 56 | private static void initializeFlipper(Context context) { 57 | if (BuildConfig.DEBUG) { 58 | try { 59 | /* 60 | We use reflection here to pick up the class that initializes Flipper, 61 | since Flipper library is not available in release mode 62 | */ 63 | Class aClass = Class.forName("com.facebook.flipper.ReactNativeFlipper"); 64 | aClass.getMethod("initializeFlipper", Context.class).invoke(null, context); 65 | } catch (ClassNotFoundException e) { 66 | e.printStackTrace(); 67 | } catch (NoSuchMethodException e) { 68 | e.printStackTrace(); 69 | } catch (IllegalAccessException e) { 70 | e.printStackTrace(); 71 | } catch (InvocationTargetException e) { 72 | e.printStackTrace(); 73 | } 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /windows/ReactWindowsAzureNotificationHub.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReactWindowsAzureNotificationHub", "ReactWindowsAzureNotificationHub\ReactWindowsAzureNotificationHub.csproj", "{95F0B433-B38E-435C-BC83-939A9E4B470D}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReactNative", "..\..\node_modules\react-native-windows\ReactWindows\ReactNative\ReactNative.csproj", "{C7673AD5-E3AA-468C-A5FD-FA38154E205C}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|ARM = Debug|ARM 13 | Debug|x64 = Debug|x64 14 | Debug|x86 = Debug|x86 15 | Release|ARM = Release|ARM 16 | Release|x64 = Release|x64 17 | Release|x86 = Release|x86 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {95F0B433-B38E-435C-BC83-939A9E4B470D}.Debug|ARM.ActiveCfg = Debug|ARM 21 | {95F0B433-B38E-435C-BC83-939A9E4B470D}.Debug|ARM.Build.0 = Debug|ARM 22 | {95F0B433-B38E-435C-BC83-939A9E4B470D}.Debug|x64.ActiveCfg = Debug|x64 23 | {95F0B433-B38E-435C-BC83-939A9E4B470D}.Debug|x64.Build.0 = Debug|x64 24 | {95F0B433-B38E-435C-BC83-939A9E4B470D}.Debug|x86.ActiveCfg = Debug|x86 25 | {95F0B433-B38E-435C-BC83-939A9E4B470D}.Debug|x86.Build.0 = Debug|x86 26 | {95F0B433-B38E-435C-BC83-939A9E4B470D}.Release|ARM.ActiveCfg = Release|ARM 27 | {95F0B433-B38E-435C-BC83-939A9E4B470D}.Release|ARM.Build.0 = Release|ARM 28 | {95F0B433-B38E-435C-BC83-939A9E4B470D}.Release|x64.ActiveCfg = Release|x64 29 | {95F0B433-B38E-435C-BC83-939A9E4B470D}.Release|x64.Build.0 = Release|x64 30 | {95F0B433-B38E-435C-BC83-939A9E4B470D}.Release|x86.ActiveCfg = Release|x86 31 | {95F0B433-B38E-435C-BC83-939A9E4B470D}.Release|x86.Build.0 = Release|x86 32 | {C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Debug|ARM.ActiveCfg = Debug|ARM 33 | {C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Debug|ARM.Build.0 = Debug|ARM 34 | {C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Debug|x64.ActiveCfg = Debug|x64 35 | {C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Debug|x64.Build.0 = Debug|x64 36 | {C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Debug|x86.ActiveCfg = Debug|x86 37 | {C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Debug|x86.Build.0 = Debug|x86 38 | {C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Release|ARM.ActiveCfg = Release|ARM 39 | {C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Release|ARM.Build.0 = Release|ARM 40 | {C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Release|x64.ActiveCfg = Release|x64 41 | {C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Release|x64.Build.0 = Release|x64 42 | {C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Release|x86.ActiveCfg = Release|x86 43 | {C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Release|x86.Build.0 = Release|x86 44 | EndGlobalSection 45 | GlobalSection(SolutionProperties) = preSolution 46 | HideSolutionNode = FALSE 47 | EndGlobalSection 48 | EndGlobal 49 | -------------------------------------------------------------------------------- /sample/ios/Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '9.0' 2 | require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' 3 | 4 | target 'ReactNativeAzureNotificationHubSample' do 5 | # Pods for ReactNativeAzureNotificationHubSample 6 | pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector" 7 | pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec" 8 | pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired" 9 | pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety" 10 | pod 'React', :path => '../node_modules/react-native/' 11 | pod 'React-Core', :path => '../node_modules/react-native/' 12 | pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules' 13 | pod 'React-Core/DevSupport', :path => '../node_modules/react-native/' 14 | pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS' 15 | pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation' 16 | pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob' 17 | pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image' 18 | pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS' 19 | pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network' 20 | pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings' 21 | pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text' 22 | pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration' 23 | pod 'React-Core/RCTWebSocket', :path => '../node_modules/react-native/' 24 | 25 | pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact' 26 | pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi' 27 | pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor' 28 | pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector' 29 | pod 'ReactCommon/jscallinvoker', :path => "../node_modules/react-native/ReactCommon" 30 | pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon" 31 | pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga' 32 | 33 | pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec' 34 | pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec' 35 | pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec' 36 | pod 'RNAzureNotificationHub', :podspec => '../node_modules/react-native-azurenotificationhub/RNAzureNotificationHub.podspec' 37 | 38 | target 'ReactNativeAzureNotificationHubSampleTests' do 39 | inherit! :search_paths 40 | use_frameworks! 41 | pod 'OCMock', '~> 3.6' 42 | end 43 | 44 | use_native_modules! 45 | end 46 | -------------------------------------------------------------------------------- /windows/ReactWindowsAzureNotificationHub/ReactAzureNotificationHubModule.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.WindowsAzure.Messaging; 2 | using Newtonsoft.Json.Linq; 3 | using ReactNative.Bridge; 4 | using System; 5 | using Windows.Networking.PushNotifications; 6 | 7 | namespace ReactWindowsAzureNotificationHub 8 | { 9 | class ReactAzureNotificationHubModule : ReactContextNativeModuleBase 10 | { 11 | private const string RegistrationFailure = "E_REGISTRATION_FAILED"; 12 | private const string ErrorInvalidArguments = "E_INVALID_ARGUMENTS"; 13 | 14 | private string _connectionString; 15 | private string _hubName; 16 | 17 | public ReactAzureNotificationHubModule(ReactContext reactContext) 18 | : base(reactContext) 19 | { 20 | } 21 | 22 | public override string Name 23 | { 24 | get 25 | { 26 | return "AzureNotificationHub"; 27 | } 28 | } 29 | 30 | [ReactMethod] 31 | public async void register(JObject config, IPromise promise) 32 | { 33 | _connectionString = config.Value("connectionString"); 34 | _hubName = config.Value("hubName"); 35 | var tags = config["tags"]?.ToObject(); 36 | 37 | AssertArguments(promise); 38 | 39 | try 40 | { 41 | var channel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync().AsTask().ConfigureAwait(false); 42 | var hub = new NotificationHub(_hubName, _connectionString); 43 | var result = await hub.RegisterNativeAsync(channel.Uri, tags).ConfigureAwait(false); 44 | if (result.RegistrationId != null) 45 | { 46 | promise.Resolve(result.RegistrationId); 47 | } 48 | else 49 | { 50 | promise.Reject(RegistrationFailure, "Registration was not successful."); 51 | } 52 | } 53 | catch (Exception ex) 54 | { 55 | promise.Reject(ex); 56 | } 57 | } 58 | 59 | [ReactMethod] 60 | public async void unregister(IPromise promise) 61 | { 62 | AssertArguments(promise); 63 | 64 | try 65 | { 66 | var hub = new NotificationHub(_hubName, _connectionString); 67 | await hub.UnregisterNativeAsync(); 68 | promise.Resolve(true); 69 | } 70 | catch (Exception ex) 71 | { 72 | promise.Reject(ex); 73 | } 74 | } 75 | 76 | private void AssertArguments(IPromise promise) 77 | { 78 | if (_connectionString == null) 79 | { 80 | promise.Reject(ErrorInvalidArguments, "Connection string cannot be null."); 81 | } 82 | 83 | if (_hubName == null) 84 | { 85 | promise.Reject(ErrorInvalidArguments, "Hub name cannot be null."); 86 | } 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /ios/RCTAzureNotificationHubManager/RCTAzureNotificationHandler.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 "RCTAzureNotificationHub.h" 11 | #import "RCTAzureNotificationHandler.h" 12 | 13 | @implementation RCTAzureNotificationHandler 14 | { 15 | @private 16 | RCTEventEmitter *_eventEmitter; 17 | } 18 | 19 | // Class initializer 20 | - (nullable instancetype)initWithEventEmitter:(nonnull RCTEventEmitter *)eventEmitter 21 | { 22 | // Initialize superclass. 23 | self = [super init]; 24 | 25 | // Handle errors. 26 | if (!self) 27 | { 28 | return nil; 29 | } 30 | 31 | _eventEmitter = eventEmitter; 32 | 33 | return self; 34 | } 35 | 36 | // Handle local notifications 37 | - (void)localNotificationReceived:(nonnull NSNotification *)notification 38 | { 39 | [_eventEmitter sendEventWithName:RCTLocalNotificationReceived 40 | body:notification.userInfo]; 41 | } 42 | 43 | // Handle remote notifications 44 | - (void)remoteNotificationReceived:(nonnull NSNotification *)notification 45 | { 46 | NSMutableDictionary *userInfo = [notification.userInfo mutableCopy]; 47 | userInfo[RCTUserInfoRemote] = @YES; 48 | [_eventEmitter sendEventWithName:RCTRemoteNotificationReceived 49 | body:userInfo]; 50 | } 51 | 52 | // Handle successful registration for remote notifications 53 | - (void)remoteNotificationRegistered:(nonnull NSNotification *)notification 54 | { 55 | [_eventEmitter sendEventWithName:RCTRemoteNotificationRegistered 56 | body:notification.userInfo]; 57 | } 58 | 59 | // Handle registration error for remote notifications 60 | - (void)remoteNotificationRegisteredError:(nonnull NSNotification *)notification 61 | { 62 | NSError *error = notification.userInfo[RCTUserInfoError]; 63 | NSDictionary *errorDetails = @{ 64 | @"message": error.localizedDescription, 65 | @"code": @(error.code), 66 | @"details": error.userInfo, 67 | }; 68 | [_eventEmitter sendEventWithName:RCTRemoteNotificationRegisteredError 69 | body:errorDetails]; 70 | } 71 | 72 | // Handle successful registration for Azure Notification Hub 73 | - (void)azureNotificationHubRegistered:(nonnull NSNotification *)notification 74 | { 75 | [_eventEmitter sendEventWithName:RCTAzureNotificationHubRegistered 76 | body:notification.userInfo]; 77 | } 78 | 79 | // Handle registration error for Azure Notification Hub 80 | - (void)azureNotificationHubRegisteredError:(nonnull NSNotification *)notification 81 | { 82 | NSError *error = notification.userInfo[RCTUserInfoError]; 83 | NSDictionary *errorDetails = @{ 84 | @"message": error.localizedDescription, 85 | @"code": @(error.code), 86 | @"details": error.userInfo, 87 | }; 88 | 89 | [_eventEmitter sendEventWithName:RCTAzureNotificationHubRegisteredError 90 | body:errorDetails]; 91 | } 92 | 93 | @end 94 | -------------------------------------------------------------------------------- /sample/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem http://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 33 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 34 | 35 | @rem Find java.exe 36 | if defined JAVA_HOME goto findJavaFromJavaHome 37 | 38 | set JAVA_EXE=java.exe 39 | %JAVA_EXE% -version >NUL 2>&1 40 | if "%ERRORLEVEL%" == "0" goto init 41 | 42 | echo. 43 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 44 | echo. 45 | echo Please set the JAVA_HOME variable in your environment to match the 46 | echo location of your Java installation. 47 | 48 | goto fail 49 | 50 | :findJavaFromJavaHome 51 | set JAVA_HOME=%JAVA_HOME:"=% 52 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 53 | 54 | if exist "%JAVA_EXE%" goto init 55 | 56 | echo. 57 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 58 | echo. 59 | echo Please set the JAVA_HOME variable in your environment to match the 60 | echo location of your Java installation. 61 | 62 | goto fail 63 | 64 | :init 65 | @rem Get command-line arguments, handling Windows variants 66 | 67 | if not "%OS%" == "Windows_NT" goto win9xME_args 68 | 69 | :win9xME_args 70 | @rem Slurp the command line arguments. 71 | set CMD_LINE_ARGS= 72 | set _SKIP=2 73 | 74 | :win9xME_args_slurp 75 | if "x%~1" == "x" goto execute 76 | 77 | set CMD_LINE_ARGS=%* 78 | 79 | :execute 80 | @rem Setup the command line 81 | 82 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 83 | 84 | @rem Execute Gradle 85 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 86 | 87 | :end 88 | @rem End local scope for the variables with windows NT shell 89 | if "%ERRORLEVEL%"=="0" goto mainEnd 90 | 91 | :fail 92 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 93 | rem the _cmd.exe /c_ return code! 94 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 95 | exit /b 1 96 | 97 | :mainEnd 98 | if "%OS%"=="Windows_NT" endlocal 99 | 100 | :omega 101 | -------------------------------------------------------------------------------- /ios/RCTAzureNotificationHubManager.xcodeproj/xcuserdata/phongcao.xcuserdatad/xcschemes/RCTAzureNotificationHubManager.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 | -------------------------------------------------------------------------------- /sample/ios/ReactNativeAzureNotificationHubSample/AppDelegate.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #import "AppDelegate.h" 9 | 10 | #import 11 | #import 12 | #import 13 | #import 14 | 15 | @implementation AppDelegate 16 | 17 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 18 | { 19 | RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions]; 20 | RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge 21 | moduleName:@"ReactNativeAzureNotificationHubSample" 22 | initialProperties:nil]; 23 | 24 | rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1]; 25 | 26 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 27 | UIViewController *rootViewController = [UIViewController new]; 28 | rootViewController.view = rootView; 29 | self.window.rootViewController = rootViewController; 30 | [self.window makeKeyAndVisible]; 31 | 32 | // Registering for local notifications 33 | [[UNUserNotificationCenter currentNotificationCenter] setDelegate:self]; 34 | 35 | return YES; 36 | } 37 | 38 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge 39 | { 40 | #if DEBUG 41 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil]; 42 | #else 43 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; 44 | #endif 45 | } 46 | 47 | // Invoked when the app successfully registered with Apple Push Notification service (APNs). 48 | - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken 49 | { 50 | [RCTAzureNotificationHubManager didRegisterForRemoteNotificationsWithDeviceToken:deviceToken]; 51 | } 52 | 53 | // Invoked when APNs cannot successfully complete the registration process. 54 | - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error 55 | { 56 | [RCTAzureNotificationHubManager didFailToRegisterForRemoteNotificationsWithError:error]; 57 | } 58 | 59 | // Invoked when a remote notification arrived and there is data to be fetched. 60 | - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo 61 | fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler 62 | { 63 | [RCTAzureNotificationHubManager didReceiveRemoteNotification:userInfo 64 | fetchCompletionHandler:completionHandler]; 65 | } 66 | 67 | // Invoked when a notification arrived while the app was running in the foreground. 68 | - (void)userNotificationCenter:(UNUserNotificationCenter *)center 69 | willPresentNotification:(UNNotification *)notification 70 | withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler 71 | { 72 | [RCTAzureNotificationHubManager userNotificationCenter:center 73 | willPresentNotification:notification 74 | withCompletionHandler:completionHandler]; 75 | } 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /ios/RCTAzureNotificationHubManager/RCTAzureNotificationHub.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 | // Notification Hub events 11 | NSString *const RCTLocalNotificationReceived = @"localNotificationReceived"; 12 | NSString *const RCTRemoteNotificationReceived = @"remoteNotificationReceived"; 13 | NSString *const RCTRemoteNotificationRegistered = @"remoteNotificationRegistered"; 14 | NSString *const RCTRemoteNotificationRegisteredError = @"remoteNotificationRegisteredError"; 15 | NSString *const RCTAzureNotificationHubRegistered = @"azureNotificationHubRegistered"; 16 | NSString *const RCTAzureNotificationHubRegisteredError = @"azureNotificationHubRegisteredError"; 17 | NSString *const RCTUserNotificationSettingsRegistered = @"userNotificationSettingsRegistered"; 18 | 19 | // Config keys used when registering 20 | NSString *const RCTConnectionStringKey = @"connectionString"; 21 | NSString *const RCTHubNameKey = @"hubName"; 22 | NSString *const RCTTagsKey = @"tags"; 23 | NSString *const RCTTemplateNameKey = @"templateName"; 24 | NSString *const RCTTemplateKey = @"template"; 25 | 26 | // User info 27 | NSString *const RCTUserInfoDeviceToken = @"deviceToken"; 28 | NSString *const RCTUserInfoRemote = @"remote"; 29 | NSString *const RCTUserInfoResolveBlock = @"resolveBlock"; 30 | NSString *const RCTUserInfoRejectBlock = @"rejectBlock"; 31 | NSString *const RCTUserInfoSuccess = @"success"; 32 | NSString *const RCTUserInfoError = @"error"; 33 | 34 | // Notification types 35 | NSString *const RCTNotificationTypeBadge = @"badge"; 36 | NSString *const RCTNotificationTypeSound = @"sound"; 37 | NSString *const RCTNotificationTypeAlert = @"alert"; 38 | 39 | // Messages 40 | NSString *const RCTPromiseResolveUnregiseredSuccessfully = @"Unregisted successfully"; 41 | 42 | // Errors 43 | NSString *const RCTErrorUnableToRequestPermissions = @"Unabled to request permissions"; 44 | NSString *const RCTErrorUnableToRequestPermissionsAppExt = @"Requesting push notifications is currently unavailable in an app extension."; 45 | NSString *const RCTErrorUnableToRequestPermissionsTwice = @"Cannot call requestPermissions twice before the first has returned."; 46 | NSString *const RCTErrorUnableToRequestPermissionsUserReject = @"User didn't allow permissions."; 47 | NSString *const RCTErrorInvalidArguments = @"Invalid arguments"; 48 | NSString *const RCTErrorMissingConnectionString = @"Connection string cannot be null."; 49 | NSString *const RCTErrorMissingHubName = @"Hub name cannot be null."; 50 | NSString *const RCTErrorMissingTemplateName = @"Template name cannot be null."; 51 | NSString *const RCTErrorMissingTemplate = @"Template cannot be null."; 52 | NSString *const RCTErrorUnableToUnregister = @"Unabled to unregister"; 53 | NSString *const RCTErrorUnableToUnregisterNoRegistration = @"There is no registration."; 54 | -------------------------------------------------------------------------------- /sample/ios/ReactNativeAzureNotificationHubSample/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 21 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | trigger: 2 | branches: 3 | include: 4 | - master 5 | - releases/* 6 | exclude: 7 | - refs/tag/* 8 | 9 | pool: 10 | vmImage: 'macOS-10.14' 11 | 12 | steps: 13 | - script: | 14 | mv ./sample ../ 15 | displayName: 'Prepare sample project' 16 | 17 | - task: NodeTool@0 18 | inputs: 19 | versionSpec: '10.15.3' 20 | displayName: 'Install Node' 21 | 22 | - script: gem install slather 23 | displayName: 'Install slather' 24 | workingDirectory: '../sample' 25 | 26 | - script: dotnet tool install -g dotnet-reportgenerator-globaltool 27 | displayName: 'Install ReportGenerator' 28 | workingDirectory: '../sample' 29 | 30 | - script: npm install 31 | displayName: 'Install dependencies' 32 | workingDirectory: '../sample' 33 | 34 | - script: | 35 | rm -R ./node_modules/react-native-azurenotificationhub/* 36 | cp -R ../s/* ./node_modules/react-native-azurenotificationhub/ 37 | cp ../s/.slather.yml . 38 | displayName: 'Copying react-native-azurenotificationhub' 39 | workingDirectory: '../sample' 40 | 41 | - script: npm run lint 42 | displayName: 'Run lint' 43 | workingDirectory: '../sample' 44 | 45 | - task: Gradle@2 46 | displayName: 'Building Android' 47 | inputs: 48 | workingDirectory: '../sample/android' 49 | gradleWrapperFile: '../sample/android/gradlew' 50 | tasks: 'assembleRelease' 51 | continueOnError: false 52 | 53 | - task: Gradle@2 54 | displayName: 'Running Android unit tests' 55 | inputs: 56 | workingDirectory: '../sample/android' 57 | gradleWrapperFile: '../sample/android/gradlew' 58 | testResultsFiles: '../sample/android/app/build/test-results/testDebugUnitTest/*.xml' 59 | publishJUnitResults: 'true' 60 | tasks: 'test' 61 | continueOnError: false 62 | 63 | - task: Gradle@2 64 | displayName: 'Generate Android code coverage' 65 | inputs: 66 | workingDirectory: '../sample/android' 67 | gradleWrapperFile: '../sample/android/gradlew' 68 | tasks: 'clean createOfflineTestCoverageReport jacocoTestReport' 69 | continueOnError: false 70 | 71 | - script: python ./cover2cover.py ./jacocoXml.xml>jacoco.xml 72 | displayName: 'Convert Jacoco report to Cobertura' 73 | workingDirectory: '../sample' 74 | 75 | - script: | 76 | pod install 77 | pod update 78 | sudo cp -R ../node_modules/react-native-azurenotificationhub/ios Pods/RNAzureNotificationHub 79 | sudo chown -R $(id -u):$(id -g) Pods/RNAzureNotificationHub 80 | pod update 81 | displayName: 'Install CocoaPods dependencies' 82 | workingDirectory: '../sample/ios' 83 | 84 | - task: Xcode@5 85 | displayName: 'Building iOS' 86 | inputs: 87 | actions: 'build' 88 | scheme: 'ReactNativeAzureNotificationHubSample' 89 | sdk: 'iphoneos' 90 | configuration: 'Release' 91 | xcWorkspacePath: '../sample/ios/ReactNativeAzureNotificationHubSample.xcworkspace' 92 | xcodeVersion: '10' 93 | signingOption: 'nosign' 94 | useXcpretty: 'true' 95 | 96 | - task: Xcode@5 97 | displayName: 'Running iOS unit tests' 98 | inputs: 99 | actions: 'test' 100 | scheme: 'ReactNativeAzureNotificationHubSample' 101 | sdk: 'iphonesimulator' 102 | configuration: 'Debug' 103 | xcWorkspacePath: '../sample/ios/ReactNativeAzureNotificationHubSample.xcworkspace' 104 | xcodeVersion: '10' 105 | signingOption: 'nosign' 106 | useXcpretty: 'true' 107 | destination: 'platform=iOS Simulator, name=iPhone 8' 108 | destinationPlatformOption: 'iOS' 109 | destinationTypeOption: 'simulators' 110 | destinationSimulators: 'iPhone 8' 111 | publishJUnitResults: 'true' 112 | 113 | - script: slather 114 | displayName: 'Running slather' 115 | workingDirectory: '../sample' 116 | 117 | - script: reportgenerator "-reports:*.xml" "-reporttypes:cobertura" "-targetdir:." 118 | displayName: 'Merge Android and iOS reports' 119 | workingDirectory: '../sample' 120 | 121 | - task: PublishCodeCoverageResults@1 122 | inputs: 123 | codeCoverageTool: 'Cobertura' 124 | summaryFileLocation: '../sample/cobertura.xml' 125 | -------------------------------------------------------------------------------- /ios/RCTAzureNotificationHubManager/RCTAzureNotificationHubManager.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 "React/RCTEventEmitter.h" 11 | 12 | #import "RCTAzureNotificationHandler.h" 13 | 14 | @import UserNotifications; 15 | 16 | @interface RCTAzureNotificationHubManager : RCTEventEmitter 17 | 18 | // Invoked from AppDelegate when the app successfully registered with Apple Push Notification service (APNs). 19 | + (void)didRegisterForRemoteNotificationsWithDeviceToken:(nonnull NSData *)deviceToken; 20 | 21 | // Invoked from AppDelegate when APNs cannot successfully complete the registration process. 22 | + (void)didFailToRegisterForRemoteNotificationsWithError:(nonnull NSError *)error; 23 | 24 | // Invoked from AppDelegate when a remote notification arrived and there is data to be fetched. 25 | + (void)didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo 26 | fetchCompletionHandler:(void (__unused ^_Nonnull)(UIBackgroundFetchResult result))completionHandler; 27 | 28 | // Invoked from AppDelegate when a notification arrived while the app was running in the foreground. 29 | + (void)userNotificationCenter:(nonnull __unused UNUserNotificationCenter *)center 30 | willPresentNotification:(nonnull UNNotification *)notification 31 | withCompletionHandler:(void (__unused ^_Nonnull)(UNNotificationPresentationOptions options))completionHandler; 32 | 33 | // Set application icon badge number 34 | - (void)setApplicationIconBadgeNumber:(NSInteger)number; 35 | 36 | // Get application icon badge number 37 | - (void)getApplicationIconBadgeNumber:(nonnull RCTResponseSenderBlock)callback; 38 | 39 | // Request notification permissions 40 | - (void)requestPermissions:(nonnull NSDictionary *)permissions 41 | resolver:(nonnull RCTPromiseResolveBlock)resolve 42 | rejecter:(nonnull RCTPromiseRejectBlock)reject; 43 | 44 | // Abandon notification permissions 45 | - (void)abandonPermissions; 46 | 47 | // Check notification permissions 48 | - (void)checkPermissions:(nonnull RCTResponseSenderBlock)callback; 49 | 50 | // Present local notification 51 | - (void)presentLocalNotification:(nonnull UILocalNotification *)notification; 52 | 53 | // Schedule local notification 54 | - (void)scheduleLocalNotification:(nonnull UILocalNotification *)notification; 55 | 56 | // Cancel all local notifications 57 | - (void)cancelAllLocalNotifications; 58 | 59 | // Cancel local notifications 60 | - (void)cancelLocalNotifications:(nonnull NSDictionary *)userInfo; 61 | 62 | // Get initial notification 63 | - (void)getInitialNotification:(nonnull RCTPromiseResolveBlock)resolve 64 | reject:(nonnull __unused RCTPromiseRejectBlock)reject; 65 | 66 | // Get scheduled local notifications 67 | - (void)getScheduledLocalNotifications:(nonnull RCTResponseSenderBlock)callback; 68 | 69 | // Register with Azure Notification Hub 70 | - (void)register:(nonnull NSString *)deviceToken 71 | config:(nonnull NSDictionary *)config 72 | resolver:(nonnull __unused RCTPromiseResolveBlock)resolve 73 | rejecter:(nonnull RCTPromiseRejectBlock)reject; 74 | 75 | // Register template 76 | - (void)registerTemplate:(nonnull NSString *)deviceToken 77 | config:(nonnull NSDictionary *)config 78 | resolver:(nonnull __unused RCTPromiseResolveBlock)resolve 79 | rejecter:(nonnull RCTPromiseRejectBlock)reject; 80 | 81 | // Unregister with Azure Notification Hub 82 | - (void)unregister:(nonnull RCTPromiseResolveBlock)resolve 83 | rejecter:(nonnull RCTPromiseRejectBlock)reject; 84 | 85 | // Unregister template 86 | - (void)unregisterTemplate:(nonnull NSString *)templateName 87 | resolver:(nonnull RCTPromiseResolveBlock)resolve 88 | rejecter:(nonnull RCTPromiseRejectBlock)reject; 89 | 90 | // Set notification handler 91 | - (void)setNotificationHandler:(nonnull RCTAzureNotificationHandler *)handler; 92 | 93 | @end 94 | -------------------------------------------------------------------------------- /android/src/main/java/com/azure/reactnative/notificationhub/ReactNativeFirebaseMessagingService.java: -------------------------------------------------------------------------------- 1 | package com.azure.reactnative.notificationhub; 2 | 3 | import android.app.NotificationChannel; 4 | import android.app.NotificationManager; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.os.Build; 8 | import android.os.Bundle; 9 | import android.util.Log; 10 | 11 | import com.google.firebase.messaging.FirebaseMessagingService; 12 | import com.google.firebase.messaging.RemoteMessage; 13 | 14 | import static com.azure.reactnative.notificationhub.ReactNativeConstants.*; 15 | 16 | public class ReactNativeFirebaseMessagingService extends FirebaseMessagingService { 17 | 18 | private static final String TAG = "ReactNativeFMS"; 19 | 20 | private static String notificationChannelID; 21 | 22 | public static void createNotificationChannel(Context context) { 23 | if (notificationChannelID == null) { 24 | ReactNativeNotificationHubUtil notificationHubUtil = ReactNativeNotificationHubUtil.getInstance(); 25 | ReactNativeNotificationChannelBuilder builder = ReactNativeNotificationChannelBuilder.Factory.create(); 26 | 27 | if (notificationHubUtil.hasChannelName(context)) { 28 | builder.setName(notificationHubUtil.getChannelName(context)); 29 | } 30 | 31 | if (notificationHubUtil.hasChannelDescription(context)) { 32 | builder.setDescription(notificationHubUtil.getChannelDescription(context)); 33 | } 34 | 35 | if (notificationHubUtil.hasChannelImportance(context)) { 36 | builder.setImportance(notificationHubUtil.getChannelImportance(context)); 37 | } 38 | 39 | if (notificationHubUtil.hasChannelShowBadge(context)) { 40 | builder.setShowBadge(notificationHubUtil.getChannelShowBadge(context)); 41 | } 42 | 43 | if (notificationHubUtil.hasChannelEnableLights(context)) { 44 | builder.enableLights(notificationHubUtil.getChannelEnableLights(context)); 45 | } 46 | 47 | if (notificationHubUtil.hasChannelEnableVibration(context)) { 48 | builder.enableVibration(notificationHubUtil.getChannelEnableVibration(context)); 49 | } 50 | 51 | notificationChannelID = NOTIFICATION_CHANNEL_ID; 52 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 53 | NotificationChannel channel = builder.build(); 54 | NotificationManager notificationManager = (NotificationManager) context.getSystemService( 55 | Context.NOTIFICATION_SERVICE); 56 | if (notificationManager != null) { 57 | notificationManager.createNotificationChannel(channel); 58 | notificationChannelID = channel.getId(); 59 | } 60 | } 61 | } 62 | } 63 | 64 | public static void deleteNotificationChannel(Context context) { 65 | if (notificationChannelID != null) { 66 | final String channelToDeleteID = notificationChannelID; 67 | notificationChannelID = null; 68 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 69 | NotificationManager notificationManager = (NotificationManager) context.getSystemService( 70 | Context.NOTIFICATION_SERVICE); 71 | notificationManager.deleteNotificationChannel(channelToDeleteID); 72 | } 73 | } 74 | } 75 | 76 | @Override 77 | public void onNewToken(String token) { 78 | Log.i(TAG, "Refreshing FCM Registration Token"); 79 | 80 | Intent intent = ReactNativeNotificationHubUtil.IntentFactory.createIntent(this, ReactNativeRegistrationIntentService.class); 81 | ReactNativeRegistrationIntentService.enqueueWork(this, intent); 82 | } 83 | 84 | @Override 85 | public void onMessageReceived(RemoteMessage remoteMessage) { 86 | ReactNativeNotificationHubUtil notificationHubUtil = ReactNativeNotificationHubUtil.getInstance(); 87 | Log.d(TAG, "Remote message from: " + remoteMessage.getFrom()); 88 | 89 | if (notificationChannelID == null) { 90 | createNotificationChannel(this); 91 | } 92 | 93 | Bundle bundle = remoteMessage.toIntent().getExtras(); 94 | if (notificationHubUtil.getAppIsForeground()) { 95 | bundle.putBoolean(KEY_REMOTE_NOTIFICATION_FOREGROUND, true); 96 | bundle.putBoolean(KEY_REMOTE_NOTIFICATION_USER_INTERACTION, false); 97 | bundle.putBoolean(KEY_REMOTE_NOTIFICATION_COLDSTART, false); 98 | } else { 99 | ReactNativeNotificationsHandler.sendNotification(this, bundle, notificationChannelID); 100 | } 101 | 102 | ReactNativeNotificationsHandler.sendBroadcast(this, bundle, 0); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /sample/ios/ReactNativeAzureNotificationHubSampleTests/RCTAzureNotificationHubUtilTests.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #import 9 | #import 10 | 11 | #import 12 | #import 13 | 14 | @import OCMock; 15 | @import UserNotifications; 16 | 17 | @interface RCTAzureNotificationHubUtilTests : XCTestCase 18 | @end 19 | 20 | @implementation RCTAzureNotificationHubUtilTests 21 | 22 | - (void)testFormatUNNotification 23 | { 24 | UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init]; 25 | id notificationRequestMock = OCMClassMock([UNNotificationRequest class]); 26 | OCMStub([notificationRequestMock content]).andReturn(content); 27 | OCMStub([notificationRequestMock identifier]).andReturn( @"identifier"); 28 | id notificationMock = OCMClassMock([UNNotification class]); 29 | OCMStub([notificationMock request]).andReturn(notificationRequestMock); 30 | 31 | NSArray *keys = [NSArray arrayWithObjects:@"userInfoKey", nil]; 32 | NSArray *objects = [NSArray arrayWithObjects:@"userInfoObject", nil]; 33 | NSDictionary *info = [[NSDictionary alloc] initWithObjects:objects forKeys:keys]; 34 | content.title = @"title"; 35 | content.threadIdentifier = @"threadIdentifier"; 36 | content.body = @"body"; 37 | content.badge = @(1); 38 | content.categoryIdentifier = @"category"; 39 | content.sound = @"sound"; 40 | content.userInfo = info; 41 | NSDictionary *expectedNotification = @{ 42 | @"identifier": @"identifier", 43 | @"title": @"title", 44 | @"thread-id": @"threadIdentifier", 45 | @"userInfo": @{ @"userInfoKey": @"userInfoObject" }, 46 | @"alertBody": @"body", 47 | @"applicationIconBadgeNumber": [NSNumber numberWithInt:1], 48 | @"category": @"category", 49 | @"soundName": @"sound" 50 | }; 51 | 52 | NSDictionary *formattedNotification = [RCTAzureNotificationHubUtil formatUNNotification:notificationMock]; 53 | 54 | XCTAssertEqualObjects(formattedNotification, expectedNotification); 55 | } 56 | 57 | - (void)testFormatLocalNotification 58 | { 59 | UILocalNotification *notification = [[UILocalNotification alloc] init]; 60 | NSArray *keys = [NSArray arrayWithObjects:@"userInfoKey", nil]; 61 | NSArray *objects = [NSArray arrayWithObjects:@"userInfoObject", nil]; 62 | NSDictionary *info = [[NSDictionary alloc] initWithObjects:objects forKeys:keys]; 63 | notification.userInfo = info; 64 | notification.alertAction = @"alertAction"; 65 | notification.alertBody = @"alertBody"; 66 | notification.applicationIconBadgeNumber = 1; 67 | notification.category = @"category"; 68 | notification.soundName = @"soundName"; 69 | NSDictionary *expectedNotification = @{ 70 | @"userInfo": @{ @"userInfoKey": @"userInfoObject" }, 71 | @"alertAction": @"alertAction", 72 | @"alertBody": @"alertBody", 73 | @"applicationIconBadgeNumber": [NSNumber numberWithInt:1], 74 | @"category": @"category", 75 | @"soundName": @"soundName", 76 | @"remote": @NO 77 | }; 78 | 79 | NSDictionary *formattedNotification = [RCTAzureNotificationHubUtil formatLocalNotification:notification]; 80 | 81 | XCTAssertEqualObjects(formattedNotification, expectedNotification); 82 | } 83 | 84 | - (void)testConvertDeviceTokenToString 85 | { 86 | NSString *deviceToken = @"Device Token"; 87 | NSData *deviceTokenData = [deviceToken dataUsingEncoding:NSASCIIStringEncoding]; 88 | NSString *expectedString = @"44657669636520546f6b656e"; 89 | 90 | NSString *convertedString = [RCTAzureNotificationHubUtil convertDeviceTokenToString:deviceTokenData]; 91 | 92 | XCTAssertEqualObjects(convertedString, expectedString); 93 | } 94 | 95 | - (void)testGetNotificationTypesWithPermissions 96 | { 97 | NSMutableDictionary *permissions = [[NSMutableDictionary alloc] init]; 98 | XCTAssertEqual([RCTAzureNotificationHubUtil getNotificationTypesWithPermissions:permissions], 0); 99 | 100 | [permissions setValue:@YES forKey:RCTNotificationTypeAlert]; 101 | XCTAssertEqual([RCTAzureNotificationHubUtil getNotificationTypesWithPermissions:permissions], 102 | UNAuthorizationOptionAlert); 103 | 104 | [permissions setValue:@YES forKey:RCTNotificationTypeBadge]; 105 | XCTAssertEqual([RCTAzureNotificationHubUtil getNotificationTypesWithPermissions:permissions], 106 | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge); 107 | 108 | [permissions setValue:@YES forKey:RCTNotificationTypeSound]; 109 | XCTAssertEqual([RCTAzureNotificationHubUtil getNotificationTypesWithPermissions:permissions], 110 | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge | UNAuthorizationOptionSound); 111 | } 112 | 113 | @end 114 | -------------------------------------------------------------------------------- /sample/android/app/jacoco.gradle: -------------------------------------------------------------------------------- 1 | /** 2 | * h8MyJob / PowerMockJacocoDemo 3 | * 4 | * https://github.com/h8MyJob/PowerMockJacocoDemo/wiki 5 | * https://stackoverflow.com/questions/53071373/powermock-jacoco-gradle-0-coverage-for-android-project 6 | * 7 | */ 8 | 9 | apply plugin: "jacoco" 10 | 11 | configurations { 12 | jacocoAnt 13 | jacocoRuntime 14 | } 15 | 16 | jacoco { 17 | toolVersion = "0.8.1" 18 | } 19 | 20 | def offline_instrumented_outputDir = "$buildDir.path/intermediates/classes-instrumented/debug" 21 | 22 | tasks.withType(Test) { 23 | jacoco.includeNoLocationClasses = true 24 | } 25 | 26 | def coverageSourceDirs = [ 27 | "../../node_modules/react-native-azurenotificationhub/android/src/main/java" 28 | ] 29 | 30 | task jacocoTestReport(type: JacocoReport, dependsOn: "test") { 31 | group = "Reporting" 32 | 33 | description = "Generate Jacoco coverage reports" 34 | 35 | getClassDirectories().setFrom(fileTree( 36 | dir: "../../node_modules/react-native-azurenotificationhub/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes", 37 | excludes: ['**/R.class', 38 | '**/R$*.class', 39 | '**/BuildConfig.*', 40 | '**/MainActivity.*']) 41 | ) 42 | 43 | getSourceDirectories().setFrom(files(coverageSourceDirs)) 44 | getExecutionData().setFrom(files("build/jacoco/testDebugUnitTest.exec")) 45 | } 46 | 47 | jacocoTestReport { 48 | reports { 49 | xml.enabled true 50 | xml.destination file("../../jacocoXml.xml") 51 | html.enabled true 52 | html.destination file("build/test-results/jacocoHtml") 53 | } 54 | } 55 | 56 | /* This task is used to create offline instrumentation of classes for on-the-fly instrumentation coverage tool like Jacoco. See jacoco classId 57 | * and Offline Instrumentation from the jacoco site for more info. 58 | * 59 | * In this case, some classes mocked using PowerMock were reported as 0% coverage on jacoco & Sonarqube. The issue between PowerMock and jacoco 60 | * is well documented, and a possible solution is offline Instrumentation (not so well documented for gradle). 61 | * 62 | * In a nutshell, this task: 63 | * - Pre-instruments the original *.class files 64 | * - Puts the instrumented classes path at the beginning of the task's classpath (for report purposes) 65 | * - Runs test & generates a new exec file based on the pre-instrumented classes -- as opposed to on-the-fly instrumented class files generated by jacoco. 66 | * 67 | * It is currently not implemented to run prior to any other existing tasks (like test, jacocoTestReport, etc...), therefore, it should be called 68 | * explicitly if Offline Instrumentation report is needed. 69 | * 70 | * Usage: gradle clean & gradle createOfflineInstrTestCoverageReport & gradle jacocoTestReport 71 | * - gradle clean //To prevent influence from any previous task execution 72 | * - gradle createOfflineInstrTestCoverageReport //To generate *.exec file from offline instrumented class 73 | * - gradle jacocoTestReport //To generate html report from newly created *.exec task 74 | */ 75 | task createOfflineTestCoverageReport(dependsOn: ["instrument", "testDebugUnitTest"]) { 76 | doLast { 77 | ant.taskdef(name: "report", 78 | classname: "org.jacoco.ant.ReportTask", 79 | classpath: configurations.jacocoAnt.asPath) 80 | ant.report() { 81 | executiondata { 82 | ant.file(file: "$buildDir.path/jacoco/testDebugUnitTest.exec") 83 | } 84 | structure(name: "React Native Azure Notification Hub Sample") { 85 | classfiles { 86 | fileset(dir: "$project.buildDir/intermediates/javac/debug/compileDebugJavaWithJavac/classes") 87 | } 88 | sourcefiles { 89 | fileset(dir: "../../node_modules/react-native-azurenotificationhub/android/src/main/java") 90 | } 91 | } 92 | } 93 | } 94 | } 95 | 96 | /* 97 | * Part of the Offline Instrumentation process is to add the jacoco runtime to the class path along with the path of the instrumented files. 98 | */ 99 | gradle.taskGraph.whenReady { graph -> 100 | if (graph.hasTask(instrument)) { 101 | tasks.withType(Test) { 102 | doFirst { 103 | systemProperty "jacoco-agent.destfile", buildDir.path + "/jacoco/testDebugUnitTest.exec" 104 | classpath = files(offline_instrumented_outputDir) + classpath + configurations.jacocoRuntime 105 | } 106 | } 107 | } 108 | } 109 | 110 | /* 111 | * Instruments the classes per se 112 | */ 113 | task instrument(dependsOn: "compileDebugUnitTestSources") { 114 | doLast { 115 | println "Instrumenting classes" 116 | 117 | ant.taskdef(name: "instrument", 118 | classname: "org.jacoco.ant.InstrumentTask", 119 | classpath: configurations.jacocoAnt.asPath) 120 | 121 | ant.instrument(destdir: offline_instrumented_outputDir) { 122 | fileset(dir: "$buildDir.path/intermediates/javac/debug/compileDebugJavaWithJavac/classes") 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /ios/RCTAzureNotificationHubManager/RCTAzureNotificationHubUtil.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 "React/RCTConvert.h" 11 | #import "React/RCTUtils.h" 12 | 13 | #import "RCTAzureNotificationHub.h" 14 | #import "RCTAzureNotificationHubUtil.h" 15 | 16 | @implementation RCTAzureNotificationHubUtil 17 | 18 | // Format UNNotification 19 | + (nonnull NSDictionary *)formatUNNotification:(nonnull UNNotification *)notification 20 | { 21 | NSMutableDictionary *formattedNotification = [NSMutableDictionary dictionary]; 22 | UNNotificationContent *content = notification.request.content; 23 | 24 | formattedNotification[@"identifier"] = notification.request.identifier; 25 | 26 | if (notification.date) 27 | { 28 | NSDateFormatter *formatter = [NSDateFormatter new]; 29 | [formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"]; 30 | NSString *dateString = [formatter stringFromDate:notification.date]; 31 | formattedNotification[@"date"] = dateString; 32 | } 33 | 34 | formattedNotification[@"title"] = RCTNullIfNil(content.title); 35 | formattedNotification[@"thread-id"] = RCTNullIfNil(content.threadIdentifier); 36 | formattedNotification[@"alertBody"] = RCTNullIfNil(content.body); 37 | formattedNotification[@"applicationIconBadgeNumber"] = RCTNullIfNil(content.badge); 38 | formattedNotification[@"category"] = RCTNullIfNil(content.categoryIdentifier); 39 | formattedNotification[@"soundName"] = RCTNullIfNil(content.sound); 40 | formattedNotification[@"userInfo"] = RCTNullIfNil(RCTJSONClean(content.userInfo)); 41 | 42 | return formattedNotification; 43 | } 44 | 45 | // Format local notification 46 | + (nonnull NSDictionary *)formatLocalNotification:(nonnull UILocalNotification *)notification 47 | { 48 | NSMutableDictionary *formattedLocalNotification = [NSMutableDictionary dictionary]; 49 | if (notification.fireDate) 50 | { 51 | NSDateFormatter *formatter = [NSDateFormatter new]; 52 | [formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"]; 53 | NSString *fireDateString = [formatter stringFromDate:notification.fireDate]; 54 | formattedLocalNotification[@"fireDate"] = fireDateString; 55 | } 56 | 57 | formattedLocalNotification[@"alertAction"] = RCTNullIfNil(notification.alertAction); 58 | formattedLocalNotification[@"alertBody"] = RCTNullIfNil(notification.alertBody); 59 | formattedLocalNotification[@"applicationIconBadgeNumber"] = @(notification.applicationIconBadgeNumber); 60 | formattedLocalNotification[@"category"] = RCTNullIfNil(notification.category); 61 | formattedLocalNotification[@"soundName"] = RCTNullIfNil(notification.soundName); 62 | formattedLocalNotification[@"userInfo"] = RCTNullIfNil(RCTJSONClean(notification.userInfo)); 63 | formattedLocalNotification[@"remote"] = @NO; 64 | return formattedLocalNotification; 65 | } 66 | 67 | // Create Azure Notification Hub 68 | + (nonnull SBNotificationHub *)createAzureNotificationHub:(nonnull NSString *)connectionString 69 | hubName:(nonnull NSString *)hubName 70 | { 71 | SBNotificationHub *hub = [[SBNotificationHub alloc] initWithConnectionString:connectionString 72 | notificationHubPath:hubName]; 73 | 74 | return hub; 75 | } 76 | 77 | // Convert device token to string 78 | + (nonnull NSString *)convertDeviceTokenToString:(nonnull NSData *)deviceToken 79 | { 80 | NSMutableString *hexString = [NSMutableString string]; 81 | NSUInteger deviceTokenLength = deviceToken.length; 82 | const unsigned char *bytes = deviceToken.bytes; 83 | for (NSUInteger i = 0; i < deviceTokenLength; i++) 84 | { 85 | [hexString appendFormat:@"%02x", bytes[i]]; 86 | } 87 | 88 | return hexString; 89 | } 90 | 91 | // Get notification types with permissions 92 | + (UNAuthorizationOptions)getNotificationTypesWithPermissions:(nullable NSDictionary *)permissions 93 | { 94 | UNAuthorizationOptions types = 0; 95 | if (permissions) 96 | { 97 | if ([RCTConvert BOOL:permissions[RCTNotificationTypeAlert]]) 98 | { 99 | types |= UNAuthorizationOptionAlert; 100 | } 101 | 102 | if ([RCTConvert BOOL:permissions[RCTNotificationTypeBadge]]) 103 | { 104 | types |= UNAuthorizationOptionBadge; 105 | } 106 | 107 | if ([RCTConvert BOOL:permissions[RCTNotificationTypeSound]]) 108 | { 109 | types |= UNAuthorizationOptionSound; 110 | } 111 | } 112 | else 113 | { 114 | types = UNAuthorizationOptionAlert | UNAuthorizationOptionBadge | UNAuthorizationOptionSound; 115 | } 116 | 117 | return types; 118 | } 119 | 120 | // Run block on the main thread 121 | + (void)runOnMainThread:(nonnull dispatch_block_t)block 122 | { 123 | dispatch_async(dispatch_get_main_queue(), block); 124 | } 125 | 126 | @end 127 | -------------------------------------------------------------------------------- /windows/.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | *.VC.VC.opendb 85 | 86 | # Visual Studio profiler 87 | *.psess 88 | *.vsp 89 | *.vspx 90 | *.sap 91 | 92 | # TFS 2012 Local Workspace 93 | $tf/ 94 | 95 | # Guidance Automation Toolkit 96 | *.gpState 97 | 98 | # ReSharper is a .NET coding add-in 99 | _ReSharper*/ 100 | *.[Rr]e[Ss]harper 101 | *.DotSettings.user 102 | 103 | # JustCode is a .NET coding add-in 104 | .JustCode 105 | 106 | # TeamCity is a build add-in 107 | _TeamCity* 108 | 109 | # DotCover is a Code Coverage Tool 110 | *.dotCover 111 | 112 | # NCrunch 113 | _NCrunch_* 114 | .*crunch*.local.xml 115 | nCrunchTemp_* 116 | 117 | # MightyMoose 118 | *.mm.* 119 | AutoTest.Net/ 120 | 121 | # Web workbench (sass) 122 | .sass-cache/ 123 | 124 | # Installshield output folder 125 | [Ee]xpress/ 126 | 127 | # DocProject is a documentation generator add-in 128 | DocProject/buildhelp/ 129 | DocProject/Help/*.HxT 130 | DocProject/Help/*.HxC 131 | DocProject/Help/*.hhc 132 | DocProject/Help/*.hhk 133 | DocProject/Help/*.hhp 134 | DocProject/Help/Html2 135 | DocProject/Help/html 136 | 137 | # Click-Once directory 138 | publish/ 139 | 140 | # Publish Web Output 141 | *.[Pp]ublish.xml 142 | *.azurePubxml 143 | # TODO: Comment the next line if you want to checkin your web deploy settings 144 | # but database connection strings (with potential passwords) will be unencrypted 145 | *.pubxml 146 | *.publishproj 147 | 148 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 149 | # checkin your Azure Web App publish settings, but sensitive information contained 150 | # in these scripts will be unencrypted 151 | PublishScripts/ 152 | 153 | # NuGet Packages 154 | *.nupkg 155 | # The packages folder can be ignored because of Package Restore 156 | **/packages/* 157 | # except build/, which is used as an MSBuild target. 158 | !**/packages/build/ 159 | # Uncomment if necessary however generally it will be regenerated when needed 160 | #!**/packages/repositories.config 161 | # NuGet v3's project.json files produces more ignoreable files 162 | *.nuget.props 163 | *.nuget.targets 164 | 165 | # Microsoft Azure Build Output 166 | csx/ 167 | *.build.csdef 168 | 169 | # Microsoft Azure Emulator 170 | ecf/ 171 | rcf/ 172 | 173 | # Windows Store app package directories and files 174 | AppPackages/ 175 | BundleArtifacts/ 176 | Package.StoreAssociation.xml 177 | _pkginfo.txt 178 | 179 | # Visual Studio cache files 180 | # files ending in .cache can be ignored 181 | *.[Cc]ache 182 | # but keep track of directories ending in .cache 183 | !*.[Cc]ache/ 184 | 185 | # Others 186 | ClientBin/ 187 | ~$* 188 | *~ 189 | *.dbmdl 190 | *.dbproj.schemaview 191 | *.pfx 192 | *.publishsettings 193 | node_modules/ 194 | orleans.codegen.cs 195 | 196 | # Since there are multiple workflows, uncomment next line to ignore bower_components 197 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 198 | #bower_components/ 199 | 200 | # RIA/Silverlight projects 201 | Generated_Code/ 202 | 203 | # Backup & report files from converting an old project file 204 | # to a newer Visual Studio version. Backup files are not needed, 205 | # because we have git ;-) 206 | _UpgradeReport_Files/ 207 | Backup*/ 208 | UpgradeLog*.XML 209 | UpgradeLog*.htm 210 | 211 | # SQL Server files 212 | *.mdf 213 | *.ldf 214 | 215 | # Business Intelligence projects 216 | *.rdl.data 217 | *.bim.layout 218 | *.bim_*.settings 219 | 220 | # Microsoft Fakes 221 | FakesAssemblies/ 222 | 223 | # GhostDoc plugin setting file 224 | *.GhostDoc.xml 225 | 226 | # Node.js Tools for Visual Studio 227 | .ntvs_analysis.dat 228 | 229 | # Visual Studio 6 build log 230 | *.plg 231 | 232 | # Visual Studio 6 workspace options file 233 | *.opt 234 | 235 | # Visual Studio LightSwitch build output 236 | **/*.HTMLClient/GeneratedArtifacts 237 | **/*.DesktopClient/GeneratedArtifacts 238 | **/*.DesktopClient/ModelManifest.xml 239 | **/*.Server/GeneratedArtifacts 240 | **/*.Server/ModelManifest.xml 241 | _Pvt_Extensions 242 | 243 | # Paket dependency manager 244 | .paket/paket.exe 245 | paket-files/ 246 | 247 | # FAKE - F# Make 248 | .fake/ 249 | 250 | # JetBrains Rider 251 | .idea/ 252 | *.sln.iml 253 | -------------------------------------------------------------------------------- /docs/windows-installation.md: -------------------------------------------------------------------------------- 1 | # Windows Installation Guide 2 | 3 | ## Prerequisites 4 | 5 | The documentation that follows assumes you have generated a React Native Windows project using the `react-native-cli` and `rnpm-plugin-windows`, i.e.: 6 | 7 | ``` 8 | react-native init myapp 9 | cd myapp 10 | npm i --save-dev rnpm-plugin-windows 11 | react-native windows 12 | ``` 13 | 14 | It also assumes you have Visual Studio 2015 installed ([Visual Studio Community](https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspx) is fine). 15 | 16 | ## Install react-native-azurenotificationhub 17 | 18 | ``` 19 | npm install react-native-azurenotificationhub 20 | ``` 21 | 22 | ## Create a Notification Hub 23 | 24 | * Log on to the [Azure Portal](https://portal.azure.com) and create a new **Notification Hub**. 25 | 26 | ![Create Notification Hub](img/CreateNotificationHub.png) 27 | 28 | ## Associate your app with the Windows Store 29 | 30 | * Open your Visual Studio .sln (generally ./windows/[app name].sln) file in Visual Studio 2015. 31 | * In Solution Explorer, right-click the Windows Store app project, click **Store**, and then click **Associate App with the Store...** 32 | 33 | ![Associate with App Store](img/AssociateAppStore.png) 34 | 35 | * Follow the instructions to login, reserve an app name, associate the app with the app name, and automatically configure the required Windows Store registration in the application manifest. 36 | 37 | ## Register app with Notification Hub 38 | 39 | * On the [Windows Dev Center](https://dev.windows.com/overview) page for your new app, click **Services**, click **Push notifications**, and then click **Live Services site** under **Windows Push Notification Services (WNS) and Microsoft Azure Mobile Apps**. 40 | 41 | ![Live Services Site](img/LiveServicesSite.png) 42 | 43 | * On the registration page for your app, make a note of the **Application Secret** password and the **Package security identifier** (SID) located in the Windows Store platform settings. 44 | 45 | ![Application Secrets](img/ApplicationSecrets.png) 46 | 47 | * Back on the [Azure Portal](https://portal.azure.com) page for your notification hub, select **Settings > Notification Services > Windows (WNS)**. Then enter the **Application Secret** password in the Security Key field. Enter your **Package SID** value that you obtained from WNS in the previous section, and then click **Save**. 48 | 49 | ![Configure WNS](./img/ConfigureWNS.png) 50 | 51 | ## Export React Native Module from app 52 | 53 | * In Solution Explorer of your open .sln in Visual Studio 2015, right-click the Solution, click **Add > Existing Project...**. 54 | 55 | ![Add Existing Project](./img/AddExistingProject.png) 56 | 57 | * Assuming you've already installed `react-native-azurenotificationhub` with NPM, find and select `ReactWindowsAzureNotificationHub.csproj` in `.\node_modules\react-native-azurenotificationhub\windows\ReactWindowsAzureNotificationHub`. 58 | * Right-click the Windows Store app project, click ** Add > Reference**, and check `ReactWindowsAzureNotificationHub` from **Projects > Solution**. 59 | 60 | ![Add Reference](./img/AddReference.png) 61 | 62 | * In **MainPage.cs** of your Windows Store app, add the the `ReactAzureNotificationHubPacakge` to your configured set of packages: 63 | 64 | ```c# 65 | using ReactWindowsAzureNotificationHub; 66 | 67 | namespace ... 68 | { 69 | public class MainPage : ReactPage 70 | { 71 | ... 72 | 73 | public override List Packages 74 | { 75 | get 76 | { 77 | new List 78 | { 79 | new MainReactPackage(), 80 | new ReactAzureNotificationHubPackage(), // <-- Add this package 81 | } 82 | } 83 | } 84 | 85 | ... 86 | } 87 | } 88 | ``` 89 | 90 | ## JavaScript Configuration 91 | 92 | On the [Azure Portal](https://portal.azure.com) page for your notification hub, copy a connection string from **Settings > Access Policies**. 93 | 94 | ![Get Connection String](img/GetConnectionString.png) 95 | 96 | The example below shows how you can register and unregister from Azure Notification Hub in your React component. 97 | 98 | ```js 99 | const NotificationHub = require('react-native-azurenotificationhub'); 100 | 101 | const connectionString = '...'; // The Notification Hub connection string 102 | const hubName = '...'; // The Notification Hub name 103 | const senderID = '...'; // The Sender ID from the Cloud Messaging tab of the Firebase console 104 | const tags = [ ... ]; // The set of tags to subscribe to 105 | 106 | class myapp extends Component { 107 | register() { 108 | NotificationHub.register({connectionString, hubName, senderID, tags}) 109 | .catch(reason => console.warn(reason)); 110 | } 111 | 112 | unregister() { 113 | NotificationHub.unregister() 114 | .catch(reason => console.warn(reason)); 115 | } 116 | 117 | render() { 118 | return ( 119 | 120 | 121 | 122 | 123 | Register 124 | 125 | 126 | 127 | 128 | 129 | 130 | Unregister 131 | 132 | 133 | 134 | 135 | ); 136 | } 137 | ``` 138 | -------------------------------------------------------------------------------- /sample/ios/ReactNativeAzureNotificationHubSampleTests/RCTAzureNotificationHandlerTests.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #import 9 | 10 | #import 11 | #import 12 | #import 13 | 14 | #import "React/RCTEventEmitter.h" 15 | 16 | @import OCMock; 17 | 18 | @interface RCTAzureNotificationHandlerTests : XCTestCase 19 | @end 20 | 21 | @implementation RCTAzureNotificationHandlerTests 22 | { 23 | @private 24 | RCTAzureNotificationHandler *_notificationHandler; 25 | NSMutableDictionary *_userInfo; 26 | id _eventEmitter; 27 | } 28 | 29 | - (void)setUp 30 | { 31 | [super setUp]; 32 | 33 | _eventEmitter = OCMClassMock([RCTEventEmitter class]); 34 | _notificationHandler = [[RCTAzureNotificationHandler alloc] initWithEventEmitter:_eventEmitter]; 35 | NSArray *keys = [NSArray arrayWithObjects:@"userInfoKey", nil]; 36 | NSArray *objects = [NSArray arrayWithObjects:@"userInfoObject", nil]; 37 | _userInfo = [[NSMutableDictionary alloc] initWithObjects:objects forKeys:keys]; 38 | } 39 | 40 | - (void)testLocalNotificationReceived 41 | { 42 | NSNotification* notification = [NSNotification notificationWithName:@"Notification" object:_userInfo userInfo:_userInfo]; 43 | 44 | [_notificationHandler localNotificationReceived:notification]; 45 | 46 | OCMVerify([_eventEmitter sendEventWithName:RCTLocalNotificationReceived 47 | body:_userInfo]); 48 | } 49 | 50 | - (void)testRemoteNotificationReceived 51 | { 52 | NSNotification* notification = [NSNotification notificationWithName:@"Notification" object:_userInfo userInfo:_userInfo]; 53 | _userInfo[RCTUserInfoRemote] = @YES; 54 | 55 | [_notificationHandler remoteNotificationReceived:notification]; 56 | 57 | OCMVerify([_eventEmitter sendEventWithName:RCTRemoteNotificationReceived 58 | body:_userInfo]); 59 | } 60 | 61 | - (void)testRemoteNotificationRegistered 62 | { 63 | NSNotification* notification = [NSNotification notificationWithName:@"Notification" object:_userInfo userInfo:_userInfo]; 64 | 65 | [_notificationHandler remoteNotificationRegistered:notification]; 66 | 67 | OCMVerify([_eventEmitter sendEventWithName:RCTRemoteNotificationRegistered 68 | body:_userInfo]); 69 | } 70 | 71 | - (void)testRemoteNotificationRegisteredError 72 | { 73 | NSDictionary *errorUserInfo = [[NSDictionary alloc] 74 | initWithObjectsAndKeys:NSLocalizedDescriptionKey, NSLocalizedDescriptionKey, nil]; 75 | 76 | NSError* error = [NSError errorWithDomain:@"Error domain" 77 | code:100 78 | userInfo:errorUserInfo]; 79 | 80 | NSArray *keys = [NSArray arrayWithObjects:RCTUserInfoError, nil]; 81 | NSArray *objects = [NSArray arrayWithObjects:error, nil]; 82 | NSDictionary *userInfo = [[NSMutableDictionary alloc] initWithObjects:objects forKeys:keys]; 83 | NSNotification* notification = [NSNotification notificationWithName:@"Notification" object:userInfo userInfo:userInfo]; 84 | NSDictionary *expectedErrorDetails = @{ 85 | @"message": NSLocalizedDescriptionKey, 86 | @"code": [NSNumber numberWithInt:100], 87 | @"details": errorUserInfo 88 | }; 89 | 90 | [_notificationHandler remoteNotificationRegisteredError:notification]; 91 | 92 | OCMVerify([_eventEmitter sendEventWithName:RCTRemoteNotificationRegisteredError 93 | body:expectedErrorDetails]); 94 | } 95 | 96 | - (void)testAzureNotificationHubRegistered 97 | { 98 | NSNotification* notification = [NSNotification notificationWithName:@"Notification" object:_userInfo userInfo:_userInfo]; 99 | 100 | [_notificationHandler azureNotificationHubRegistered:notification]; 101 | 102 | OCMVerify([_eventEmitter sendEventWithName:RCTAzureNotificationHubRegistered 103 | body:_userInfo]); 104 | } 105 | 106 | - (void)testAzureNotificationHubRegisteredError 107 | { 108 | NSDictionary *errorUserInfo = [[NSDictionary alloc] 109 | initWithObjectsAndKeys:NSLocalizedDescriptionKey, NSLocalizedDescriptionKey, nil]; 110 | 111 | NSError* error = [NSError errorWithDomain:@"Error domain" 112 | code:100 113 | userInfo:errorUserInfo]; 114 | 115 | NSArray *keys = [NSArray arrayWithObjects:RCTUserInfoError, nil]; 116 | NSArray *objects = [NSArray arrayWithObjects:error, nil]; 117 | NSDictionary *userInfo = [[NSMutableDictionary alloc] initWithObjects:objects forKeys:keys]; 118 | NSNotification* notification = [NSNotification notificationWithName:@"Notification" object:userInfo userInfo:userInfo]; 119 | NSDictionary *expectedErrorDetails = @{ 120 | @"message": NSLocalizedDescriptionKey, 121 | @"code": [NSNumber numberWithInt:100], 122 | @"details": errorUserInfo 123 | }; 124 | 125 | [_notificationHandler azureNotificationHubRegisteredError:notification]; 126 | 127 | OCMVerify([_eventEmitter sendEventWithName:RCTAzureNotificationHubRegisteredError 128 | body:expectedErrorDetails]); 129 | } 130 | 131 | @end 132 | -------------------------------------------------------------------------------- /index.ios.d.ts: -------------------------------------------------------------------------------- 1 | declare namespace IOSNotification { 2 | export interface RegistrationInfo { 3 | success: boolean; 4 | registrationId?: string; 5 | } 6 | 7 | export interface RegistrationConfig { 8 | connectionString: string; 9 | hubName: string; 10 | tags?: string[]; 11 | } 12 | 13 | export interface IOSAlert { 14 | body?: string; 15 | action?: string; 16 | title?: string; 17 | hasAction?: boolean; 18 | alertLaunchImage?: string; 19 | category?: string; 20 | 21 | [key: string]: any; 22 | } 23 | 24 | export interface TemplateRegistrationConfig extends RegistrationConfig { 25 | // JSON serialized template 26 | template: string; 27 | // Unique name for this template 28 | templateName: string; 29 | } 30 | 31 | export interface RegistrationError { 32 | message: string; 33 | code: number; 34 | details: any; 35 | } 36 | 37 | export interface AllowedPermissions { 38 | alert: boolean; 39 | badge: boolean; 40 | sound: boolean; 41 | } 42 | 43 | type NotificationUserInfo = {[key: string]: string | number | null}; 44 | type PushNotificationEventName = 45 | /** 46 | * Fired when a remote notification is received. The handler will be invoked 47 | * with an instance of `IOSNotification`. 48 | */ 49 | 'notification' | 50 | /** 51 | * Fired when a local notification is received. The handler will be invoked 52 | * with an instance of `IOSNotification`. 53 | */ 54 | 'localNotification' | 55 | /** 56 | * Fired when the user registers for remote notifications. The handler will be 57 | * invoked with a hex string representing the deviceToken. 58 | */ 59 | 'register' | 60 | /** 61 | * Fired when the user fails to register for remote notifications. Typically 62 | * occurs when APNS is having issues, or the device is a simulator. The 63 | * handler will be invoked with {message: string, code: number, details: any}. 64 | */ 65 | 'registrationError' | 66 | /** 67 | * Fired when the user registers for Azure notification hub. The handler will be 68 | * invoked with the connection string and hub name. 69 | */ 70 | 'registerAzureNotificationHub' | 71 | /** 72 | * Fired when the user fails to register for Azure notification hub. 73 | */ 74 | 'azureNotificationHubRegistrationError'; 75 | 76 | interface LocalNotification { 77 | alertBody: string; 78 | alertAction: string; 79 | soundName?: string; 80 | category?: string; 81 | userInfo?: NotificationUserInfo; 82 | applicationIconBadgeNumber?: number; 83 | remote?: boolean; 84 | } 85 | 86 | interface FutureLocalNotification extends LocalNotification { 87 | fireDate: Date; 88 | } 89 | } 90 | // TODO: Generic the data if possible. Figure out registrationInfo 91 | 92 | declare class IOSNotification { 93 | private _data: any; 94 | private _alert: string | IOSNotification.IOSAlert; 95 | private _sound: string; 96 | private _badgeCount: number; 97 | private _category: string; 98 | 99 | static presentLocalNotification(details: IOSNotification.LocalNotification): void; 100 | static scheduleLocalNotification(details: IOSNotification.FutureLocalNotification): void; 101 | static cancelAllLocalNotifications(): void; 102 | static setApplicationIconBadgeNumber(number: number): void; 103 | static getApplicationIconBadgeNumber(callback: (number) => void): void; 104 | static cancelLocalNotifications(userInfo?: Partial): void; 105 | static getScheduledLocalNotifications(callback: (notifications: IOSNotification.FutureLocalNotification[]) => void): void; 106 | 107 | static addEventListener(name: 'notification', cb: (notification: IOSNotification) => void): void; 108 | static addEventListener(name: 'localNotification', cb: (notification: IOSNotification) => void): void; 109 | static addEventListener(name: 'register', cb: (deviceToken: string) => void): void; 110 | static addEventListener(name: 'registrationError', cb: (err: IOSNotification.RegistrationError) => void): void; 111 | static addEventListener(name: 'registerAzureNotificationHub', cb: (registrationInfo: IOSNotification.RegistrationInfo) => void): void; 112 | static addEventListener(name: 'azureNotificationHubRegistrationError', cb: (err: IOSNotification.RegistrationError) => void): void; 113 | static removeEventListener(type: IOSNotification.PushNotificationEventName, handler: Function): void; 114 | 115 | static requestPermissions(permissions?: Partial): Promise; 116 | static abandonPermissions(): void; 117 | static checkPermissions(callback: (permissions: IOSNotification.AllowedPermissions) => void): void; 118 | 119 | static register(deviceToken: string, config: IOSNotification.RegistrationConfig): void; 120 | static registerTemplate(deviceToken: string, config: IOSNotification.TemplateRegistrationConfig): void; 121 | static unregister(): Promise; 122 | static unregisterTemplate(templateName: string): Promise; 123 | 124 | static getInitialNotification(): Promise; 125 | 126 | public getAlert(): string | IOSNotification.IOSAlert; 127 | public getMessage(): string | IOSNotification.IOSAlert; 128 | public getSound(): string; 129 | public getBadgeCount(): number; 130 | public getCategory(): string; 131 | public getData(): any; 132 | } 133 | 134 | export = IOSNotification; 135 | -------------------------------------------------------------------------------- /sample/ios/ReactNativeAzureNotificationHubSample.xcodeproj/xcshareddata/xcschemes/ReactNativeAzureNotificationHubSample-tvOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 43 | 49 | 50 | 51 | 52 | 53 | 58 | 59 | 61 | 67 | 68 | 69 | 70 | 71 | 77 | 78 | 79 | 80 | 81 | 82 | 92 | 94 | 100 | 101 | 102 | 103 | 104 | 105 | 111 | 113 | 119 | 120 | 121 | 122 | 124 | 125 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /sample/cover2cover.py: -------------------------------------------------------------------------------- 1 | # https://github.com/rix0rrr/cover2cover 2 | 3 | #!/usr/bin/env python 4 | import sys 5 | import xml.etree.ElementTree as ET 6 | import re 7 | import os.path 8 | 9 | # branch-rate="0.0" complexity="0.0" line-rate="1.0" 10 | # branch="true" hits="1" number="86" 11 | 12 | def find_lines(j_package, filename): 13 | """Return all elements for a given source file in a package.""" 14 | lines = list() 15 | sourcefiles = j_package.findall("sourcefile") 16 | for sourcefile in sourcefiles: 17 | if sourcefile.attrib.get("name") == os.path.basename(filename): 18 | lines = lines + sourcefile.findall("line") 19 | return lines 20 | 21 | def line_is_after(jm, start_line): 22 | return int(jm.attrib.get('line', 0)) > start_line 23 | 24 | def method_lines(jmethod, jmethods, jlines): 25 | """Filter the lines from the given set of jlines that apply to the given jmethod.""" 26 | start_line = int(jmethod.attrib.get('line', 0)) 27 | larger = list(int(jm.attrib.get('line', 0)) for jm in jmethods if line_is_after(jm, start_line)) 28 | end_line = min(larger) if len(larger) else 99999999 29 | 30 | for jline in jlines: 31 | if start_line <= int(jline.attrib['nr']) < end_line: 32 | yield jline 33 | 34 | def convert_lines(j_lines, into): 35 | """Convert the JaCoCo elements into Cobertura elements, add them under the given element.""" 36 | c_lines = ET.SubElement(into, 'lines') 37 | for jline in j_lines: 38 | mb = int(jline.attrib['mb']) 39 | cb = int(jline.attrib['cb']) 40 | ci = int(jline.attrib['ci']) 41 | 42 | cline = ET.SubElement(c_lines, 'line') 43 | cline.set('number', jline.attrib['nr']) 44 | cline.set('hits', '1' if ci > 0 else '0') # Probably not true but no way to know from JaCoCo XML file 45 | 46 | if mb + cb > 0: 47 | percentage = str(int(100 * (float(cb) / (float(cb) + float(mb))))) + '%' 48 | cline.set('branch', 'true') 49 | cline.set('condition-coverage', percentage + ' (' + str(cb) + '/' + str(cb + mb) + ')') 50 | 51 | cond = ET.SubElement(ET.SubElement(cline, 'conditions'), 'condition') 52 | cond.set('number', '0') 53 | cond.set('type', 'jump') 54 | cond.set('coverage', percentage) 55 | else: 56 | cline.set('branch', 'false') 57 | 58 | def guess_filename(path_to_class): 59 | m = re.match('([^$]*)', path_to_class) 60 | return (m.group(1) if m else path_to_class) + '.java' 61 | 62 | def add_counters(source, target): 63 | target.set('line-rate', counter(source, 'LINE')) 64 | target.set('branch-rate', counter(source, 'BRANCH')) 65 | target.set('complexity', counter(source, 'COMPLEXITY', sum)) 66 | 67 | def fraction(covered, missed): 68 | return covered / (covered + missed) 69 | 70 | def sum(covered, missed): 71 | return covered + missed 72 | 73 | def counter(source, type, operation=fraction): 74 | cs = source.findall('counter') 75 | c = next((ct for ct in cs if ct.attrib.get('type') == type), None) 76 | 77 | if c is not None: 78 | covered = float(c.attrib['covered']) 79 | missed = float(c.attrib['missed']) 80 | 81 | return str(operation(covered, missed)) 82 | else: 83 | return '0.0' 84 | 85 | def convert_method(j_method, j_lines): 86 | c_method = ET.Element('method') 87 | c_method.set('name', j_method.attrib['name']) 88 | c_method.set('signature', j_method.attrib['desc']) 89 | 90 | add_counters(j_method, c_method) 91 | convert_lines(j_lines, c_method) 92 | 93 | return c_method 94 | 95 | def convert_class(j_class, j_package): 96 | c_class = ET.Element('class') 97 | c_class.set('name', j_class.attrib['name'].replace('/', '.')) 98 | 99 | # Append absolute path so that Azure Pipelines can display code coverage properly 100 | c_class.set('filename', os.path.dirname(os.path.abspath(__file__)) + '/node_modules/react-native-azurenotificationhub/android/src/main/java/' + guess_filename(j_class.attrib['name'])) 101 | 102 | all_j_lines = list(find_lines(j_package, c_class.attrib['filename'])) 103 | 104 | c_methods = ET.SubElement(c_class, 'methods') 105 | all_j_methods = list(j_class.findall('method')) 106 | for j_method in all_j_methods: 107 | j_method_lines = method_lines(j_method, all_j_methods, all_j_lines) 108 | c_methods.append(convert_method(j_method, j_method_lines)) 109 | 110 | add_counters(j_class, c_class) 111 | convert_lines(all_j_lines, c_class) 112 | 113 | return c_class 114 | 115 | def convert_package(j_package): 116 | c_package = ET.Element('package') 117 | c_package.attrib['name'] = j_package.attrib['name'].replace('/', '.') 118 | 119 | c_classes = ET.SubElement(c_package, 'classes') 120 | for j_class in j_package.findall('class'): 121 | c_classes.append(convert_class(j_class, j_package)) 122 | 123 | add_counters(j_package, c_package) 124 | 125 | return c_package 126 | 127 | def convert_root(source, target, source_roots): 128 | target.set('timestamp', str(int(source.find('sessioninfo').attrib['start']) / 1000)) 129 | 130 | sources = ET.SubElement(target, 'sources') 131 | for s in source_roots: 132 | ET.SubElement(sources, 'source').text = s 133 | 134 | packages = ET.SubElement(target, 'packages') 135 | for package in source.findall('package'): 136 | packages.append(convert_package(package)) 137 | 138 | add_counters(source, target) 139 | 140 | def jacoco2cobertura(filename, source_roots): 141 | if filename == '-': 142 | root = ET.fromstring(sys.stdin.read()) 143 | else: 144 | tree = ET.parse(filename) 145 | root = tree.getroot() 146 | 147 | into = ET.Element('coverage') 148 | convert_root(root, into, source_roots) 149 | print '' 150 | print ET.tostring(into) 151 | 152 | if __name__ == '__main__': 153 | if len(sys.argv) < 2: 154 | print "Usage: cover2cover.py FILENAME [SOURCE_ROOTS]" 155 | sys.exit(1) 156 | 157 | filename = sys.argv[1] 158 | source_roots = sys.argv[2:] if 2 < len(sys.argv) else '.' 159 | 160 | jacoco2cobertura(filename, source_roots) 161 | -------------------------------------------------------------------------------- /sample/ios/ReactNativeAzureNotificationHubSample.xcodeproj/xcshareddata/xcschemes/ReactNativeAzureNotificationHubSample.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 43 | 49 | 50 | 51 | 52 | 53 | 60 | 61 | 67 | 68 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 87 | 88 | 89 | 90 | 91 | 101 | 103 | 109 | 110 | 111 | 112 | 118 | 120 | 126 | 127 | 128 | 129 | 131 | 132 | 135 | 136 | 137 | -------------------------------------------------------------------------------- /android/src/main/java/com/azure/reactnative/notificationhub/ReactNativeRegistrationIntentService.java: -------------------------------------------------------------------------------- 1 | package com.azure.reactnative.notificationhub; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | 6 | import androidx.core.app.JobIntentService; 7 | 8 | import android.util.Log; 9 | 10 | import com.google.android.gms.tasks.OnSuccessListener; 11 | import com.google.firebase.iid.FirebaseInstanceId; 12 | import com.google.firebase.iid.InstanceIdResult; 13 | import com.microsoft.windowsazure.messaging.NotificationHub; 14 | 15 | import java.util.concurrent.ExecutorService; 16 | import java.util.concurrent.Executors; 17 | 18 | public class ReactNativeRegistrationIntentService extends JobIntentService { 19 | 20 | public static final String TAG = "ReactNativeRegistration"; 21 | 22 | private static final int JOB_ID = 1000; 23 | 24 | private final ExecutorService mPool = Executors.newFixedThreadPool(1); 25 | 26 | /** 27 | * Convenience method for enqueuing work in to this service. 28 | */ 29 | public static void enqueueWork(Context context, Intent work) { 30 | enqueueWork(context, ReactNativeRegistrationIntentService.class, JOB_ID, work); 31 | } 32 | 33 | @Override 34 | protected void onHandleWork(Intent intent) { 35 | final Intent event = ReactNativeNotificationHubUtil.IntentFactory.createIntent(TAG); 36 | final ReactNativeNotificationHubUtil notificationHubUtil = ReactNativeNotificationHubUtil.getInstance(); 37 | final String connectionString = notificationHubUtil.getConnectionString(this); 38 | final String hubName = notificationHubUtil.getHubName(this); 39 | final String storedToken = notificationHubUtil.getFCMToken(this); 40 | final String[] tags = notificationHubUtil.getTags(this); 41 | final boolean isTemplated = notificationHubUtil.isTemplated(this); 42 | final String templateName = notificationHubUtil.getTemplateName(this); 43 | final String template = notificationHubUtil.getTemplate(this); 44 | 45 | if (connectionString == null || hubName == null) { 46 | // The intent was triggered when no connection string has been set. 47 | // This is likely due to an InstanceID refresh occurring while no user 48 | // registration is active for Azure Notification Hub. 49 | return; 50 | } 51 | 52 | FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener( 53 | mPool, new OnSuccessListener() { 54 | @Override 55 | public void onSuccess(InstanceIdResult instanceIdResult) { 56 | try { 57 | String regID = notificationHubUtil.getRegistrationID(ReactNativeRegistrationIntentService.this); 58 | String token = instanceIdResult.getToken(); 59 | Log.d(TAG, "FCM Registration Token: " + token); 60 | 61 | // Storing the registration ID indicates whether the generated token has been 62 | // sent to your server. If it is not stored, send the token to your server. 63 | // Also check if the token has been compromised and needs refreshing. 64 | if (regID == null || storedToken != token) { 65 | NotificationHub hub = ReactNativeUtil.createNotificationHub(hubName, connectionString, 66 | ReactNativeRegistrationIntentService.this); 67 | Log.d(TAG, "NH Registration refreshing with token : " + token); 68 | 69 | if (isTemplated) { 70 | regID = hub.registerTemplate( 71 | token, templateName, template, tags).getRegistrationId(); 72 | } else { 73 | regID = hub.register(token, tags).getRegistrationId(); 74 | } 75 | 76 | Log.d(TAG, "New NH Registration Successfully - RegId : " + regID); 77 | 78 | notificationHubUtil.setRegistrationID(ReactNativeRegistrationIntentService.this, regID); 79 | notificationHubUtil.setFCMToken(ReactNativeRegistrationIntentService.this, token); 80 | 81 | event.putExtra( 82 | ReactNativeConstants.KEY_INTENT_EVENT_NAME, 83 | ReactNativeConstants.EVENT_AZURE_NOTIFICATION_HUB_REGISTERED); 84 | event.putExtra( 85 | ReactNativeConstants.KEY_INTENT_EVENT_TYPE, 86 | ReactNativeConstants.INTENT_EVENT_TYPE_STRING); 87 | event.putExtra( 88 | ReactNativeConstants.KEY_INTENT_EVENT_STRING_DATA, regID); 89 | ReactNativeNotificationsHandler.sendBroadcast( 90 | ReactNativeRegistrationIntentService.this, event, 0); 91 | 92 | // Create notification handler 93 | ReactNativeFirebaseMessagingService.createNotificationChannel( 94 | ReactNativeRegistrationIntentService.this); 95 | } 96 | } catch (Exception e) { 97 | Log.e(TAG, "Failed to complete token refresh", e); 98 | 99 | event.putExtra( 100 | ReactNativeConstants.KEY_INTENT_EVENT_NAME, 101 | ReactNativeConstants.EVENT_AZURE_NOTIFICATION_HUB_REGISTERED_ERROR); 102 | event.putExtra( 103 | ReactNativeConstants.KEY_INTENT_EVENT_TYPE, 104 | ReactNativeConstants.INTENT_EVENT_TYPE_STRING); 105 | event.putExtra(ReactNativeConstants.KEY_INTENT_EVENT_STRING_DATA, e.getMessage()); 106 | ReactNativeNotificationsHandler.sendBroadcast( 107 | ReactNativeRegistrationIntentService.this, event, 0); 108 | } 109 | } 110 | }); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /sample/android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | # Determine the Java command to use to start the JVM. 86 | if [ -n "$JAVA_HOME" ] ; then 87 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 88 | # IBM's JDK on AIX uses strange locations for the executables 89 | JAVACMD="$JAVA_HOME/jre/sh/java" 90 | else 91 | JAVACMD="$JAVA_HOME/bin/java" 92 | fi 93 | if [ ! -x "$JAVACMD" ] ; then 94 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 95 | 96 | Please set the JAVA_HOME variable in your environment to match the 97 | location of your Java installation." 98 | fi 99 | else 100 | JAVACMD="java" 101 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 102 | 103 | Please set the JAVA_HOME variable in your environment to match the 104 | location of your Java installation." 105 | fi 106 | 107 | # Increase the maximum file descriptors if we can. 108 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 109 | MAX_FD_LIMIT=`ulimit -H -n` 110 | if [ $? -eq 0 ] ; then 111 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 112 | MAX_FD="$MAX_FD_LIMIT" 113 | fi 114 | ulimit -n $MAX_FD 115 | if [ $? -ne 0 ] ; then 116 | warn "Could not set maximum file descriptor limit: $MAX_FD" 117 | fi 118 | else 119 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 120 | fi 121 | fi 122 | 123 | # For Darwin, add options to specify how the application appears in the dock 124 | if $darwin; then 125 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 126 | fi 127 | 128 | # For Cygwin, switch paths to Windows format before running java 129 | if $cygwin ; then 130 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 131 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 132 | JAVACMD=`cygpath --unix "$JAVACMD"` 133 | 134 | # We build the pattern for arguments to be converted via cygpath 135 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 136 | SEP="" 137 | for dir in $ROOTDIRSRAW ; do 138 | ROOTDIRS="$ROOTDIRS$SEP$dir" 139 | SEP="|" 140 | done 141 | OURCYGPATTERN="(^($ROOTDIRS))" 142 | # Add a user-defined pattern to the cygpath arguments 143 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 144 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 145 | fi 146 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 147 | i=0 148 | for arg in "$@" ; do 149 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 150 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 151 | 152 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 153 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 154 | else 155 | eval `echo args$i`="\"$arg\"" 156 | fi 157 | i=$((i+1)) 158 | done 159 | case $i in 160 | (0) set -- ;; 161 | (1) set -- "$args0" ;; 162 | (2) set -- "$args0" "$args1" ;; 163 | (3) set -- "$args0" "$args1" "$args2" ;; 164 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 165 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 166 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 167 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 168 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 169 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 170 | esac 171 | fi 172 | 173 | # Escape application args 174 | save () { 175 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 176 | echo " " 177 | } 178 | APP_ARGS=$(save "$@") 179 | 180 | # Collect all arguments for the java command, following the shell quoting and substitution rules 181 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 182 | 183 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 184 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 185 | cd "$(dirname "$0")" 186 | fi 187 | 188 | exec "$JAVACMD" "$@" 189 | -------------------------------------------------------------------------------- /windows/ReactWindowsAzureNotificationHub/ReactWindowsAzureNotificationHub.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {95F0B433-B38E-435C-BC83-939A9E4B470D} 8 | Library 9 | Properties 10 | ReactWindowsAzureNotificationHub 11 | ReactWindowsAzureNotificationHub 12 | en-US 13 | UAP 14 | 10.0.14393.0 15 | 10.0.10586.0 16 | 14 17 | 512 18 | {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 19 | 20 | 21 | AnyCPU 22 | true 23 | full 24 | false 25 | bin\Debug\ 26 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 27 | prompt 28 | 4 29 | 30 | 31 | AnyCPU 32 | pdbonly 33 | true 34 | bin\Release\ 35 | TRACE;NETFX_CORE;WINDOWS_UWP 36 | prompt 37 | 4 38 | 39 | 40 | x86 41 | true 42 | bin\x86\Debug\ 43 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 44 | ;2008 45 | full 46 | x86 47 | false 48 | prompt 49 | 50 | 51 | x86 52 | bin\x86\Release\ 53 | TRACE;NETFX_CORE;WINDOWS_UWP 54 | true 55 | ;2008 56 | pdbonly 57 | x86 58 | false 59 | prompt 60 | 61 | 62 | ARM 63 | true 64 | bin\ARM\Debug\ 65 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 66 | ;2008 67 | full 68 | ARM 69 | false 70 | prompt 71 | 72 | 73 | ARM 74 | bin\ARM\Release\ 75 | TRACE;NETFX_CORE;WINDOWS_UWP 76 | true 77 | ;2008 78 | pdbonly 79 | ARM 80 | false 81 | prompt 82 | 83 | 84 | x64 85 | true 86 | bin\x64\Debug\ 87 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 88 | ;2008 89 | full 90 | x64 91 | false 92 | prompt 93 | 94 | 95 | x64 96 | bin\x64\Release\ 97 | TRACE;NETFX_CORE;WINDOWS_UWP 98 | true 99 | ;2008 100 | pdbonly 101 | x64 102 | false 103 | prompt 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | {c7673ad5-e3aa-468c-a5fd-fa38154e205c} 118 | ReactNative 119 | 120 | 121 | 122 | 14.0 123 | 124 | 125 | 132 | -------------------------------------------------------------------------------- /sample/App.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Sample React Native App 3 | * https://github.com/facebook/react-native 4 | * 5 | * @format 6 | * @flow 7 | */ 8 | 9 | import React, { Component } from 'react'; 10 | import { NativeEventEmitter } from 'react-native'; 11 | import { 12 | StyleSheet, 13 | Text, 14 | View, 15 | TouchableOpacity, 16 | } from 'react-native'; 17 | 18 | const NotificationHub = require('react-native-azurenotificationhub'); 19 | const PushNotificationEmitter = new NativeEventEmitter(NotificationHub); 20 | 21 | const EVENT_AZURE_NOTIFICATION_HUB_REGISTERED = 'azureNotificationHubRegistered'; 22 | const EVENT_AZURE_NOTIFICATION_HUB_REGISTERED_ERROR = 'azureNotificationHubRegisteredError'; 23 | const EVENT_REMOTE_NOTIFICATION_RECEIVED = 'remoteNotificationReceived'; 24 | 25 | const connectionString = 'Endpoint=sb://rn-anh.servicebus.windows.net/;SharedAccessKeyName=DefaultFullSharedAccessSignature;SharedAccessKey=12345'; 26 | const hubName = 'azurenotificationhub'; 27 | const senderID = '12345'; 28 | const tags = []; 29 | const channelName = 'Channel Name'; 30 | const channelImportance = 3; 31 | const channelShowBadge = true; 32 | const channelEnableLights = true; 33 | const channelEnableVibration = true; 34 | const template = '{\"data\":{\"message\":\"$(message)\"}}'; 35 | const templateName = 'Template Name'; 36 | 37 | export default class App extends Component { 38 | constructor(props) { 39 | super(props); 40 | PushNotificationEmitter.addListener(EVENT_REMOTE_NOTIFICATION_RECEIVED, this._onRemoteNotification); 41 | } 42 | 43 | register() { 44 | PushNotificationEmitter.addListener(EVENT_AZURE_NOTIFICATION_HUB_REGISTERED, this._onAzureNotificationHubRegistered); 45 | PushNotificationEmitter.addListener(EVENT_AZURE_NOTIFICATION_HUB_REGISTERED_ERROR, this._onAzureNotificationHubRegisteredError); 46 | 47 | NotificationHub.register({ 48 | connectionString, 49 | hubName, 50 | senderID, 51 | tags, 52 | channelName, 53 | channelImportance, 54 | channelShowBadge, 55 | channelEnableLights, 56 | channelEnableVibration 57 | }) 58 | .then((res) => console.warn(res)) 59 | .catch(reason => console.warn(reason)); 60 | } 61 | 62 | registerTemplate() { 63 | PushNotificationEmitter.addListener(EVENT_AZURE_NOTIFICATION_HUB_REGISTERED, this._onAzureNotificationHubRegistered); 64 | PushNotificationEmitter.addListener(EVENT_AZURE_NOTIFICATION_HUB_REGISTERED_ERROR, this._onAzureNotificationHubRegisteredError); 65 | 66 | NotificationHub.registerTemplate({ 67 | connectionString, 68 | hubName, 69 | senderID, 70 | template, 71 | templateName, 72 | tags, 73 | channelName, 74 | channelImportance, 75 | channelShowBadge, 76 | channelEnableLights, 77 | channelEnableVibration 78 | }) 79 | .then((res) => console.warn(res)) 80 | .catch(reason => console.warn(reason)); 81 | } 82 | 83 | getInitialNotification() { 84 | NotificationHub.getInitialNotification() 85 | .then((res) => console.warn(res)) 86 | .catch(reason => console.warn(reason)); 87 | } 88 | 89 | getUUID() { 90 | NotificationHub.getUUID(false) 91 | .then((res) => console.warn(res)) 92 | .catch(reason => console.warn(reason)); 93 | } 94 | 95 | isNotificationEnabledOnOSLevel() { 96 | NotificationHub.isNotificationEnabledOnOSLevel() 97 | .then((res) => console.warn(res)) 98 | .catch(reason => console.warn(reason)); 99 | } 100 | 101 | unregister() { 102 | NotificationHub.unregister() 103 | .then((res) => console.warn(res)) 104 | .catch(reason => console.warn(reason)); 105 | } 106 | 107 | unregisterTemplate() { 108 | NotificationHub.unregisterTemplate(templateName) 109 | .then((res) => console.warn(res)) 110 | .catch(reason => console.warn(reason)); 111 | } 112 | 113 | render() { 114 | return ( 115 | 116 | 117 | 118 | 119 | Register 120 | 121 | 122 | 123 | 124 | 125 | 126 | Register Template 127 | 128 | 129 | 130 | 131 | 132 | 133 | Get initial notification 134 | 135 | 136 | 137 | 138 | 139 | 140 | Get UUID 141 | 142 | 143 | 144 | 145 | 146 | 147 | Check if notification is enabled 148 | 149 | 150 | 151 | 152 | 153 | 154 | Unregister 155 | 156 | 157 | 158 | 159 | 160 | 161 | Unregister Template 162 | 163 | 164 | 165 | 166 | ); 167 | } 168 | 169 | _onAzureNotificationHubRegistered(registrationID) { 170 | console.warn('RegistrationID: ' + registrationID); 171 | } 172 | 173 | _onAzureNotificationHubRegisteredError(error) { 174 | console.warn('Error: ' + error); 175 | } 176 | 177 | _onRemoteNotification(notification) { 178 | console.warn(notification); 179 | } 180 | } 181 | 182 | const styles = StyleSheet.create({ 183 | container: { 184 | flex: 1, 185 | justifyContent: 'center', 186 | alignItems: 'center', 187 | backgroundColor: '#F5FCFF', 188 | }, 189 | welcome: { 190 | fontSize: 20, 191 | textAlign: 'center', 192 | margin: 10, 193 | }, 194 | instructions: { 195 | textAlign: 'center', 196 | color: '#333333', 197 | marginBottom: 5, 198 | }, 199 | }); 200 | -------------------------------------------------------------------------------- /sample/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.application" 2 | 3 | import com.android.build.OutputFile 4 | 5 | /** 6 | * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets 7 | * and bundleReleaseJsAndAssets). 8 | * These basically call `react-native bundle` with the correct arguments during the Android build 9 | * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the 10 | * bundle directly from the development server. Below you can see all the possible configurations 11 | * and their defaults. If you decide to add a configuration block, make sure to add it before the 12 | * `apply from: "../../node_modules/react-native/react.gradle"` line. 13 | * 14 | * project.ext.react = [ 15 | * // the name of the generated asset file containing your JS bundle 16 | * bundleAssetName: "index.android.bundle", 17 | * 18 | * // the entry file for bundle generation 19 | * entryFile: "index.android.js", 20 | * 21 | * // https://facebook.github.io/react-native/docs/performance#enable-the-ram-format 22 | * bundleCommand: "ram-bundle", 23 | * 24 | * // whether to bundle JS and assets in debug mode 25 | * bundleInDebug: false, 26 | * 27 | * // whether to bundle JS and assets in release mode 28 | * bundleInRelease: true, 29 | * 30 | * // whether to bundle JS and assets in another build variant (if configured). 31 | * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants 32 | * // The configuration property can be in the following formats 33 | * // 'bundleIn${productFlavor}${buildType}' 34 | * // 'bundleIn${buildType}' 35 | * // bundleInFreeDebug: true, 36 | * // bundleInPaidRelease: true, 37 | * // bundleInBeta: true, 38 | * 39 | * // whether to disable dev mode in custom build variants (by default only disabled in release) 40 | * // for example: to disable dev mode in the staging build type (if configured) 41 | * devDisabledInStaging: true, 42 | * // The configuration property can be in the following formats 43 | * // 'devDisabledIn${productFlavor}${buildType}' 44 | * // 'devDisabledIn${buildType}' 45 | * 46 | * // the root of your project, i.e. where "package.json" lives 47 | * root: "../../", 48 | * 49 | * // where to put the JS bundle asset in debug mode 50 | * jsBundleDirDebug: "$buildDir/intermediates/assets/debug", 51 | * 52 | * // where to put the JS bundle asset in release mode 53 | * jsBundleDirRelease: "$buildDir/intermediates/assets/release", 54 | * 55 | * // where to put drawable resources / React Native assets, e.g. the ones you use via 56 | * // require('./image.png')), in debug mode 57 | * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug", 58 | * 59 | * // where to put drawable resources / React Native assets, e.g. the ones you use via 60 | * // require('./image.png')), in release mode 61 | * resourcesDirRelease: "$buildDir/intermediates/res/merged/release", 62 | * 63 | * // by default the gradle tasks are skipped if none of the JS files or assets change; this means 64 | * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to 65 | * // date; if you have any other folders that you want to ignore for performance reasons (gradle 66 | * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/ 67 | * // for example, you might want to remove it from here. 68 | * inputExcludes: ["android/**", "ios/**"], 69 | * 70 | * // override which node gets called and with what additional arguments 71 | * nodeExecutableAndArgs: ["node"], 72 | * 73 | * // supply additional arguments to the packager 74 | * extraPackagerArgs: [] 75 | * ] 76 | */ 77 | 78 | project.ext.react = [ 79 | entryFile: "index.js", 80 | enableHermes: false, // clean and rebuild if changing 81 | ] 82 | 83 | apply from: "../../node_modules/react-native/react.gradle" 84 | apply from: "jacoco.gradle" 85 | 86 | /** 87 | * Set this to true to create two separate APKs instead of one: 88 | * - An APK that only works on ARM devices 89 | * - An APK that only works on x86 devices 90 | * The advantage is the size of the APK is reduced by about 4MB. 91 | * Upload all the APKs to the Play Store and people will download 92 | * the correct one based on the CPU architecture of their device. 93 | */ 94 | def enableSeparateBuildPerCPUArchitecture = false 95 | 96 | /** 97 | * Run Proguard to shrink the Java bytecode in release builds. 98 | */ 99 | def enableProguardInReleaseBuilds = false 100 | 101 | /** 102 | * The preferred build flavor of JavaScriptCore. 103 | * 104 | * For example, to use the international variant, you can use: 105 | * `def jscFlavor = 'org.webkit:android-jsc-intl:+'` 106 | * 107 | * The international variant includes ICU i18n library and necessary data 108 | * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that 109 | * give correct results when using with locales other than en-US. Note that 110 | * this variant is about 6MiB larger per architecture than default. 111 | */ 112 | def jscFlavor = 'org.webkit:android-jsc:+' 113 | 114 | /** 115 | * Whether to enable the Hermes VM. 116 | * 117 | * This should be set on project.ext.react and mirrored here. If it is not set 118 | * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode 119 | * and the benefits of using Hermes will therefore be sharply reduced. 120 | */ 121 | def enableHermes = project.ext.react.get("enableHermes", false); 122 | 123 | android { 124 | compileSdkVersion rootProject.ext.compileSdkVersion 125 | 126 | compileOptions { 127 | sourceCompatibility JavaVersion.VERSION_1_8 128 | targetCompatibility JavaVersion.VERSION_1_8 129 | } 130 | 131 | defaultConfig { 132 | applicationId "com.reactnativeazurenotificationhubsample" 133 | minSdkVersion rootProject.ext.minSdkVersion 134 | targetSdkVersion rootProject.ext.targetSdkVersion 135 | versionCode 1 136 | versionName "1.0" 137 | } 138 | 139 | splits { 140 | abi { 141 | reset() 142 | enable enableSeparateBuildPerCPUArchitecture 143 | universalApk false // If true, also generate a universal APK 144 | include "armeabi-v7a", "x86", "arm64-v8a", "x86_64" 145 | } 146 | } 147 | 148 | signingConfigs { 149 | debug { 150 | storeFile file('debug.keystore') 151 | storePassword 'android' 152 | keyAlias 'androiddebugkey' 153 | keyPassword 'android' 154 | } 155 | } 156 | 157 | buildTypes { 158 | debug { 159 | signingConfig signingConfigs.debug 160 | } 161 | release { 162 | // Caution! In production, you need to generate your own keystore file. 163 | // see https://facebook.github.io/react-native/docs/signed-apk-android. 164 | signingConfig signingConfigs.debug 165 | minifyEnabled enableProguardInReleaseBuilds 166 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" 167 | } 168 | } 169 | 170 | // applicationVariants are e.g. debug, release 171 | applicationVariants.all { variant -> 172 | variant.outputs.each { output -> 173 | // For each separate APK per architecture, set a unique version code as described here: 174 | // https://developer.android.com/studio/build/configure-apk-splits.html 175 | def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4] 176 | def abi = output.getFilter(OutputFile.ABI) 177 | if (abi != null) { // null for the universal-debug, universal-release variants 178 | output.versionCodeOverride = 179 | versionCodes.get(abi) * 1048576 + defaultConfig.versionCode 180 | } 181 | 182 | } 183 | } 184 | } 185 | 186 | dependencies { 187 | implementation fileTree(dir: "libs", include: ["*.jar"]) 188 | implementation "com.facebook.react:react-native:+" // From node_modules 189 | implementation project(":react-native-azurenotificationhub") // From node_modules 190 | implementation "com.google.firebase:firebase-messaging:17.6.0" 191 | implementation "com.google.firebase:firebase-core:16.0.8" 192 | implementation "com.microsoft.azure:notification-hubs-android-sdk:0.6@aar" 193 | testImplementation "org.powermock:powermock-core:2.0.2" 194 | testImplementation "org.powermock:powermock-api-mockito2:2.0.2" 195 | testImplementation "org.powermock:powermock-module-junit4:2.0.2" 196 | testImplementation "org.json:json:20180130" 197 | 198 | if (enableHermes) { 199 | def hermesPath = "../../node_modules/hermes-engine/android/"; 200 | debugImplementation files(hermesPath + "hermes-debug.aar") 201 | releaseImplementation files(hermesPath + "hermes-release.aar") 202 | } else { 203 | implementation jscFlavor 204 | } 205 | } 206 | 207 | apply plugin: "com.google.gms.google-services" 208 | 209 | // Run this once to be able to run the application with BUCK 210 | // puts all compile dependencies into folder libs for BUCK to use 211 | task copyDownloadableDepsToLibs(type: Copy) { 212 | from configurations.compile 213 | into 'libs' 214 | } 215 | 216 | apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) -------------------------------------------------------------------------------- /android/src/main/java/com/azure/reactnative/notificationhub/ReactNativeConstants.java: -------------------------------------------------------------------------------- 1 | package com.azure.reactnative.notificationhub; 2 | 3 | public final class ReactNativeConstants { 4 | // Notification 5 | public static final String AZURE_NOTIFICATION_HUB_NAME = "AzureNotificationHub"; 6 | public static final String NOTIFICATION_CHANNEL_ID = "rn-push-notification-channel-id"; 7 | public static final String KEY_NOTIFICATION_PAYLOAD_TYPE = "notification"; 8 | public static final String KEY_DATA_PAYLOAD_TYPE = "data"; 9 | 10 | // Notification hub events 11 | public static final String EVENT_REMOTE_NOTIFICATION_RECEIVED = "remoteNotificationReceived"; 12 | public static final String EVENT_AZURE_NOTIFICATION_HUB_REGISTERED = "azureNotificationHubRegistered"; 13 | public static final String EVENT_AZURE_NOTIFICATION_HUB_REGISTERED_ERROR = "azureNotificationHubRegisteredError"; 14 | 15 | // Registration's keys 16 | public static final String KEY_REGISTRATION_CONNECTIONSTRING = "connectionString"; 17 | public static final String KEY_REGISTRATION_HUBNAME = "hubName"; 18 | public static final String KEY_REGISTRATION_SENDERID = "senderID"; 19 | public static final String KEY_REGISTRATION_TAGS = "tags"; 20 | public static final String KEY_REGISTRATION_CHANNELNAME = "channelName"; 21 | public static final String KEY_REGISTRATION_CHANNELDESCRIPTION = "channelDescription"; 22 | public static final String KEY_REGISTRATION_CHANNELIMPORTANCE = "channelImportance"; 23 | public static final String KEY_REGISTRATION_CHANNELSHOWBADGE = "channelShowBadge"; 24 | public static final String KEY_REGISTRATION_CHANNELENABLELIGHTS = "channelEnableLights"; 25 | public static final String KEY_REGISTRATION_CHANNELENABLEVIBRATION = "channelEnableVibration"; 26 | public static final String KEY_REGISTRATION_TEMPLATENAME = "templateName"; 27 | public static final String KEY_REGISTRATION_TEMPLATE = "template"; 28 | public static final String KEY_REGISTRATION_ISTEMPLATE = "isTemplate"; 29 | 30 | // Shared prefs used in NotificationHubUtil 31 | public static final String SHARED_PREFS_NAME = "com.azure.reactnative.notificationhub.NotificationHubUtil"; 32 | public static final String KEY_FOR_PREFS_REGISTRATIONID = "AzureNotificationHub_registrationID"; 33 | public static final String KEY_FOR_PREFS_CONNECTIONSTRING = "AzureNotificationHub_connectionString"; 34 | public static final String KEY_FOR_PREFS_HUBNAME = "AzureNotificationHub_hubName"; 35 | public static final String KEY_FOR_PREFS_FCMTOKEN = "AzureNotificationHub_FCMToken"; 36 | public static final String KEY_FOR_PREFS_TAGS = "AzureNotificationHub_Tags"; 37 | public static final String KEY_FOR_PREFS_SENDERID = "AzureNotificationHub_senderID"; 38 | public static final String KEY_FOR_PREFS_CHANNELNAME = "AzureNotificationHub_channelName"; 39 | public static final String KEY_FOR_PREFS_CHANNELDESCRIPTION = "AzureNotificationHub_channelDescription"; 40 | public static final String KEY_FOR_PREFS_CHANNELIMPORTANCE = "AzureNotificationHub_channelImportance"; 41 | public static final String KEY_FOR_PREFS_CHANNELSHOWBADGE = "AzureNotificationHub_channelShowBadge"; 42 | public static final String KEY_FOR_PREFS_CHANNELENABLELIGHTS = "AzureNotificationHub_channelEnableLights"; 43 | public static final String KEY_FOR_PREFS_CHANNELENABLEVIBRATION = "AzureNotificationHub_channelEnableVibration"; 44 | public static final String KEY_FOR_PREFS_TEMPLATENAME = "AzureNotificationHub_templateName"; 45 | public static final String KEY_FOR_PREFS_TEMPLATE = "AzureNotificationHub_template"; 46 | public static final String KEY_FOR_PREFS_ISTEMPLATE = "AzureNotificationHub_isTemplate"; 47 | public static final String KEY_FOR_PREFS_UUID = "AzureNotificationHub_UUID"; 48 | 49 | // Remote notification payload 50 | public static final String KEY_REMOTE_NOTIFICATION_MESSAGE = "message"; 51 | public static final String KEY_REMOTE_NOTIFICATION_BODY = "body"; 52 | public static final String KEY_REMOTE_NOTIFICATION_ID = "google.message_id"; 53 | public static final String KEY_REMOTE_NOTIFICATION_TITLE = "title"; 54 | public static final String KEY_REMOTE_NOTIFICATION_PRIORITY = "google.original_priority"; 55 | public static final String KEY_REMOTE_NOTIFICATION_TICKER = "ticker"; 56 | public static final String KEY_REMOTE_NOTIFICATION_AUTO_CANCEL = "autoCancel"; 57 | public static final String KEY_REMOTE_NOTIFICATION_GROUP = "group"; 58 | public static final String KEY_REMOTE_NOTIFICATION_LARGE_ICON = "largeIcon"; 59 | public static final String KEY_REMOTE_NOTIFICATION_SUB_TEXT = "subText"; 60 | public static final String KEY_REMOTE_NOTIFICATION_NUMBER = "number"; 61 | public static final String KEY_REMOTE_NOTIFICATION_SMALL_ICON = "smallIcon"; 62 | public static final String KEY_REMOTE_NOTIFICATION_BIG_TEXT = "bigText"; 63 | public static final String KEY_REMOTE_NOTIFICATION_PLAY_SOUND = "playSound"; 64 | public static final String KEY_REMOTE_NOTIFICATION_SOUND_NAME = "soundName"; 65 | public static final String KEY_REMOTE_NOTIFICATION_ONGOING = "ongoing"; 66 | public static final String KEY_REMOTE_NOTIFICATION_COLOR = "color"; 67 | public static final String KEY_REMOTE_NOTIFICATION_VIBRATE = "vibrate"; 68 | public static final String KEY_REMOTE_NOTIFICATION_VIBRATION = "vibration"; 69 | public static final String KEY_REMOTE_NOTIFICATION_FOREGROUND = "foreground"; 70 | public static final String KEY_REMOTE_NOTIFICATION_ACTIONS = "actions"; 71 | public static final String KEY_REMOTE_NOTIFICATION_ACTION = "action"; 72 | public static final String KEY_REMOTE_NOTIFICATION_TAG = "tag"; 73 | public static final String KEY_REMOTE_NOTIFICATION_USER_INTERACTION = "userInteraction"; 74 | public static final String KEY_REMOTE_NOTIFICATION_COLDSTART = "coldstart"; 75 | public static final String KEY_REMOTE_NOTIFICATION_AVATAR_URL = "avatarUrl"; 76 | 77 | // Remote notification payload's priority 78 | public static final String REMOTE_NOTIFICATION_PRIORITY_MAX = "max"; 79 | public static final String REMOTE_NOTIFICATION_PRIORITY_HIGH = "high"; 80 | public static final String REMOTE_NOTIFICATION_PRIORITY_LOW = "low"; 81 | public static final String REMOTE_NOTIFICATION_PRIORITY_MIN = "min"; 82 | public static final String REMOTE_NOTIFICATION_PRIORITY_NORMAL = "normal"; 83 | 84 | // Intent 85 | public static final String KEY_INTENT_EVENT_NAME = "eventName"; 86 | public static final String KEY_INTENT_EVENT_TYPE = "eventType"; 87 | public static final String KEY_INTENT_EVENT_STRING_DATA = "eventStringData"; 88 | public static final String INTENT_EVENT_TYPE_STRING = "eventTypeString"; 89 | public static final String INTENT_EVENT_TYPE_BUNDLE = "eventTypeBundle"; 90 | 91 | // Resources 92 | public static final String RESOURCE_DEF_TYPE_MIPMAP = "mipmap"; 93 | public static final String RESOURCE_DEF_TYPE_RAW = "raw"; 94 | public static final String RESOURCE_NAME_NOTIFICATION = "ic_notification"; 95 | public static final String RESOURCE_NAME_LAUNCHER = "ic_launcher"; 96 | 97 | // Promise 98 | public static final String KEY_PROMISE_RESOLVE_UUID = "uuid"; 99 | public static final String AZURE_NOTIFICATION_HUB_UNREGISTERED = "Unregistered successfully"; 100 | 101 | // Errors 102 | public static final String ERROR_NO_ACTIVITY_CLASS = "No activity class found for the notification"; 103 | public static final String ERROR_NO_MESSAGE = "No message specified for the notification"; 104 | public static final String ERROR_COVERT_ACTIONS = "Exception while converting actions to JSON object."; 105 | public static final String ERROR_GET_ACTIONS_ARRAY = "Exception while getting action from actionsArray."; 106 | public static final String ERROR_SEND_PUSH_NOTIFICATION = "failed to send push notification"; 107 | public static final String ERROR_ACTIVITY_CLASS_NOT_FOUND = "Activity class not found"; 108 | public static final String ERROR_INVALID_ARGUMENTS = "E_INVALID_ARGUMENTS"; 109 | public static final String ERROR_INVALID_CONNECTION_STRING = "Connection string cannot be null."; 110 | public static final String ERROR_INVALID_HUBNAME = "Hub name cannot be null."; 111 | public static final String ERROR_INVALID_SENDER_ID = "Sender ID cannot be null."; 112 | public static final String ERROR_INVALID_TEMPLATE_NAME = "Template Name cannot be null."; 113 | public static final String ERROR_INVALID_TEMPLATE = "Template cannot be null."; 114 | public static final String ERROR_PLAY_SERVICES = "E_PLAY_SERVICES"; 115 | public static final String ERROR_PLAY_SERVICES_DISABLED = "User must enable Google Play Services."; 116 | public static final String ERROR_PLAY_SERVICES_UNSUPPORTED = "This device is not supported by Google Play Services."; 117 | public static final String ERROR_NOTIFICATION_HUB = "E_NOTIFICATION_HUB"; 118 | public static final String ERROR_NOT_REGISTERED = "E_NOT_REGISTERED"; 119 | public static final String ERROR_NOT_REGISTERED_DESC = "No registration to Azure Notification Hub."; 120 | public static final String ERROR_FETCH_IMAGE = "Error while fetching image."; 121 | public static final String ERROR_GET_INIT_NOTIFICATION = "E_GET_INIT_NOTIF"; 122 | public static final String ERROR_ACTIVITY_IS_NULL = "Current activity is null"; 123 | public static final String ERROR_INTENT_EXTRAS_IS_NULL = "Intent get extras is null"; 124 | public static final String ERROR_ACTIVITY_INTENT_IS_NULL = "Activity intent is null"; 125 | public static final String ERROR_GET_UUID = "E_GET_UUID"; 126 | public static final String ERROR_NO_UUID_SET = "No uuid set"; 127 | 128 | private ReactNativeConstants() { 129 | } 130 | } 131 | --------------------------------------------------------------------------------