├── .gitattributes
├── .gitignore
├── LICENSE
├── README.md
├── art
└── icon.png
├── cd-pipeline.yml
├── ci-pipeline.yml
├── docs
├── AndroidCustomization.md
├── FAQ.md
├── GettingStarted.md
├── LocalizedPushNotifications.md
├── NotificationActions.md
├── ReceivingNotifications.md
└── iOSCustomization.md
├── nuget
└── Plugin.nuspec
├── samples
└── AzurePushNotificationSample
│ ├── AzurePushNotificationSample.Android
│ ├── Assets
│ │ └── AboutAssets.txt
│ ├── AzurePushNotificationSample.Android.csproj
│ ├── MainActivity.cs
│ ├── MainApplication.cs
│ ├── Properties
│ │ ├── AndroidManifest.xml
│ │ └── AssemblyInfo.cs
│ ├── Resources
│ │ ├── AboutResources.txt
│ │ ├── Resource.designer.cs
│ │ ├── drawable-hdpi
│ │ │ └── icon.png
│ │ ├── drawable-xhdpi
│ │ │ └── icon.png
│ │ ├── drawable-xxhdpi
│ │ │ └── icon.png
│ │ ├── drawable
│ │ │ ├── icon.png
│ │ │ └── splash_screen.xml
│ │ ├── layout
│ │ │ ├── Main.axml
│ │ │ ├── Tabbar.axml
│ │ │ └── Toolbar.axml
│ │ ├── mipmap-hdpi
│ │ │ └── Icon.png
│ │ ├── mipmap-mdpi
│ │ │ └── Icon.png
│ │ ├── mipmap-xhdpi
│ │ │ └── Icon.png
│ │ ├── mipmap-xxhdpi
│ │ │ └── Icon.png
│ │ ├── mipmap-xxxhdpi
│ │ │ └── Icon.png
│ │ └── values
│ │ │ ├── Strings.xml
│ │ │ ├── colors.xml
│ │ │ └── styles.xml
│ ├── SplashActivity.cs
│ └── google-services.json
│ ├── AzurePushNotificationSample.iOS
│ ├── AppDelegate.cs
│ ├── AzurePushNotificationSample.iOS.csproj
│ ├── Entitlements.plist
│ ├── Info.plist
│ ├── Main.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── Resources
│ │ ├── Default-568h@2x.png
│ │ ├── Default-Portrait.png
│ │ ├── Default-Portrait@2x.png
│ │ ├── Default.png
│ │ ├── Default@2x.png
│ │ ├── Icon-60@2x.png
│ │ ├── Icon-60@3x.png
│ │ ├── Icon-76.png
│ │ ├── Icon-76@2x.png
│ │ ├── Icon-Small-40.png
│ │ ├── Icon-Small-40@2x.png
│ │ ├── Icon-Small-40@3x.png
│ │ ├── Icon-Small.png
│ │ ├── Icon-Small@2x.png
│ │ ├── Icon-Small@3x.png
│ │ └── LaunchScreen.storyboard
│ └── packages.config
│ ├── AzurePushNotificationSample.sln
│ └── AzurePushNotificationSample
│ ├── App.xaml
│ ├── App.xaml.cs
│ ├── AzureConstants.cs
│ ├── AzurePushNotificationSample.csproj
│ ├── MainPage.xaml
│ └── MainPage.xaml.cs
└── src
├── AzurePushNotification.sln
└── Plugin.AzurePushNotification
├── AzurePushNotificationManager.android.cs
├── AzurePushNotificationManager.apple.cs
├── CrossAzurePushNotification.shared.cs
├── DefaultPushNotificationHandler.android.cs
├── DefaultPushNotificationHandler.apple.cs
├── IAzurePushNotification.shared.cs
├── IPushNotificationHandler.shared.cs
├── NotificationActionType.shared.cs
├── NotificationCategoryType.shared.cs
├── NotificationPriority.shared.cs
├── NotificationResponse.shared.cs
├── NotificationUserCategory.shared.cs
├── PNMessagingService.android.cs
├── Plugin.AzurePushNotification.csproj
├── PushNotificationActionReceiver.android.cs
└── PushNotificationDeletedReceiver.android.cs
/.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 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.suo
8 | *.user
9 | *.userosscache
10 | *.sln.docstates
11 |
12 | # User-specific files (MonoDevelop/Xamarin Studio)
13 | *.userprefs
14 |
15 | # Build results
16 | [Dd]ebug/
17 | [Dd]ebugPublic/
18 | [Rr]elease/
19 | [Rr]eleases/
20 | x64/
21 | x86/
22 | bld/
23 | [Bb]in/
24 | [Oo]bj/
25 | [Ll]og/
26 |
27 | # Visual Studio 2015 cache/options directory
28 | .vs/
29 | # Uncomment if you have tasks that create the project's static files in wwwroot
30 | #wwwroot/
31 |
32 | # MSTest test Results
33 | [Tt]est[Rr]esult*/
34 | [Bb]uild[Ll]og.*
35 |
36 | # NUNIT
37 | *.VisualState.xml
38 | TestResult.xml
39 |
40 | # Build Results of an ATL Project
41 | [Dd]ebugPS/
42 | [Rr]eleasePS/
43 | dlldata.c
44 |
45 | # .NET Core
46 | project.lock.json
47 | project.fragment.lock.json
48 | artifacts/
49 | **/Properties/launchSettings.json
50 |
51 | *_i.c
52 | *_p.c
53 | *_i.h
54 | *.ilk
55 | *.meta
56 | *.obj
57 | *.pch
58 | *.pdb
59 | *.pgc
60 | *.pgd
61 | *.rsp
62 | *.sbr
63 | *.tlb
64 | *.tli
65 | *.tlh
66 | *.tmp
67 | *.tmp_proj
68 | *.log
69 | *.vspscc
70 | *.vssscc
71 | .builds
72 | *.pidb
73 | *.svclog
74 | *.scc
75 |
76 | # Chutzpah Test files
77 | _Chutzpah*
78 |
79 | # Visual C++ cache files
80 | ipch/
81 | *.aps
82 | *.ncb
83 | *.opendb
84 | *.opensdf
85 | *.sdf
86 | *.cachefile
87 | *.VC.db
88 | *.VC.VC.opendb
89 |
90 | # Visual Studio profiler
91 | *.psess
92 | *.vsp
93 | *.vspx
94 | *.sap
95 |
96 | # TFS 2012 Local Workspace
97 | $tf/
98 |
99 | # Guidance Automation Toolkit
100 | *.gpState
101 |
102 | # ReSharper is a .NET coding add-in
103 | _ReSharper*/
104 | *.[Rr]e[Ss]harper
105 | *.DotSettings.user
106 |
107 | # JustCode is a .NET coding add-in
108 | .JustCode
109 |
110 | # TeamCity is a build add-in
111 | _TeamCity*
112 |
113 | # DotCover is a Code Coverage Tool
114 | *.dotCover
115 |
116 | # Visual Studio code coverage results
117 | *.coverage
118 | *.coveragexml
119 |
120 | # NCrunch
121 | _NCrunch_*
122 | .*crunch*.local.xml
123 | nCrunchTemp_*
124 |
125 | # MightyMoose
126 | *.mm.*
127 | AutoTest.Net/
128 |
129 | # Web workbench (sass)
130 | .sass-cache/
131 |
132 | # Installshield output folder
133 | [Ee]xpress/
134 |
135 | # DocProject is a documentation generator add-in
136 | DocProject/buildhelp/
137 | DocProject/Help/*.HxT
138 | DocProject/Help/*.HxC
139 | DocProject/Help/*.hhc
140 | DocProject/Help/*.hhk
141 | DocProject/Help/*.hhp
142 | DocProject/Help/Html2
143 | DocProject/Help/html
144 |
145 | # Click-Once directory
146 | publish/
147 |
148 | # Publish Web Output
149 | *.[Pp]ublish.xml
150 | *.azurePubxml
151 | # TODO: Comment the next line if you want to checkin your web deploy settings
152 | # but database connection strings (with potential passwords) will be unencrypted
153 | *.pubxml
154 | *.publishproj
155 |
156 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
157 | # checkin your Azure Web App publish settings, but sensitive information contained
158 | # in these scripts will be unencrypted
159 | PublishScripts/
160 |
161 | # NuGet Packages
162 | *.nupkg
163 | # The packages folder can be ignored because of Package Restore
164 | **/packages/*
165 | # except build/, which is used as an MSBuild target.
166 | !**/packages/build/
167 | # Uncomment if necessary however generally it will be regenerated when needed
168 | #!**/packages/repositories.config
169 | # NuGet v3's project.json files produces more ignorable files
170 | *.nuget.props
171 | *.nuget.targets
172 |
173 | # Microsoft Azure Build Output
174 | csx/
175 | *.build.csdef
176 |
177 | # Microsoft Azure Emulator
178 | ecf/
179 | rcf/
180 |
181 | # Windows Store app package directories and files
182 | AppPackages/
183 | BundleArtifacts/
184 | Package.StoreAssociation.xml
185 | _pkginfo.txt
186 |
187 | # Visual Studio cache files
188 | # files ending in .cache can be ignored
189 | *.[Cc]ache
190 | # but keep track of directories ending in .cache
191 | !*.[Cc]ache/
192 |
193 | # Others
194 | ClientBin/
195 | ~$*
196 | *~
197 | *.dbmdl
198 | *.dbproj.schemaview
199 | *.jfm
200 | *.pfx
201 | *.publishsettings
202 | orleans.codegen.cs
203 |
204 | # Since there are multiple workflows, uncomment next line to ignore bower_components
205 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
206 | #bower_components/
207 |
208 | # RIA/Silverlight projects
209 | Generated_Code/
210 |
211 | # Backup & report files from converting an old project file
212 | # to a newer Visual Studio version. Backup files are not needed,
213 | # because we have git ;-)
214 | _UpgradeReport_Files/
215 | Backup*/
216 | UpgradeLog*.XML
217 | UpgradeLog*.htm
218 |
219 | # SQL Server files
220 | *.mdf
221 | *.ldf
222 | *.ndf
223 |
224 | # Business Intelligence projects
225 | *.rdl.data
226 | *.bim.layout
227 | *.bim_*.settings
228 |
229 | # Microsoft Fakes
230 | FakesAssemblies/
231 |
232 | # GhostDoc plugin setting file
233 | *.GhostDoc.xml
234 |
235 | # Node.js Tools for Visual Studio
236 | .ntvs_analysis.dat
237 | node_modules/
238 |
239 | # Typescript v1 declaration files
240 | typings/
241 |
242 | # Visual Studio 6 build log
243 | *.plg
244 |
245 | # Visual Studio 6 workspace options file
246 | *.opt
247 |
248 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
249 | *.vbw
250 |
251 | # Visual Studio LightSwitch build output
252 | **/*.HTMLClient/GeneratedArtifacts
253 | **/*.DesktopClient/GeneratedArtifacts
254 | **/*.DesktopClient/ModelManifest.xml
255 | **/*.Server/GeneratedArtifacts
256 | **/*.Server/ModelManifest.xml
257 | _Pvt_Extensions
258 |
259 | # Paket dependency manager
260 | .paket/paket.exe
261 | paket-files/
262 |
263 | # FAKE - F# Make
264 | .fake/
265 |
266 | # JetBrains Rider
267 | .idea/
268 | *.sln.iml
269 |
270 | # CodeRush
271 | .cr/
272 |
273 | # Python Tools for Visual Studio (PTVS)
274 | __pycache__/
275 | *.pyc
276 |
277 | # Cake - Uncomment if you are using it
278 | # tools/**
279 | # !tools/packages.config
280 |
281 | # Telerik's JustMock configuration file
282 | *.jmconfig
283 |
284 | # BizTalk build output
285 | *.btp.cs
286 | *.btm.cs
287 | *.odx.cs
288 | *.xsd.cs
289 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 CrossGeeks
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Azure Push Notification Plugin for Xamarin iOS and Android
2 |
3 | [](https://dev.azure.com/CrossGeeks/Plugins/_build/latest?definitionId=10&branchName=master)
4 |
5 | Simple cross platform plugin for handling azure notification hub push notifications.
6 |
7 | ### Setup
8 | * Available on NuGet: http://www.nuget.org/packages/Plugin.AzurePushNotification [](https://www.nuget.org/packages/Plugin.AzurePushNotification/)
9 | * Install into your .NETStandard project and Client projects.
10 |
11 | **Platform Support**
12 |
13 | |Platform|Version|
14 | | ------------------- | :------------------: |
15 | |Xamarin.iOS|iOS 8+|
16 | |Xamarin.Android|API 15+|
17 |
18 | ### API Usage
19 |
20 | Call **CrossAzurePushNotification.Current** from any project to gain access to APIs.
21 |
22 | ## Features
23 |
24 | - Receive push notifications
25 | - Tag registration
26 | - Support for push notification category actions
27 | - Customize push notifications
28 | - Localization
29 |
30 |
31 | ## Documentation
32 |
33 | Here you will find detailed documentation on setting up and using the Azure Push Notification Plugin for Xamarin
34 |
35 | * [Getting Started](docs/GettingStarted.md)
36 | * [Receiving Push Notifications](docs/ReceivingNotifications.md)
37 | * [Android Customization](docs/AndroidCustomization.md)
38 | * [iOS Customization](docs/iOSCustomization.md)
39 | * [Notification Category Actions](docs/NotificationActions.md)
40 | * [Notification Localization](docs/LocalizedPushNotifications.md)
41 | * [FAQ](docs/FAQ.md)
42 |
43 | #### Contributors
44 |
45 | * [Rendy Del Rosario](https://github.com/rdelrosario)
46 | * [Charlin Agramonte](https://github.com/char0394)
47 | * [Alberto Florenzan](https://github.com/aflorenzan)
48 | * [Angel Andres Mañon](https://github.com/AngelAndresM)
49 | * [Tymen Steur](https://github.com/TymenSteur)
50 | * [Mircea-Tiberiu MATEI](https://github.com/matei-tm)
51 | * [Pier-Lionel Sgard](https://github.com/plsgard)
52 | * [Peseur](https://github.com/Peseur)
53 | * [Zain Ahmad Khan](https://github.com/zainniazi)
54 |
--------------------------------------------------------------------------------
/art/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/AzurePushNotificationPlugin/31fa9e9062fcae30881a86caa7753c6ab2777ca2/art/icon.png
--------------------------------------------------------------------------------
/cd-pipeline.yml:
--------------------------------------------------------------------------------
1 | variables:
2 | MONO_VERSION: 6_4_0
3 | NETCORE_VERSION: '3.0.x'
4 |
5 | # set the version numbering, this results in 1.0.1 for the first build incrementing that way.
6 | name: 2.1$(rev:.r)
7 |
8 | # Defines that a commit to the master branch should trigger this build
9 | trigger:
10 | - master
11 |
12 | # Defines that PRs against this branch should also trigger this build
13 | pr:
14 | - master
15 |
16 | # the machine and prerequisites to run this build on
17 | pool:
18 | vmImage: macOS-latest
19 |
20 | # The different steps in our build
21 | steps:
22 |
23 | - bash: sudo $AGENT_HOMEDIRECTORY/scripts/select-xamarin-sdk.sh $(MONO_VERSION)
24 | displayName: Switch to the latest Xamarin SDK
25 |
26 | - task: UseDotNet@2
27 | displayName: 'Use .Net Core sdk'
28 | inputs:
29 | version: $(NETCORE_VERSION)
30 | includePreviewVersions: false
31 |
32 | # build and pack a beta version of the NuGet package. Versioning is done through the name tag in this definition.
33 | - task: MSBuild@1
34 | displayName: 'Build & Pack beta build'
35 | inputs:
36 | solution: 'src/Plugin.AzurePushNotification/Plugin.AzurePushNotification.csproj'
37 | configuration: 'Release'
38 | msbuildArguments: '/restore /t:Build /p:ContinuousIntegrationBuild=true /p:Deterministic=false /t:Pack /p:PackageVersion=$(Build.BuildNumber)-beta /p:PackageOutputPath=$(build.artifactstagingdirectory)/beta /p:AssemblyFileVersion=$(Build.BuildNumber)'
39 | clean: true
40 |
41 | # build and pack a final version of the NuGet package. Versioning is done through the name tag in this definition.
42 | - task: MSBuild@1
43 | displayName: 'Build & Pack final build'
44 | inputs:
45 | solution: 'src/Plugin.AzurePushNotification/Plugin.AzurePushNotification.csproj'
46 | configuration: 'Release'
47 | msbuildArguments: '/restore /t:Build /p:ContinuousIntegrationBuild=true /p:Deterministic=false /t:Pack /p:PackageVersion=$(Build.BuildNumber) /p:PackageOutputPath=$(build.artifactstagingdirectory)/final /p:AssemblyFileVersion=$(Build.BuildNumber)'
48 | clean: true
49 |
50 | # copy all the nupkg files created to the artifact directory
51 | - task: CopyFiles@2
52 | displayName: 'Copy Files to: $(build.artifactstagingdirectory)'
53 | inputs:
54 | SourceFolder: '$(build.sourcesdirectory)'
55 | Contents: '**\*.nupkg'
56 | TargetFolder: '$(build.artifactstagingdirectory)'
57 |
58 | # publish the artifacts as results of the build
59 | - task: PublishBuildArtifacts@1
60 | displayName: 'Publish Artifact: drop'
61 |
--------------------------------------------------------------------------------
/ci-pipeline.yml:
--------------------------------------------------------------------------------
1 | variables:
2 | MONO_VERSION: 6_4_0
3 | NETCORE_VERSION: '3.0.x'
4 | XCODE_VERSION: 11.1
5 |
6 | # Starter pipeline
7 | # Start with a minimal pipeline that you can customize to build and deploy your code.
8 | # Add steps that build, run tests, deploy, and more:
9 | # https://aka.ms/yaml
10 |
11 | # Defines that a commit to the master branch should trigger this build
12 | trigger:
13 | - master
14 |
15 | # Defines that PRs against this branch should also trigger this build
16 | pr:
17 | - master
18 |
19 | # The type of machine this build should run on and what software should be on it
20 | pool:
21 | vmImage: macos-10.14
22 |
23 | # The different steps in our build
24 | steps:
25 |
26 | - bash: sudo $AGENT_HOMEDIRECTORY/scripts/select-xamarin-sdk.sh $(MONO_VERSION)
27 | displayName: Switch to the latest Xamarin SDK
28 |
29 | - bash: echo '##vso[task.setvariable variable=MD_APPLE_SDK_ROOT;]'/Applications/Xcode_$(XCODE_VERSION).app;sudo xcode-select --switch /Applications/Xcode_$(XCODE_VERSION).app/Contents/Developer
30 | displayName: Switch to the latest Xcode
31 |
32 | - task: UseDotNet@2
33 | displayName: 'Use .Net Core sdk'
34 | inputs:
35 | version: $(NETCORE_VERSION)
36 | includePreviewVersions: false
37 |
38 | - task: MSBuild@1
39 | displayName: 'Build solution'
40 | inputs:
41 | solution: 'src/**/*.sln'
42 | msbuildArguments: '/restore /t:Build /p:ContinuousIntegrationBuild=true /p:Deterministic=false /p:PackageOutputPath=$(build.artifactstagingdirectory)'
43 | clean: true
44 |
--------------------------------------------------------------------------------
/docs/AndroidCustomization.md:
--------------------------------------------------------------------------------
1 | ## Android Specific Customization
2 |
3 | You can set the activity to be launched when you tap on the notification on Android project by setting **AzurePushNotificationManager.NotificationActivityType**
4 |
5 | Usage sample:
6 |
7 | ```csharp
8 | AzurePushNotificationManager.NotificationActivityType = typeof(MainActivity);
9 | ```
10 |
11 | **Note: Uses application main launcher activity if the above is not set.**
12 |
13 | You can also set the flags for launching this activity with **AzurePushNotificationManager.NotificationActivityFlags** by default is set to:
14 |
15 | ```csharp
16 | AzurePushNotificationManager.NotificationActivityFlags = ActivityFlags.ClearTop | ActivityFlags.SingleTop
17 | ```
18 |
19 | ### Static customization properties
20 |
21 | If plugin is not initialized with a push handler on Android by default the plugin uses the default push notification handler to create the notification ui & actions support when sending **Data messages**.
22 |
23 | By using the default push notification handler. There are a few things you can configure in Android project using the following static properties of **AzurePushNotificationManager** class:
24 |
25 | ```csharp
26 |
27 | //Sets the key associated with the value will be look for in the notification payload to be used to show the title for the notification
28 | public static string NotificationContentTitleKey { get; set; }
29 |
30 | //Sets the key associated with the value will look for in the notification payload to be used to show the text for the notification
31 | public static string NotificationContentTextKey { get; set; }
32 |
33 | //Sets the resource id for the icon will be used for the notification
34 | public static int IconResource { get; set; }
35 |
36 | //Sets the sound uri will be used for the notification
37 | public static Android.Net.Uri SoundUri { get; set; }
38 |
39 | //Sets the color will be used for the notification
40 | public static Color? Color { get; set; }
41 |
42 | //Sets the default notification channel id for Android O
43 | public static string DefaultNotificationChannelId { get; set; } = "PushNotificationChannel";
44 |
45 | //Sets the default notification channel name for Android O
46 | public static string DefaultNotificationChannelName { get; set; } = "General";
47 |
48 | ```
49 |
50 | If **AzurePushNotificationManager.IconResource** not set will use default application icon.
51 |
52 | If **AzurePushNotificationManager.SoundUri** not set will use the default notification ringtone.
53 |
54 | If **NotificationContentTitleKey** not set will look for **title** key value in the notification payload to set the title. If no title key present will use the application name as the notification title.
55 |
56 | If **NotificationContentTextKey** not set will look for one of the following keys value in the notification payload using the priority order shown below to set the message for the notification:
57 |
58 | 1. **alert**
59 | 2. **body**
60 | 3. **message**
61 | 4. **subtitle**
62 | 5. **text**
63 | 6. **title**
64 |
65 | Once one of the above keys is found on the notification data message payload will show it's value as the notification message.
66 |
67 |
68 | ### Payload Keys
69 |
70 | There are also some keys you can set on the payload:
71 |
72 | * **id** : Sets the notification id
73 | * **tag** : Sets the notification tag
74 | * **priority** : Sets the notification priority
75 | * **sound** : Sets the notification sound
76 | * **icon** : Sets the notification icon
77 | * **large_icon** : Sets the notification large icon
78 | * **click_action** : Sets name for the notification action
79 | * **channel_id** : Sets id for the notification channel that will be used when notification is delivered
80 |
81 | If **sound** or **icon** keys present have priority over the **AzurePushNotificationManager.SoundUri** and **AzurePushNotificationManager.IconResource** static customization properties mentioned above.
82 |
83 | ##### Notification Id
84 |
85 | * **id** key is set as the notification id if present (integer value).
86 |
87 |
88 | Payload sample with id
89 |
90 | ```json
91 | {
92 | "data" : {
93 | "title": "hello",
94 | "body": "world",
95 | "id": 1
96 | }
97 | }
98 | ```
99 |
100 | ##### Notification Tag
101 |
102 | * **tag** key is set as the notification tag if present.
103 |
104 | Payload sample with id and tag
105 |
106 | ```json
107 | {
108 | "data" : {
109 | "title": "hello",
110 | "body": "world",
111 | "id": 1,
112 | "tag" : "msg"
113 |
114 | }
115 | }
116 |
117 |
118 | ```
119 | ##### Notification without UI
120 |
121 | * If you send a key called **silent** with value true it won't display a notification.
122 |
123 | Silent notification payload sample
124 |
125 | ```json
126 | {
127 | "data" : {
128 | "title": "hello",
129 | "body": "world",
130 | "silent":"true"
131 | }
132 | }
133 | ```
134 |
135 | * For notification with actions will look for **click_action** key value as the match. More information here: [Notification Actions](NotificationActions.md)
136 |
137 |
138 | ##### Notification Priority
139 |
140 | * Depending on the value of **priority** key in your data payload. It will set the notification priority. Posible values are: "max", "high","default","low","min".
141 |
142 | The behaviour for these values:
143 |
144 | **MAX** - Use for critical and urgent notifications that alert the user to a condition that is time-critical or needs to be resolved before they can continue with a particular task.
145 |
146 | **HIGH** - Use primarily for important communication, such as message or chat events with content that is particularly interesting for the user. High-priority notifications trigger the heads-up notification display.
147 |
148 | **DEFAULT** - Use for all notifications that don't fall into any of the other priorities described here and if the application does not prioritize its own notifications
149 |
150 | **LOW** - Use for notifications that you want the user to be informed about, but that are less urgent. Low-priority notifications tend to show up at the bottom of the list, which makes them a good choice for things like public or undirected social updates: The user has asked to be notified about them, but these notifications should never take precedence over urgent or direct communication.
151 |
152 | **MIN** - Use for contextual or background information such as weather information or contextual location information. Minimum-priority notifications do not appear in the status bar. The user discovers them on expanding the notification shade.
153 |
154 | If no priority is set then "priority" is default.
155 |
156 | For heads-up notification send inside your payload data key "priority" : "high" within your other keys:
157 |
158 | Sample payload with priority
159 |
160 | ```json
161 | {
162 | "data" : {
163 | "title": "hello",
164 | "body": "world",
165 | "priority":"high"
166 | }
167 | }
168 | ```
169 | ##### Notification Sound
170 |
171 | * You can send sound by using **sound** key, a sound with the value set should be in your *Resources/raw* folder.
172 |
173 | Payload sample with sound
174 | ```json
175 | {
176 | "data" : {
177 | "title": "hello",
178 | "body": "world",
179 | "priority":"high",
180 | "sound":"test"
181 | }
182 | }
183 | ```
184 | If sound not set will set the **AzurePushNotificationManager.SoundUri** value if not set either will use the default notification ringtone.
185 |
186 | ##### Notification Icon
187 |
188 | * You can send the icon to be displayed on the notification by using **icon** key, an icon with the value set should be in your *Resources/drawable* folder.
189 |
190 | Payload sample with icon
191 |
192 | ```json
193 | {
194 | "data" : {
195 | "title": "hello",
196 | "body": "world",
197 | "priority":"high",
198 | "icon":"test"
199 | }
200 | }
201 | ```
202 |
203 | Payload sample with icon and sound
204 |
205 | ```json
206 | {
207 | "data" : {
208 | "title": "hello",
209 | "body": "world",
210 | "priority":"high",
211 | "icon":"test",
212 | "sound":"test"
213 | }
214 | }
215 | ```
216 |
217 | If icon not set will set the **AzurePushNotificationManager.IconResource** value if not set either will use the default application icon.
218 |
219 |
220 | ##### Notification Large Icon
221 |
222 | * You can send the large_icon to be displayed on the notification by using **large_icon** key, an icon with the value set should be in your *Resources/drawable* folder.
223 |
224 | Payload sample with large icon
225 |
226 | ```json
227 | {
228 | "data" : {
229 | "title": "hello",
230 | "body": "world",
231 | "priority":"high",
232 | "large_icon":"test"
233 | }
234 | }
235 | ```
236 |
237 | Payload sample with large icon and sound
238 |
239 | ```json
240 | {
241 | "data" : {
242 | "title": "hello",
243 | "body": "world",
244 | "priority":"high",
245 | "large_icon":"test",
246 | "sound":"test"
247 | }
248 | }
249 | ```
250 |
251 | If large icon not set will set the **AzurePushNotificationManager.LargeIconResource** value.
252 |
253 |
254 | ##### Notification Actions
255 |
256 | * For notification with actions will look for **click_action** key value as the match. More information here: [Notification Actions](NotificationActions.md)
257 |
258 | ##### Notification Channel Id
259 |
260 | * **channel_id** key is set as the notification channel id if present will use that specified notification channel for this notification.
261 |
262 | Payload sample with id and tag
263 |
264 | ```json
265 | {
266 | "data" : {
267 | "title": "hello",
268 | "body": "firebase",
269 | "channel_id" : "PushNotificationChannel"
270 |
271 | }
272 | }
273 | ```
274 |
275 | <= Back to [Table of Contents](../README.md)
276 |
277 |
--------------------------------------------------------------------------------
/docs/FAQ.md:
--------------------------------------------------------------------------------
1 | ## FAQ
2 |
3 | ### Android
4 |
5 | 1. Getting java.lang.IllegalStateException: Default FirebaseApp is not initialized in this process {your_package_name}.
6 |
7 | **Solution 1:**
8 |
9 | Make sure the google-services.json has the GoogleServicesJson build action
10 |
11 | **Solution 2:**
12 |
13 | Make sure your firebase android app package name is the same package name on your Android project.
14 |
15 | 2. Android initialization should be done on and Android Application class to be able to handle received notifications when application is closed. Since no activity exist when application is closed.
16 |
17 | 3. You won't receive any push notifications if application is stopped while debugging, should reopen and close again for notifications to work when app closed. This is due to the application being on an unstable state when stopped while debugging.
18 |
19 | 4. On some phones android background services might be blocked by some application. This is the case of ASUS Zenfone 3 that has an Auto-start manager, which disables background services by default. You need to make sure that your push notification service is not being blocked by some application like this one, since you won't receive push notifications when app is closed if so.
20 |
21 | 5. Must compile against 26+ as plugin is using API 26 specific things. Here is a great breakdown: http://redth.codes/such-android-api-levels-much-confuse-wow/ (Android project must be compiled using 8.0+ target framework)
22 |
23 | 6. The package name of your Android aplication must start with lower case or you will get the build error: Installation error: INSTALL_PARSE_FAILED_MANIFEST_MALFORMED
24 |
25 | 7. Make sure you have updated your Android SDK Manager libraries:
26 |
27 | 
28 |
29 | 9. Error 1589 NotificationService Not posting notification without small icon
30 | It happen when the message is received, but the notification isn't displayed. If you got this error, it mean you need to tell which one is your app icon on Android Project Properties > Android Manifest > application Icon or in the AndroidManifext.xml file and put android:icon="@drawable/{replace with your icon file name}" in the
31 |
32 |
33 | ...
34 |
35 |
--------------------------------------------------------------------------------
/docs/GettingStarted.md:
--------------------------------------------------------------------------------
1 | ## Starting with Android
2 |
3 | ### Android Configuration
4 |
5 | First, make sure you setup everthing on Firebase portal and Azure portal.
6 |
7 | Also add this permission:
8 |
9 | ```xml
10 |
11 | ```
12 |
13 | Add google-services.json to Android project. Make sure build action is GoogleServicesJson
14 |
15 | 
16 |
17 | Must compile against 26+ as plugin is using API 26 specific things. Here is a great breakdown: http://redth.codes/such-android-api-levels-much-confuse-wow/ (Android project must be compiled using 8.0+ target framework)
18 |
19 | ### Android Initialization
20 |
21 | You should initialize the plugin on an Android Application class if you don't have one on your project, should create an application class. Then call **AzurePushNotificationManager.Initialize** method on OnCreate.
22 |
23 | There are 3 overrides to **AzurePushNotificationManager.Initialize**:
24 |
25 | - **AzurePushNotificationManager.Initialize(Context context,string notificationHubConnectionString,string notificationHubPathName, bool resetToken,bool autoRegistration)** : Default method to initialize plugin without supporting any user notification categories. Uses a DefaultPushHandler to provide the ui for the notification.
26 |
27 | - **AzurePushNotificationManager.Initialize(Context context,string notificationHubConnectionString,string notificationHubPathName, NotificationUserCategory[] categories, bool resetToken,bool autoRegistration)** : Initializes plugin using user notification categories. Uses a DefaultPushHandler to provide the ui for the notification supporting buttons based on the action_click send on the notification
28 |
29 | - **AzurePushNotificationManager.Initialize(Context context,string notificationHubConnectionString,string notificationHubPathName,IPushNotificationHandler pushHandler, bool resetToken,bool autoRegistration)** : Initializes the plugin using a custom push notification handler to provide custom ui and behaviour notifications receipt and opening.
30 |
31 | **Important: While debugging set resetToken parameter to true.**
32 |
33 | Example of initialization:
34 |
35 | ```csharp
36 |
37 | [Application]
38 | public class MainApplication : Application
39 | {
40 | public MainApplication(IntPtr handle, JniHandleOwnership transer) :base(handle, transer)
41 | {
42 | }
43 |
44 | public override void OnCreate()
45 | {
46 | base.OnCreate();
47 |
48 | //Set the default notification channel for your app when running Android Oreo
49 | if (Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O)
50 | {
51 | //Change for your default notification channel id here
52 | AzurePushNotificationManager.DefaultNotificationChannelId = "DefaultChannel";
53 |
54 | //Change for your default notification channel name here
55 | AzurePushNotificationManager.DefaultNotificationChannelName = "General";
56 | }
57 |
58 | //If debug you should reset the token each time.
59 | #if DEBUG
60 | AzurePushNotificationManager.Initialize(this,"Notification Hub Connection String","Notification Hub Path Name",true);
61 | #else
62 | AzurePushNotificationManager.Initialize(this,"Notification Hub Connection String","Notification Hub Path Name",false);
63 | #endif
64 |
65 | //Handle notification when app is closed here
66 | CrossAzurePushNotification.Current.OnNotificationReceived += (s,p) =>
67 | {
68 |
69 |
70 | };
71 |
72 |
73 | }
74 | }
75 |
76 | ```
77 |
78 | By default the plugin launches the main launcher activity when you tap at a notification, but you can change this behaviour by setting the type of the activity you want to be launch on **AzurePushNotificationManager.NotificationActivityType**
79 |
80 | If you set **AzurePushNotificationManager.NotificationActivityType** then put the following call on the **OnCreate** of activity of the type set. If not set then put it on your main launcher activity **OnCreate** method (On the Activity you got MainLauncher= true set)
81 |
82 | ```csharp
83 | protected override void OnCreate(Bundle bundle)
84 | {
85 | base.OnCreate(bundle);
86 |
87 | //Other initialization stuff
88 |
89 | AzurePushNotificationManager.ProcessIntent(this,Intent);
90 | }
91 |
92 | ```
93 |
94 | **Note: When using Xamarin Forms do it just after LoadApplication call.**
95 |
96 | By default the plugin launches the activity where **ProcessIntent** method is called when you tap at a notification, but you can change this behaviour by setting the type of the activity you want to be launch on **AzurePushNotificationManager.NotificationActivityType**
97 |
98 | You can change this behaviour by setting **AzurePushNotificationManager.NotificationActivityFlags**.
99 |
100 | If you set **AzurePushNotificationManager.NotificationActivityFlags** to ActivityFlags.SingleTop or using default plugin behaviour then make this call on **OnNewIntent** method of the same activity on the previous step.
101 |
102 | ```csharp
103 | protected override void OnNewIntent(Intent intent)
104 | {
105 | base.OnNewIntent(intent);
106 | AzurePushNotificationManager.ProcessIntent(this,intent);
107 | }
108 | ```
109 |
110 | More information on **AzurePushNotificationManager.NotificationActivityType** and **AzurePushNotificationManager.NotificationActivityFlags** and other android customizations here:
111 |
112 | [Android Customization](../docs/AndroidCustomization.md)
113 |
114 | ## Starting with iOS
115 |
116 | First, make sure you set everything on Apple Developer Portal and Azure portal. You can follow this guide:
117 |
118 | https://docs.microsoft.com/en-us/azure/notification-hubs/notification-hubs-push-notification-http2-token-authentification
119 |
120 | ### iOS Configuration
121 |
122 | On Info.plist enable remote notification background mode
123 |
124 | 
125 |
126 | ### iOS Initialization
127 |
128 | There are 3 overrides to **AzurePushNotificationManager.Initialize**:
129 |
130 | - **AzurePushNotificationManager.Initialize(string notificationHubConnectionString,string notificationHubPathName, NSDictionary options,bool autoRegistration,bool autoRegistration, bool enableDelayedResponse)** : Default method to initialize plugin without supporting any user notification categories. Auto registers for push notifications if second parameter is true.
131 |
132 | - **AzurePushNotificationManager.Initialize(string notificationHubConnectionString,string notificationHubPathName,NSDictionary options, NotificationUserCategory[] categories,bool autoRegistration, bool enableDelayedResponse)** : Initializes plugin using user notification categories to support iOS notification actions.
133 |
134 | - **AzurePushNotificationManager.Initialize(string notificationHubConnectionString,string notificationHubPathName,NSDictionary options,IPushNotificationHandler pushHandler,bool autoRegistration, bool enableDelayedResponse)** : Initializes the plugin using a custom push notification handler to provide native feedback of notifications event on the native platform.
135 |
136 |
137 | Call **AzurePushNotificationManager.Initialize** on AppDelegate FinishedLaunching
138 | ```csharp
139 |
140 | AzurePushNotificationManager.Initialize("Notification Hub Connection String","Notification Hub Path Name",options,true);
141 |
142 | ```
143 | **Note: When using Xamarin Forms do it just after LoadApplication call.**
144 |
145 | Also should override these methods and make the following calls:
146 | ```csharp
147 | public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
148 | {
149 | AzurePushNotificationManager.DidRegisterRemoteNotifications(deviceToken);
150 | }
151 |
152 | public override void FailedToRegisterForRemoteNotifications(UIApplication application, NSError error)
153 | {
154 | AzurePushNotificationManager.RemoteNotificationRegistrationFailed(error);
155 |
156 | }
157 | // To receive notifications in foregroung on iOS 9 and below.
158 | // To receive notifications in background in any iOS version
159 | public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action completionHandler)
160 | {
161 |
162 | AzurePushNotificationManager.DidReceiveMessage(userInfo);
163 | }
164 |
165 |
166 | ```
167 |
168 |
169 | ## Using Push Notification APIs
170 | It is drop dead simple to gain access to the PushNotification APIs in any project. All you need to do is get a reference to the current instance of IPushNotification via `CrossPushNotification.Current`:
171 |
172 | Register tags
173 |
174 | ```csharp
175 | ///
176 | /// Registers tags in Azure Notification hub
177 | ///
178 | await CrossAzurePushNotification.Current.RegisterAsync(new string[]{"crossgeeks","general"});
179 | ```
180 |
181 | Note: The method above cleans all previous registered tags when called. So it kind of replaces the tags each time you call it.
182 |
183 | Unregister tags
184 |
185 | ```csharp
186 | ///
187 | /// Unregister all tags in Azure Notification hub
188 | ///
189 | await CrossAzurePushNotification.Current.UnregisterAsync();
190 | ```
191 |
192 | ### On Demand Registration
193 |
194 | When plugin initializes by default auto request permission the device for push notifications. If needed you can do on demand permisssion registration by turning off auto registration when initializing the plugin.
195 |
196 | Use the following method for on demand permission registration:
197 |
198 | ```csharp
199 | CrossAzurePushNotification.Current.RegisterForPushNotifications();
200 | ```
201 |
202 |
203 | ### Events
204 |
205 | Once token is registered/refreshed you will get it on **OnTokenRefresh** event.
206 |
207 |
208 | ```csharp
209 | ///
210 | /// Event triggered when token is refreshed
211 | ///
212 | event AzurePushNotificationTokenEventHandler OnTokenRefresh;
213 | ```
214 |
215 | Note: Don't call **RegisterAsync** in the event above because it is called automatically each time the token changes
216 |
217 | ```csharp
218 | ///
219 | /// Event triggered when a notification is received
220 | ///
221 | event AzurePushNotificationResponseEventHandler OnNotificationReceived;
222 | ```
223 |
224 |
225 | ```csharp
226 | ///
227 | /// Event triggered when a notification is opened
228 | ///
229 | event AzurePushNotificationResponseEventHandler OnNotificationOpened;
230 | ```
231 |
232 | ```csharp
233 | ///
234 | /// Event triggered when a notification is deleted (Android Only)
235 | ///
236 | event AzurePushNotificationDataEventHandler OnNotificationDeleted;
237 | ```
238 |
239 | ```csharp
240 | ///
241 | /// Event triggered when there's an error
242 | ///
243 | event AzurePushNotificationErrorEventHandler OnNotificationError;
244 | ```
245 |
246 | Token event usage sample:
247 | ```csharp
248 |
249 | CrossAzurePushNotification.Current.OnTokenRefresh += (s,p) =>
250 | {
251 | System.Diagnostics.Debug.WriteLine($"TOKEN : {p.Token}");
252 | };
253 |
254 | ```
255 |
256 | Push message received event usage sample:
257 | ```csharp
258 |
259 | CrossAzurePushNotification.Current.OnNotificationReceived += (s,p) =>
260 | {
261 |
262 | System.Diagnostics.Debug.WriteLine("Received");
263 |
264 | };
265 |
266 | ```
267 |
268 | Push message opened event usage sample:
269 | ```csharp
270 |
271 | CrossAzurePushNotification.Current.OnNotificationOpened += (s,p) =>
272 | {
273 | System.Diagnostics.Debug.WriteLine("Opened");
274 | foreach(var data in p.Data)
275 | {
276 | System.Diagnostics.Debug.WriteLine($"{data.Key} : {data.Value}");
277 | }
278 |
279 | if(!string.IsNullOrEmpty(p.Identifier))
280 | {
281 | System.Diagnostics.Debug.WriteLine($"ActionId: {p.Identifier}");
282 | }
283 |
284 | };
285 | ```
286 | Push message deleted event usage sample: (Android Only)
287 | ```csharp
288 |
289 | CrossAzurePushNotification.Current.OnNotificationDeleted+= (s,p) =>
290 | {
291 |
292 | System.Diagnostics.Debug.WriteLine("Deleted");
293 |
294 | };
295 |
296 | ```
297 |
298 | Plugin by default provides some notification customization features for each platform. Check out the [Android Customization](AndroidCustomization.md) and [iOS Customization](iOSCustomization.md) sections.
299 |
300 | <= Back to [Table of Contents](../README.md)
301 |
--------------------------------------------------------------------------------
/docs/LocalizedPushNotifications.md:
--------------------------------------------------------------------------------
1 | ## Localized Push Notifications
2 |
3 | When having an application available in multiple countries is very common to have multilingual support to provide the best user experience posible. That's why we provided this guide in case you need support for localization on your push notifications.
4 |
5 | ### iOS - Push Notifications Localization
6 |
7 | On iOS push notifications are associated with iOS default platform localization.
8 |
9 | > If you use a consistent set of messages for your notifications, you can store localized versions of the message text in your app bundle and use the loc-key and loc-args keys in your payload to specify which message to display. The loc-key and loc-args keys define the message content of the notification. When present, the local system searches the app’s Localizable.strings files for a key string matching the value in loc-key. It then uses the corresponding value from the strings file as the basis for the message text, replacing any placeholder values with the strings specified by the loc-args key. (You can also specify a title string for the notification using the title-loc-key and title-loc-args keys.). [Apple documentation](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CreatingtheNotificationPayload.html#//apple_ref/doc/uid/TP40008194-CH10-SW9)
10 |
11 | So you can use iOS default platform localization by following this brief guide:
12 |
13 | On the iOS project you have to add **Localizable.strings** (Build action for these files should be Bundle Resource) for each language you need to support. This is the file where you will define your keys and values based on the language.
14 |
15 | These files are organized by language, in specially named directories with an **.lproj** suffix.
16 |
17 | **Base.lproj** is the directory that contains resources for the default language. It is often located in the project root (but can also be placed in the Resources folder).
18 |
19 | **.lproj** directories are created for each supported language, usually in the Resources folder.
20 |
21 | Once you add this files your structure should look similar to this:
22 |
23 | 
24 |
25 | This is an example Base.lproj/Localizable.strings (default language) file:
26 |
27 | ```
28 | "NOTIFICATION_TITLE" = "Hello World";
29 | "NOTIFICATION_MESSAGE" = "This is a message";
30 | ```
31 |
32 |
33 | This is an example es.lproj/Localizable.strings (ie. Spanish) file:
34 |
35 | ```
36 | "NOTIFICATION_TITLE" = "Hola Mundo";
37 | "NOTIFICATION_MESSAGE" = "Esto es un mensaje";
38 | ```
39 |
40 | On the payload instead of using **title** and **message** keys, we will use **title-loc-key** to represent the key for our localized title and **loc-key** to represent the key for our localized message.
41 |
42 | Finally, when sending the payload would look like this:
43 |
44 | ```json
45 | {
46 | "aps" : {
47 | "alert" : {
48 | "title-loc-key" : "NOTIFICATION_TITLE",
49 | "loc-key" : "NOTIFICATION_MESSAGE"
50 | }
51 | }
52 | }
53 | ```
54 |
55 | That works out just fine for a static message but if you have variable parameters in the content then you will need some extra keys on your payloads and define the value for your Localizable.strings differently. Let's say my payload have variable content on the title and message, then there are two additional keys we need to add **title-loc-args** (represents the variable parameters for the title) and **loc-args** (represents the variable parameters for the message).
56 |
57 | ```json
58 | {
59 | "aps" : {
60 | "alert" : {
61 | "title-loc-key" : "NOTIFICATION_TITLE",
62 | "loc-key" : "NOTIFICATION_MESSAGE",
63 | "title-loc-args" : ["Dominican Republic"],
64 | "loc-args" : ["Rendy"]
65 | }
66 | }
67 | }
68 | ```
69 | Each of this two payload keys is a string array so you can have as many string arguments as you need. Here's how should **Localizable.strings** files look like when using arguments:
70 |
71 | This is an example Base.lproj/Localizable.strings (default language) file:
72 |
73 | ```
74 | "NOTIFICATION_TITLE" = "Hello %@";
75 | "NOTIFICATION_MESSAGE" = "This is a message for %@";
76 | ```
77 |
78 |
79 | This is an example es.lproj/Localizable.strings (ie. Spanish) file:
80 |
81 | ```
82 | "NOTIFICATION_TITLE" = "Hola %@";
83 | "NOTIFICATION_MESSAGE" = "Esto es un mensaje para %@";
84 | ```
85 | Each %@ represents a parameter or parameters if more than one.
86 |
87 |
88 | More information on iOS localization here:
89 |
90 | [Apple Remote Notifications Localization](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CreatingtheNotificationPayload.html#//apple_ref/doc/uid/TP40008194-CH10-SW9)
91 |
92 | [Xamarin iOS Localization](https://developer.xamarin.com/guides/ios/advanced_topics/localization_and_internationalization/)
93 |
94 |
95 | ### Android - Push Notifications Localization
96 |
97 | On Android the plugin has localization support by default using Android platform localization. Uses specific keys to be sent on the payload that will then be resolved with values on string files depending on the android language set to the device.
98 |
99 | First, you have to add a **strings.xml** (Build action for these files should be Android Resource) for each language you need to support. This is the file where you will define your keys and values based on the language.
100 |
101 | These files are organized by language, in specially named directories with an **values** and a language suffix (For example values-en, values-fr, values-es). Naming must conform specifications on [AlternativeResources](https://developer.android.com/guide/topics/resources/providing-resources.html#AlternativeResources).
102 |
103 | **values**: without any suffix is the directory that contains resources for the default language. Placed in the Resources folder.
104 |
105 | **values-{language code}**: directories are created for each supported language, placed in the Resources folder. Examples : **values-ja**, **values-fr**, **values-es**.
106 |
107 | Notes:
108 |
109 | - If device set to a language that has a strings.xml file (ex. Resources/values-es/strings.xml) and have the requested key defined in this file then will use the value for this file.
110 | - If device set to a language that doesn't have strings.xml file then will fallback to default string.xml on **values** without suffix.
111 | - If device set to a language that has a strings.xml file (ex. Resources/values-es/strings.xml) but doesn't have a specific key requested then will fallback to default string.xml on **values** without suffix to look for this key/value.
112 |
113 |
114 | Example:
115 |
116 | Let's say we need to support 2 languages: English, Spanish. In this case, you could create two alternative strings.xml files, each stored in a locale-specific resource directory:
117 |
118 | 1. Resources/values/strings.xml (default file)
119 |
120 | ```xml
121 | Hello world
122 | This is a message
123 | ```
124 | 2. Resources/values-es/strings.xml (Spanish strings file)
125 |
126 | ```xml
127 | Hola mundo
128 | Esto es un mensaje
129 | ```
130 | On the payload instead of using **title** and **message** / **body** keys, we will use **title_loc_key** to represent the key for our localized title and **body_loc_key** to represent the key for our localized message.
131 |
132 | When sending the payload would look like this:
133 |
134 | ```json
135 | {
136 | "data": {
137 | "title_loc_key": "notification_title_string",
138 | "body_loc_key": "notification_message_string"
139 | },
140 | "priority": "high",
141 | "registration_ids" : ["eoPr8fUIPns:APA91bEVYODiWaL9a9JidumLRcFjVrEC4iHY80mHSE1e-udmPB32RjMiYL2P2vWTIUgYCJYVOx9SGSN_R4Ksau3vFX4WvkDj4ZstxqmcBhM3K-NMrX8P6U0sdDEqDpr-lD_N5JWBLCoV"]
142 | }
143 | ```
144 |
145 | When using parameters in the content you will need some extra keys on your payload and define the value for your strings.xml differently. Let's say the payload have variable content on the title and message, then there are two additional keys we need to add **title_loc_args** (represents the variable parameters for the title) and **body_loc_args** (represents the variable parameters for the message).
146 |
147 | ```json
148 | {
149 | "data": {
150 | "title_loc_key" : "notification_title_string",
151 | "body_loc_key" : "notification_message_string",
152 | "title_loc_args" : ["Dominican Republic"],
153 | "body_loc_args" : ["Rendy"]
154 | },
155 | "priority": "high",
156 | "registration_ids" : ["eoPr8fUIPns:APA91bEVYODiWaL9a9JidumLRcFjVrEC4iHY80mHSE1e-udmPB32RjMiYL2P2vWTIUgYCJYVOx9SGSN_R4Ksau3vFX4WvkDj4ZstxqmcBhM3K-NMrX8P6U0sdDEqDpr-lD_N5JWBLCoV"]
157 | }
158 | ```
159 |
160 | Each of this two payload keys is a string array so you can have as many string arguments as you need.
161 |
162 | Here's how should **strings.xml** files look like when using arguments:
163 |
164 | 1. Resources/values/strings.xml (default file)
165 |
166 | ```xml
167 | Hola %1$s
168 | Esto es un mensaje para %1$s
169 | ```
170 |
171 | 2. Resources/values-es/strings.xml (Spansih strings file)
172 |
173 | ```xml
174 | Hello %1$s
175 | This is a message for %1$s
176 | ```
177 |
178 | The format for parameter replacement is: %[parameter index]$[format type].
179 |
180 | - Parameter index: Starts at 1. For example, if you have 2 parameters: %1 and %2. The order you place them in the resource string doesn't matter, only the order that you supply the parameters.
181 | - Format type: Most common types are : $s (string), $d (decimal integer), $f (floating point number)
182 |
183 | More information on string format for parameter replacing here:
184 |
185 | [Dynamic string](https://stackoverflow.com/questions/3656371/dynamic-string-using-string-xml)
186 |
187 | [Formatting Resource Strings](https://code.tutsplus.com/tutorials/android-sdk-quick-tip-formatting-resource-strings--mobile-1775)
188 |
189 | More information on localization here:
190 |
191 | [Android Localization](https://developer.android.com/guide/topics/resources/localization.html)
192 |
193 | <= Back to [Table of Contents](../README.md)
194 |
195 |
--------------------------------------------------------------------------------
/docs/NotificationActions.md:
--------------------------------------------------------------------------------
1 | ## Notification Category Actions
2 |
3 | You can initialize the plugin with notification user categories to provide button options within the notification. Depending on the notification category received you can provide different button options.
4 |
5 | ### Notification User Category:
6 |
7 | Each notification user category can have it's own options
8 |
9 | ```csharp
10 | public class NotificationUserCategory
11 | {
12 | public string Category { get; }
13 |
14 | public List Actions { get; }
15 |
16 | public NotificationCategoryType Type { get; }
17 |
18 | public NotificationUserCategory(string category, List actions, NotificationCategoryType type = NotificationCategoryType.Default)
19 | {
20 | Category = category;
21 | Actions = actions;
22 | Type = type;
23 | }
24 | }
25 | ```
26 |
27 | ```csharp
28 | //This just applies for iOS on Android is always set as default when used
29 | public enum NotificationCategoryType
30 | {
31 | Default,
32 | Custom,
33 | Dismiss
34 | }
35 | ```
36 |
37 | ### Notification User Action:
38 |
39 | Each user action represents a button option of the notification user category
40 |
41 | ```csharp
42 | public class NotificationUserAction
43 | {
44 | public string Id { get; } // Action Identifier
45 |
46 | public string Title { get; } //Title to be displayed for the option
47 |
48 | public NotificationActionType Type { get; } //Determines the behaviour when action is executed
49 |
50 | public string Icon { get; } //Applies only for Android
51 |
52 | public NotificationUserAction(string id, string title, NotificationActionType type = NotificationActionType.Default, string icon = "")
53 | {
54 | Id = id;
55 | Title = title;
56 | Type = type;
57 | Icon = icon;
58 | }
59 | }
60 | ```
61 | There are a few types of notification user actions which determines the behaviour of it when the button option is tapped:
62 |
63 | ```csharp
64 | public enum NotificationActionType
65 | {
66 | Default,
67 | AuthenticationRequired, //Only applies for iOS
68 | Foreground,
69 | Destructive //Only applies for iOS
70 | }
71 | ```
72 |
73 | **Default** : When a button with this notification action type is tapped will handle the notification on background won't bring the application to foreground. Action will take place without launching the application.
74 |
75 | **Foreground** : When a button with this notification action type is tapped will bring the application to foreground and receive the notification once application is in foreground.
76 |
77 | **AuthenticationRequired** : If set the user needs to insert the unlock code to launch the action in background. This action is iOS specific will be ignored on Android.
78 |
79 | **Destructive** : Action button will have a red color. This action is iOS specific will be ignored on Android.
80 |
81 | ### Initialize using a User Category Notifications
82 |
83 | Android on **Application** class **OnCreate** method:
84 |
85 | ```csharp
86 | #if DEBUG
87 | AzurePushNotificationManager.Initialize(this,
88 | "Notification Hub Connection String",
89 | "Notification Hub Path Name",
90 | new NotificationUserCategory[]
91 | {
92 | new NotificationUserCategory("message",new List {
93 | new NotificationUserAction("Reply","Reply", NotificationActionType.Foreground),
94 | new NotificationUserAction("Forward","Forward", NotificationActionType.Foreground)
95 |
96 | }),
97 | new NotificationUserCategory("request",new List {
98 | new NotificationUserAction("Accept","Accept", NotificationActionType.Default, "check"),
99 | new NotificationUserAction("Reject","Reject", NotificationActionType.Default, "cancel")
100 | })
101 | }, true);
102 | #else
103 | AzurePushNotificationManager.Initialize(this,
104 | "Notification Hub Connection String",
105 | "Notification Hub Path Name",
106 | new NotificationUserCategory[]
107 | {
108 | new NotificationUserCategory("message",new List {
109 | new NotificationUserAction("Reply","Reply", NotificationActionType.Foreground),
110 | new NotificationUserAction("Forward","Forward", NotificationActionType.Foreground)
111 |
112 | }),
113 | new NotificationUserCategory("request",new List {
114 | new NotificationUserAction("Accept","Accept", NotificationActionType.Default, "check"),
115 | new NotificationUserAction("Reject","Reject", NotificationActionType.Default, "cancel")
116 | })
117 | }, false);
118 | #endif
119 |
120 | ```
121 |
122 | iOS on **AppDelegate** FinishLaunching:
123 |
124 | ```csharp
125 |
126 | AzurePushNotificationManager.Initialize(
127 | "Notification Hub Connection String",
128 | "Notification Hub Path Name",
129 | options,
130 | new NotificationUserCategory[]
131 | {
132 | new NotificationUserCategory("message",new List {
133 | new NotificationUserAction("Reply","Reply",NotificationActionType.Foreground)
134 | }),
135 | new NotificationUserCategory("request",new List {
136 | new NotificationUserAction("Accept","Accept"),
137 | new NotificationUserAction("Reject","Reject",NotificationActionType.Destructive)
138 | })
139 | });
140 |
141 | ```
142 |
143 | You will get the identifier of the action that was tapped on **OnNotificationOpened** event:
144 |
145 | ```csharp
146 | CrossAzurePushNotification.Current.OnNotificationOpened += (s,p) =>
147 | {
148 | System.Diagnostics.Debug.WriteLine("Opened");
149 |
150 |
151 | if(!string.IsNullOrEmpty(p.Identifier))
152 | {
153 | System.Diagnostics.Debug.WriteLine($"ActionId: {p.Identifier}");
154 | }
155 |
156 | foreach(var data in p.Data)
157 | {
158 | System.Diagnostics.Debug.WriteLine($"{data.Key} : {data.Value}");
159 | }
160 |
161 | };
162 | ```
163 |
164 | On Android should use **click_action** key inside the data payload when sending notification with categories. The value for this key will be the category.
165 |
166 | Android Notification Sample Payload:
167 | ```json
168 | {
169 | "data": {
170 | "body" : "hello!",
171 | "title": "push",
172 | "click_action":"message"
173 | }
174 | }
175 | ```
176 |
177 | On iOS should use **category** key inside the aps payload when sending notification with categories. The value for this key will be the category.
178 |
179 | iOS Notification Sample Payload:
180 | ```json
181 | {
182 | "aps" : {
183 | "category" : "message",
184 | "alert" : {
185 | "body" : "hello!"
186 | },
187 | "badge" : 3
188 | }
189 | }
190 | ```
191 |
192 | <= Back to [Table of Contents](../README.md)
193 |
--------------------------------------------------------------------------------
/docs/ReceivingNotifications.md:
--------------------------------------------------------------------------------
1 | ## Android Firebase Push Notifications
2 |
3 | **Data messages** - Handled by the client app. These messages trigger the onMessageReceived() callback even if your app is in foreground/background/killed. When using this type of message you are the one providing the UI and handling when push notification is received on an Android device.
4 |
5 | ```json
6 | {
7 | "data": {
8 | "message" : "my_custom_value",
9 | "other_key" : true,
10 | "body":"test"
11 | }
12 | }
13 | ```
14 |
15 | ## iOS APS Push Notifications
16 |
17 | https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CreatingtheNotificationPayload.html#//apple_ref/doc/uid/TP40008194-CH10-SW1
18 |
19 | ## Configuring a Silent Notification
20 |
21 | On iOS to get a silent notification you should send "content-available" : 1 inside the "aps" payload key.
22 |
23 | iOS Silent Payload Sample:
24 | ```json
25 | {
26 | "aps" : {
27 | "content-available" : 1
28 | },
29 | "acme1" : "bar",
30 | "acme2" : 42
31 | }
32 | ```
33 |
34 | On Android to get a silent notification you should send "silent" : true inside the "data" payload key.
35 |
36 | Android Silent Payload Sample:
37 | ```json
38 | {
39 | "data": {
40 | "message" : "my_custom_value",
41 | "other_key" : true,
42 | "body":"test",
43 | "silent" : true
44 | }
45 | }
46 | ```
47 |
48 | ### Notification Events
49 |
50 | **OnNotificationReceived**
51 | ```csharp
52 |
53 | CrossAzurePushNotification.Current.OnNotificationReceived += (s,p) =>
54 | {
55 |
56 | System.Diagnostics.Debug.WriteLine("Received");
57 |
58 | };
59 |
60 | ```
61 |
62 | **OnNotificationOpened**
63 | ```csharp
64 |
65 | CrossAzurePushNotification.Current.OnNotificationOpened += (s,p) =>
66 | {
67 | System.Diagnostics.Debug.WriteLine("Opened");
68 | foreach(var data in p.Data)
69 | {
70 | System.Diagnostics.Debug.WriteLine($"{data.Key} : {data.Value}");
71 | }
72 |
73 | if(!string.IsNullOrEmpty(p.Identifier))
74 | {
75 | System.Diagnostics.Debug.WriteLine($"ActionId: {p.Identifier}");
76 | }
77 |
78 | };
79 | ```
80 |
81 | **Note: This is the event were you will navigate to an specific page/activity/viewcontroller, if needed**
82 |
83 | **OnNotificationDeleted** (Android Only)
84 | ```csharp
85 |
86 | CrossAzurePushNotification.Current.OnNotificationDeleted += (s,p) =>
87 | {
88 |
89 | System.Diagnostics.Debug.WriteLine("Deleted");
90 |
91 | };
92 |
93 | ```
94 |
95 | ### Push Notification Handler
96 |
97 | A push notification handler is the way to provide ui push notification customization(on Android) and events feedback on native platforms by using **IPushNotificationHandler** interface. The plugin has a default push notification handler implementation and it's the one used by default.
98 |
99 | On most common use cases the default implementation might be enough so a custom implementation might not be needed at all.
100 |
101 | ```csharp
102 | public interface IPushNotificationHandler
103 | {
104 | //Method triggered when an error occurs
105 | void OnError(string error);
106 | //Method triggered when a notification is opened
107 | void OnOpened(NotificationResponse response);
108 | //Method triggered when a notification is received
109 | void OnReceived(IDictionary parameters);
110 | }
111 | ```
112 | An example of a custom handler use is the [DefaultPushNotificationHandler](../src/Plugin.AzurePushNotification.Android/DefaultPushNotificationHandler.cs) which is the plugin default implementation to render the push notification ui when sending data messages and supporting notification actions on Android.
113 |
114 | ### Initialize using a PushHandler on Application class on Android and AppDelegate on iOS:
115 |
116 | Application class **OnCreate** on Android:
117 |
118 | ```csharp
119 | #if DEBUG
120 | AzurePushNotificationManager.Initialize(this,new CustomPushHandler(),true);
121 | #else
122 | AzurePushNotificationManager.Initialize(this,new CustomPushHandler(),false);
123 | #endif
124 | ```
125 | To keep the default push notification handler functionality but make small adjustments or customizations to the notification. You can inherit from **DefaultPushNotificationHandler** and implement **OnBuildNotification** method which can be used to e.g. load an image from the web and set it as the 'LargeIcon' of a notification (notificationBuilder.SetLargeIcon) or other modifications to the resulting notification.
126 |
127 | **Note: If you use a custom push notification handler on Android, you will have full control on the notification arrival, so will be in charge of creating the notification ui for data messages when needed.**
128 |
129 | AppDelegate **FinishLaunching** on iOS:
130 | ```csharp
131 | AzurePushNotificationManager.Initialize(options,new CustomPushHandler());
132 | ```
133 |
134 | <= Back to [Table of Contents](../README.md)
135 |
136 |
--------------------------------------------------------------------------------
/docs/iOSCustomization.md:
--------------------------------------------------------------------------------
1 | ### iOS Specifics Customization
2 |
3 | #### Notification Sound
4 |
5 | You can set the sound to be played when notification arrive by setting **sound** key on th payload. A sound file with the value set should be in your should be on *Library/Sounds*.
6 |
7 | Valid extensions are: aiff, wav, or caf file
8 |
9 | ```json
10 | {
11 | "aps" : {
12 | "alert" : {
13 | "title" : "hello",
14 | "body" : "world"
15 | },
16 | "sound" : "test.aiff"
17 | }
18 | }
19 | ```
20 | #### Notification on Foreground
21 |
22 | You can set UNNotificationPresentationOptions to get an alert, badge, sound when notification is received in foreground by setting static property **AzurePushNotificationManager.CurrentNotificationPresentationOption**. By default is set to UNNotificationPresentationOptions.None.
23 |
24 | ```csharp
25 | public enum UNNotificationPresentationOptions
26 | {
27 | Alert, //Display the notification as an alert, using the notification text.
28 | Badge, //Display the notification badge value in the application's badge.
29 | None, //No options are set.
30 | Sound //Play the notification sound.
31 | }
32 | ```
33 |
34 | Usage sample on iOS Project:
35 |
36 | ```csharp
37 | //To set for alert
38 | AzurePushNotificationManager.CurrentNotificationPresentationOption = UNNotificationPresentationOptions.Alert;
39 |
40 | //You can also combine them
41 | AzurePushNotificationManager.CurrentNotificationPresentationOption = UNNotificationPresentationOptions.Alert | UNNotificationPresentationOptions.Badge;
42 | ```
43 |
44 | A good place to do this would be on the **OnReceived** method of a custom push notification handler if it changes depending on the notification, if not you can just set it once on the AppDelegate **FinishLaunching**.
45 |
46 | <= Back to [Table of Contents](../README.md)
47 |
48 |
--------------------------------------------------------------------------------
/nuget/Plugin.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Plugin.AzurePushNotification
5 | 1.1.0
6 | Azure Push Notification Plugin for Xamarin
7 | Rendy Del Rosario
8 | crossgeeks,rdelrosario
9 | https://raw.githubusercontent.com/CrossGeeks/AzurePushNotificationPlugin/master/LICENSE
10 | https://github.com/CrossGeeks/AzurePushNotificationPlugin
11 | https://github.com/CrossGeeks/AzurePushNotificationPlugin/blob/master/art/icon.png?raw=true
12 | false
13 | Receive and handle azure push notifications across Xamarin.iOS and Xamarin.Android
14 | Receive and handle push azure notifications across Xamarin.iOS and Xamarin.Android
15 | On demand registration, persistent token, better error handling and other minor fixes
16 | Copyright 2017
17 | iOS,Android,azure,notifications hub,push notifications,pcl,xamarin,plugins,xam.pcl,fcm,apn
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.Android/Assets/AboutAssets.txt:
--------------------------------------------------------------------------------
1 | Any raw assets you want to be deployed with your application can be placed in
2 | this directory (and child directories) and given a Build Action of "AndroidAsset".
3 |
4 | These files will be deployed with you package and will be accessible using Android's
5 | AssetManager, like this:
6 |
7 | public class ReadAsset : Activity
8 | {
9 | protected override void OnCreate (Bundle bundle)
10 | {
11 | base.OnCreate (bundle);
12 |
13 | InputStream input = Assets.Open ("my_asset.txt");
14 | }
15 | }
16 |
17 | Additionally, some Android functions will automatically load asset files:
18 |
19 | Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf");
20 |
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.Android/AzurePushNotificationSample.Android.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}
7 | {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
8 | Library
9 | AzurePushNotificationSample.Droid
10 | AzurePushNotificationSample.Android
11 | v9.0
12 | True
13 | Resources\Resource.designer.cs
14 | Resource
15 | Properties\AndroidManifest.xml
16 | Resources
17 | Assets
18 |
19 |
20 |
21 |
22 | true
23 | full
24 | false
25 | bin\Debug
26 | DEBUG;
27 | prompt
28 | 4
29 | None
30 |
31 |
32 | true
33 | pdbonly
34 | true
35 | bin\Release
36 | prompt
37 | 4
38 | true
39 | false
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | 2.0.18
51 |
52 |
53 | 28.0.0.3
54 |
55 |
56 | 28.0.0.3
57 |
58 |
59 | 28.0.0.3
60 |
61 |
62 | 28.0.0.3
63 |
64 |
65 | 28.0.0.3
66 |
67 |
68 | 28.0.0.3
69 |
70 |
71 | 28.0.0.3
72 |
73 |
74 | 28.0.0.3
75 |
76 |
77 | 28.0.0.3
78 |
79 |
80 | 0.6.0
81 |
82 |
83 | 71.1740.0
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 | 71.1620.0
93 |
94 |
95 | 71.1601.0
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 | Designer
124 |
125 |
126 |
127 |
128 | {D752C30D-5472-46DE-8256-E959BFF373FD}
129 | AzurePushNotificationSample
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.Android/MainActivity.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | using Android.App;
4 | using Android.Content.PM;
5 | using Android.Runtime;
6 | using Android.Views;
7 | using Android.Widget;
8 | using Android.OS;
9 | using Plugin.AzurePushNotification;
10 | using Android.Content;
11 |
12 | namespace AzurePushNotificationSample.Droid
13 | {
14 | [Activity(Label = "AzurePushNotificationSample", Icon = "@drawable/icon", Theme = "@style/MainTheme", ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
15 | public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
16 | {
17 | protected override void OnCreate(Bundle bundle)
18 | {
19 | TabLayoutResource = Resource.Layout.Tabbar;
20 | ToolbarResource = Resource.Layout.Toolbar;
21 |
22 | base.OnCreate(bundle);
23 |
24 | global::Xamarin.Forms.Forms.Init(this, bundle);
25 | LoadApplication(new App());
26 | AzurePushNotificationManager.ProcessIntent(this,Intent);
27 | }
28 |
29 | protected override void OnNewIntent(Intent intent)
30 | {
31 | base.OnNewIntent(intent);
32 | AzurePushNotificationManager.ProcessIntent(this,intent);
33 | }
34 | }
35 | }
36 |
37 |
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.Android/MainApplication.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | using Android.App;
7 | using Android.Content;
8 | using Android.OS;
9 | using Android.Runtime;
10 | using Android.Views;
11 | using Android.Widget;
12 | using Plugin.AzurePushNotification;
13 | using AzurePushNotificationSample;
14 | namespace AzurePushNotificationSample.Droid
15 | {
16 | [Application]
17 | public class MainApplication : Application
18 | {
19 | protected MainApplication(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
20 | {
21 | }
22 |
23 | public override void OnCreate()
24 | {
25 | base.OnCreate();
26 |
27 | //Set the default notification channel for your app when running Android Oreo
28 | if (Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O)
29 | {
30 | //Change for your default notification channel id here
31 | AzurePushNotificationManager.DefaultNotificationChannelId = "DefaultChannel";
32 |
33 | //Change for your default notification channel name here
34 | AzurePushNotificationManager.DefaultNotificationChannelName = "General";
35 | }
36 |
37 | #if DEBUG
38 | AzurePushNotificationManager.Initialize(this, AzureConstants.ListenConnectionString, AzureConstants.NotificationHubName, true);
39 | #else
40 | AzurePushNotificationManager.Initialize(this, AzureConstants.ListenConnectionString, AzureConstants.NotificationHubName, false);
41 | #endif
42 |
43 |
44 | //Handle notification when app is closed here
45 | CrossAzurePushNotification.Current.OnNotificationReceived += (s, p) =>
46 | {
47 |
48 |
49 | };
50 | }
51 |
52 |
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.Android/Properties/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.Android/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 | using Android.App;
5 |
6 | // General Information about an assembly is controlled through the following
7 | // set of attributes. Change these attribute values to modify the information
8 | // associated with an assembly.
9 | [assembly: AssemblyTitle("AzurePushNotificationSample.Android")]
10 | [assembly: AssemblyDescription("")]
11 | [assembly: AssemblyConfiguration("")]
12 | [assembly: AssemblyCompany("")]
13 | [assembly: AssemblyProduct("AzurePushNotificationSample.Android")]
14 | [assembly: AssemblyCopyright("Copyright © 2014")]
15 | [assembly: AssemblyTrademark("")]
16 | [assembly: AssemblyCulture("")]
17 | [assembly: ComVisible(false)]
18 |
19 | // Version information for an assembly consists of the following four values:
20 | //
21 | // Major Version
22 | // Minor Version
23 | // Build Number
24 | // Revision
25 | //
26 | // You can specify all the values or you can default the Build and Revision Numbers
27 | // by using the '*' as shown below:
28 | // [assembly: AssemblyVersion("1.0.*")]
29 | [assembly: AssemblyVersion("1.0.0.0")]
30 | [assembly: AssemblyFileVersion("1.0.0.0")]
31 |
32 | // Add some common permissions, these can be removed if not needed
33 | [assembly: UsesPermission(Android.Manifest.Permission.Internet)]
34 | [assembly: UsesPermission(Android.Manifest.Permission.WriteExternalStorage)]
35 |
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.Android/Resources/AboutResources.txt:
--------------------------------------------------------------------------------
1 | Images, layout descriptions, binary blobs and string dictionaries can be included
2 | in your application as resource files. Various Android APIs are designed to
3 | operate on the resource IDs instead of dealing with images, strings or binary blobs
4 | directly.
5 |
6 | For example, a sample Android app that contains a user interface layout (main.xml),
7 | an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png)
8 | would keep its resources in the "Resources" directory of the application:
9 |
10 | Resources/
11 | drawable-hdpi/
12 | icon.png
13 |
14 | drawable-ldpi/
15 | icon.png
16 |
17 | drawable-mdpi/
18 | icon.png
19 |
20 | layout/
21 | main.xml
22 |
23 | values/
24 | strings.xml
25 |
26 | In order to get the build system to recognize Android resources, set the build action to
27 | "AndroidResource". The native Android APIs do not operate directly with filenames, but
28 | instead operate on resource IDs. When you compile an Android application that uses resources,
29 | the build system will package the resources for distribution and generate a class called
30 | "Resource" that contains the tokens for each one of the resources included. For example,
31 | for the above Resources layout, this is what the Resource class would expose:
32 |
33 | public class Resource {
34 | public class drawable {
35 | public const int icon = 0x123;
36 | }
37 |
38 | public class layout {
39 | public const int main = 0x456;
40 | }
41 |
42 | public class strings {
43 | public const int first_string = 0xabc;
44 | public const int second_string = 0xbcd;
45 | }
46 | }
47 |
48 | You would then use R.drawable.icon to reference the drawable/icon.png file, or Resource.layout.main
49 | to reference the layout/main.xml file, or Resource.strings.first_string to reference the first
50 | string in the dictionary file values/strings.xml.
51 |
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.Android/Resources/drawable-hdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/AzurePushNotificationPlugin/31fa9e9062fcae30881a86caa7753c6ab2777ca2/samples/AzurePushNotificationSample/AzurePushNotificationSample.Android/Resources/drawable-hdpi/icon.png
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.Android/Resources/drawable-xhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/AzurePushNotificationPlugin/31fa9e9062fcae30881a86caa7753c6ab2777ca2/samples/AzurePushNotificationSample/AzurePushNotificationSample.Android/Resources/drawable-xhdpi/icon.png
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.Android/Resources/drawable-xxhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/AzurePushNotificationPlugin/31fa9e9062fcae30881a86caa7753c6ab2777ca2/samples/AzurePushNotificationSample/AzurePushNotificationSample.Android/Resources/drawable-xxhdpi/icon.png
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.Android/Resources/drawable/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/AzurePushNotificationPlugin/31fa9e9062fcae30881a86caa7753c6ab2777ca2/samples/AzurePushNotificationSample/AzurePushNotificationSample.Android/Resources/drawable/icon.png
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.Android/Resources/drawable/splash_screen.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 | -
7 |
10 |
11 |
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.Android/Resources/layout/Main.axml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.Android/Resources/layout/Tabbar.axml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.Android/Resources/layout/Toolbar.axml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.Android/Resources/mipmap-hdpi/Icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/AzurePushNotificationPlugin/31fa9e9062fcae30881a86caa7753c6ab2777ca2/samples/AzurePushNotificationSample/AzurePushNotificationSample.Android/Resources/mipmap-hdpi/Icon.png
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.Android/Resources/mipmap-mdpi/Icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/AzurePushNotificationPlugin/31fa9e9062fcae30881a86caa7753c6ab2777ca2/samples/AzurePushNotificationSample/AzurePushNotificationSample.Android/Resources/mipmap-mdpi/Icon.png
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.Android/Resources/mipmap-xhdpi/Icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/AzurePushNotificationPlugin/31fa9e9062fcae30881a86caa7753c6ab2777ca2/samples/AzurePushNotificationSample/AzurePushNotificationSample.Android/Resources/mipmap-xhdpi/Icon.png
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.Android/Resources/mipmap-xxhdpi/Icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/AzurePushNotificationPlugin/31fa9e9062fcae30881a86caa7753c6ab2777ca2/samples/AzurePushNotificationSample/AzurePushNotificationSample.Android/Resources/mipmap-xxhdpi/Icon.png
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.Android/Resources/mipmap-xxxhdpi/Icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/AzurePushNotificationPlugin/31fa9e9062fcae30881a86caa7753c6ab2777ca2/samples/AzurePushNotificationSample/AzurePushNotificationSample.Android/Resources/mipmap-xxxhdpi/Icon.png
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.Android/Resources/values/Strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Hello World, Click Me!
4 | AzurePushNotificationSample.Droid
5 |
6 |
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.Android/Resources/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #ffffff
4 |
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.Android/Resources/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
26 |
30 |
33 |
34 |
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.Android/SplashActivity.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | using Android.App;
7 | using Android.Content;
8 | using Android.Content.PM;
9 | using Android.OS;
10 | using Android.Runtime;
11 | using Android.Support.V7.App;
12 | using Android.Views;
13 | using Android.Widget;
14 |
15 | namespace AzurePushNotificationSample.Droid
16 | {
17 | [Activity(Theme = "@style/MainTheme.Splash", MainLauncher = true, NoHistory = true, ScreenOrientation = ScreenOrientation.Portrait)]
18 | public class SplashActivity : AppCompatActivity
19 | {
20 | protected override void OnCreate(Bundle savedInstanceState)
21 | {
22 | base.OnCreate(savedInstanceState);
23 |
24 | // Create your application here
25 | var mainIntent = new Intent(Application.Context, typeof(MainActivity));
26 |
27 | if (Intent.Extras != null)
28 | {
29 | mainIntent.PutExtras(Intent.Extras);
30 | }
31 | mainIntent.SetFlags(ActivityFlags.SingleTop);
32 |
33 | StartActivity(mainIntent);
34 | }
35 | protected override void OnResume()
36 | {
37 | base.OnResume();
38 |
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.Android/google-services.json:
--------------------------------------------------------------------------------
1 | {
2 | "project_info": {
3 | "project_number": "834212238609",
4 | "firebase_url": "https://azurepushnotificationsample.firebaseio.com",
5 | "project_id": "azurepushnotificationsample",
6 | "storage_bucket": "azurepushnotificationsample.appspot.com"
7 | },
8 | "client": [
9 | {
10 | "client_info": {
11 | "mobilesdk_app_id": "1:834212238609:android:e7b57bbb22651eb8",
12 | "android_client_info": {
13 | "package_name": "com.crossgeeks.azurepushnotificationsample"
14 | }
15 | },
16 | "oauth_client": [
17 | {
18 | "client_id": "834212238609-qeum216pk7l59g199o44gdmj39qjhehm.apps.googleusercontent.com",
19 | "client_type": 3
20 | }
21 | ],
22 | "api_key": [
23 | {
24 | "current_key": "AIzaSyAlys6j2rECJKC5TqmI1wC2TB_sOQgb4Cc"
25 | }
26 | ],
27 | "services": {
28 | "appinvite_service": {
29 | "other_platform_oauth_client": [
30 | {
31 | "client_id": "834212238609-qeum216pk7l59g199o44gdmj39qjhehm.apps.googleusercontent.com",
32 | "client_type": 3
33 | }
34 | ]
35 | }
36 | }
37 | }
38 | ],
39 | "configuration_version": "1"
40 | }
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/AppDelegate.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 |
5 | using Foundation;
6 | using Plugin.AzurePushNotification;
7 | using UIKit;
8 | using UserNotifications;
9 |
10 | namespace AzurePushNotificationSample.iOS
11 | {
12 | // The UIApplicationDelegate for the application. This class is responsible for launching the
13 | // User Interface of the application, as well as listening (and optionally responding) to
14 | // application events from iOS.
15 | [Register("AppDelegate")]
16 | public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
17 | {
18 | //
19 | // This method is invoked when the application has loaded and is ready to run. In this
20 | // method you should instantiate the window, load the UI into it and then make the window
21 | // visible.
22 | //
23 | // You have 17 seconds to return from this method, or iOS will terminate your application.
24 | //
25 | public override bool FinishedLaunching(UIApplication app, NSDictionary options)
26 | {
27 | global::Xamarin.Forms.Forms.Init();
28 | LoadApplication(new App());
29 | AzurePushNotificationManager.CurrentNotificationPresentationOption = UNNotificationPresentationOptions.Alert | UNNotificationPresentationOptions.Sound;
30 |
31 | AzurePushNotificationManager.Initialize(AzureConstants.ListenConnectionString, AzureConstants.NotificationHubName, options);
32 |
33 | return base.FinishedLaunching(app, options);
34 |
35 | }
36 |
37 | public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
38 | {
39 | AzurePushNotificationManager.DidRegisterRemoteNotifications(deviceToken);
40 | }
41 |
42 | public override void FailedToRegisterForRemoteNotifications(UIApplication application, NSError error)
43 | {
44 | AzurePushNotificationManager.RemoteNotificationRegistrationFailed(error);
45 |
46 | }
47 | // To receive notifications in foreground on iOS 9 and below.
48 | // To receive notifications in background in any iOS version
49 | public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action completionHandler)
50 | {
51 |
52 | AzurePushNotificationManager.DidReceiveMessage(userInfo);
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/AzurePushNotificationSample.iOS.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | iPhoneSimulator
6 | 8.0.30703
7 | 2.0
8 | {3834014E-65E6-4B5A-9792-4718E3E7DFD1}
9 | {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
10 | Exe
11 | AzurePushNotificationSample.iOS
12 | Resources
13 | AzurePushNotificationSample.iOS
14 |
15 |
16 |
17 |
18 | true
19 | full
20 | false
21 | bin\iPhoneSimulator\Debug
22 | DEBUG
23 | prompt
24 | 4
25 | false
26 | x86_64
27 | None
28 | true
29 |
30 |
31 | none
32 | true
33 | bin\iPhoneSimulator\Release
34 | prompt
35 | 4
36 | None
37 | x86_64
38 | false
39 |
40 |
41 | true
42 | full
43 | false
44 | bin\iPhone\Debug
45 | DEBUG
46 | prompt
47 | 4
48 | false
49 | ARM64
50 | iPhone Developer
51 | true
52 | Entitlements.plist
53 |
54 |
55 |
56 |
57 | none
58 | true
59 | bin\iPhone\Release
60 | prompt
61 | 4
62 | ARM64
63 | false
64 | iPhone Developer
65 | Entitlements.plist
66 |
67 |
68 | none
69 | True
70 | bin\iPhone\Ad-Hoc
71 | prompt
72 | 4
73 | False
74 | ARM64
75 | True
76 | Automatic:AdHoc
77 | iPhone Distribution
78 | Entitlements.plist
79 |
80 |
81 | none
82 | True
83 | bin\iPhone\AppStore
84 | prompt
85 | 4
86 | False
87 | ARM64
88 | Automatic:AppStore
89 | iPhone Distribution
90 | Entitlements.plist
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 | 2.0.18
129 |
130 |
131 | 2.0.4
132 |
133 |
134 |
135 |
136 |
137 |
138 | {D752C30D-5472-46DE-8256-E959BFF373FD}
139 | AzurePushNotificationSample
140 |
141 |
142 |
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/Entitlements.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | UIDeviceFamily
6 |
7 | 1
8 | 2
9 |
10 | UISupportedInterfaceOrientations
11 |
12 | UIInterfaceOrientationPortrait
13 | UIInterfaceOrientationLandscapeLeft
14 | UIInterfaceOrientationLandscapeRight
15 |
16 | UISupportedInterfaceOrientations~ipad
17 |
18 | UIInterfaceOrientationPortrait
19 | UIInterfaceOrientationPortraitUpsideDown
20 | UIInterfaceOrientationLandscapeLeft
21 | UIInterfaceOrientationLandscapeRight
22 |
23 | MinimumOSVersion
24 | 11.2
25 | CFBundleDisplayName
26 | AzurePushNotificationSample
27 | CFBundleIdentifier
28 | com.crossgeeks.azurepushnotificationsample
29 | CFBundleVersion
30 | 1.0
31 | CFBundleIconFiles
32 |
33 | Icon-60@2x
34 | Icon-60@3x
35 | Icon-76
36 | Icon-76@2x
37 | Default
38 | Default@2x
39 | Default-568h@2x
40 | Default-Portrait
41 | Default-Portrait@2x
42 | Icon-Small-40
43 | Icon-Small-40@2x
44 | Icon-Small-40@3x
45 | Icon-Small
46 | Icon-Small@2x
47 | Icon-Small@3x
48 |
49 | UILaunchStoryboardName
50 | LaunchScreen
51 | CFBundleName
52 | AzurePushNotificationSample
53 | CFBundleShortVersionString
54 | 1.0
55 | UIBackgroundModes
56 |
57 | remote-notification
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/Main.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 |
5 | using Foundation;
6 | using UIKit;
7 |
8 | namespace AzurePushNotificationSample.iOS
9 | {
10 | public class Application
11 | {
12 | // This is the main entry point of the application.
13 | static void Main(string[] args)
14 | {
15 | // if you want to use a different Application Delegate class from "AppDelegate"
16 | // you can specify it here.
17 | UIApplication.Main(args, null, "AppDelegate");
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/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("AzurePushNotificationSample.iOS")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("AzurePushNotificationSample.iOS")]
13 | [assembly: AssemblyCopyright("Copyright © 2014")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("72bdc44f-c588-44f3-b6df-9aace7daafdd")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/Resources/Default-568h@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/AzurePushNotificationPlugin/31fa9e9062fcae30881a86caa7753c6ab2777ca2/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/Resources/Default-568h@2x.png
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/Resources/Default-Portrait.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/AzurePushNotificationPlugin/31fa9e9062fcae30881a86caa7753c6ab2777ca2/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/Resources/Default-Portrait.png
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/Resources/Default-Portrait@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/AzurePushNotificationPlugin/31fa9e9062fcae30881a86caa7753c6ab2777ca2/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/Resources/Default-Portrait@2x.png
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/Resources/Default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/AzurePushNotificationPlugin/31fa9e9062fcae30881a86caa7753c6ab2777ca2/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/Resources/Default.png
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/Resources/Default@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/AzurePushNotificationPlugin/31fa9e9062fcae30881a86caa7753c6ab2777ca2/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/Resources/Default@2x.png
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/Resources/Icon-60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/AzurePushNotificationPlugin/31fa9e9062fcae30881a86caa7753c6ab2777ca2/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/Resources/Icon-60@2x.png
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/Resources/Icon-60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/AzurePushNotificationPlugin/31fa9e9062fcae30881a86caa7753c6ab2777ca2/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/Resources/Icon-60@3x.png
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/Resources/Icon-76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/AzurePushNotificationPlugin/31fa9e9062fcae30881a86caa7753c6ab2777ca2/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/Resources/Icon-76.png
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/Resources/Icon-76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/AzurePushNotificationPlugin/31fa9e9062fcae30881a86caa7753c6ab2777ca2/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/Resources/Icon-76@2x.png
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/Resources/Icon-Small-40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/AzurePushNotificationPlugin/31fa9e9062fcae30881a86caa7753c6ab2777ca2/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/Resources/Icon-Small-40.png
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/Resources/Icon-Small-40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/AzurePushNotificationPlugin/31fa9e9062fcae30881a86caa7753c6ab2777ca2/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/Resources/Icon-Small-40@2x.png
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/Resources/Icon-Small-40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/AzurePushNotificationPlugin/31fa9e9062fcae30881a86caa7753c6ab2777ca2/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/Resources/Icon-Small-40@3x.png
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/Resources/Icon-Small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/AzurePushNotificationPlugin/31fa9e9062fcae30881a86caa7753c6ab2777ca2/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/Resources/Icon-Small.png
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/Resources/Icon-Small@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/AzurePushNotificationPlugin/31fa9e9062fcae30881a86caa7753c6ab2777ca2/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/Resources/Icon-Small@2x.png
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/Resources/Icon-Small@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/AzurePushNotificationPlugin/31fa9e9062fcae30881a86caa7753c6ab2777ca2/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/Resources/Icon-Small@3x.png
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/Resources/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.iOS/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.27130.2010
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzurePushNotificationSample.Android", "AzurePushNotificationSample.Android\AzurePushNotificationSample.Android.csproj", "{81FBC96F-CA10-4D03-B76A-C94E7A87F844}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzurePushNotificationSample.iOS", "AzurePushNotificationSample.iOS\AzurePushNotificationSample.iOS.csproj", "{3834014E-65E6-4B5A-9792-4718E3E7DFD1}"
9 | EndProject
10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AzurePushNotificationSample", "AzurePushNotificationSample\AzurePushNotificationSample.csproj", "{D752C30D-5472-46DE-8256-E959BFF373FD}"
11 | EndProject
12 | Global
13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
14 | Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
15 | Ad-Hoc|ARM = Ad-Hoc|ARM
16 | Ad-Hoc|iPhone = Ad-Hoc|iPhone
17 | Ad-Hoc|iPhoneSimulator = Ad-Hoc|iPhoneSimulator
18 | Ad-Hoc|x64 = Ad-Hoc|x64
19 | Ad-Hoc|x86 = Ad-Hoc|x86
20 | AppStore|Any CPU = AppStore|Any CPU
21 | AppStore|ARM = AppStore|ARM
22 | AppStore|iPhone = AppStore|iPhone
23 | AppStore|iPhoneSimulator = AppStore|iPhoneSimulator
24 | AppStore|x64 = AppStore|x64
25 | AppStore|x86 = AppStore|x86
26 | Debug|Any CPU = Debug|Any CPU
27 | Debug|ARM = Debug|ARM
28 | Debug|iPhone = Debug|iPhone
29 | Debug|iPhoneSimulator = Debug|iPhoneSimulator
30 | Debug|x64 = Debug|x64
31 | Debug|x86 = Debug|x86
32 | Release|Any CPU = Release|Any CPU
33 | Release|ARM = Release|ARM
34 | Release|iPhone = Release|iPhone
35 | Release|iPhoneSimulator = Release|iPhoneSimulator
36 | Release|x64 = Release|x64
37 | Release|x86 = Release|x86
38 | EndGlobalSection
39 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
40 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
41 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
42 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Ad-Hoc|Any CPU.Deploy.0 = Release|Any CPU
43 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU
44 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Ad-Hoc|ARM.Build.0 = Release|Any CPU
45 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Ad-Hoc|ARM.Deploy.0 = Release|Any CPU
46 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
47 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
48 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Ad-Hoc|iPhone.Deploy.0 = Release|Any CPU
49 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
50 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
51 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Ad-Hoc|iPhoneSimulator.Deploy.0 = Release|Any CPU
52 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU
53 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Ad-Hoc|x64.Build.0 = Release|Any CPU
54 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Ad-Hoc|x64.Deploy.0 = Release|Any CPU
55 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU
56 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Ad-Hoc|x86.Build.0 = Release|Any CPU
57 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Ad-Hoc|x86.Deploy.0 = Release|Any CPU
58 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
59 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.AppStore|Any CPU.Build.0 = Release|Any CPU
60 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.AppStore|Any CPU.Deploy.0 = Release|Any CPU
61 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.AppStore|ARM.ActiveCfg = Release|Any CPU
62 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.AppStore|ARM.Build.0 = Release|Any CPU
63 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.AppStore|ARM.Deploy.0 = Release|Any CPU
64 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.AppStore|iPhone.ActiveCfg = Release|Any CPU
65 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.AppStore|iPhone.Build.0 = Release|Any CPU
66 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.AppStore|iPhone.Deploy.0 = Release|Any CPU
67 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
68 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
69 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.AppStore|iPhoneSimulator.Deploy.0 = Release|Any CPU
70 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.AppStore|x64.ActiveCfg = Release|Any CPU
71 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.AppStore|x64.Build.0 = Release|Any CPU
72 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.AppStore|x64.Deploy.0 = Release|Any CPU
73 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.AppStore|x86.ActiveCfg = Release|Any CPU
74 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.AppStore|x86.Build.0 = Release|Any CPU
75 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.AppStore|x86.Deploy.0 = Release|Any CPU
76 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
77 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Debug|Any CPU.Build.0 = Debug|Any CPU
78 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
79 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Debug|ARM.ActiveCfg = Debug|Any CPU
80 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Debug|ARM.Build.0 = Debug|Any CPU
81 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Debug|ARM.Deploy.0 = Debug|Any CPU
82 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Debug|iPhone.ActiveCfg = Debug|Any CPU
83 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Debug|iPhone.Build.0 = Debug|Any CPU
84 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Debug|iPhone.Deploy.0 = Debug|Any CPU
85 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
86 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
87 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Debug|iPhoneSimulator.Deploy.0 = Debug|Any CPU
88 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Debug|x64.ActiveCfg = Debug|Any CPU
89 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Debug|x64.Build.0 = Debug|Any CPU
90 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Debug|x64.Deploy.0 = Debug|Any CPU
91 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Debug|x86.ActiveCfg = Debug|Any CPU
92 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Debug|x86.Build.0 = Debug|Any CPU
93 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Debug|x86.Deploy.0 = Debug|Any CPU
94 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Release|Any CPU.ActiveCfg = Release|Any CPU
95 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Release|Any CPU.Build.0 = Release|Any CPU
96 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Release|Any CPU.Deploy.0 = Release|Any CPU
97 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Release|ARM.ActiveCfg = Release|Any CPU
98 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Release|ARM.Build.0 = Release|Any CPU
99 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Release|ARM.Deploy.0 = Release|Any CPU
100 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Release|iPhone.ActiveCfg = Release|Any CPU
101 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Release|iPhone.Build.0 = Release|Any CPU
102 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Release|iPhone.Deploy.0 = Release|Any CPU
103 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
104 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
105 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU
106 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Release|x64.ActiveCfg = Release|Any CPU
107 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Release|x64.Build.0 = Release|Any CPU
108 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Release|x64.Deploy.0 = Release|Any CPU
109 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Release|x86.ActiveCfg = Release|Any CPU
110 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Release|x86.Build.0 = Release|Any CPU
111 | {81FBC96F-CA10-4D03-B76A-C94E7A87F844}.Release|x86.Deploy.0 = Release|Any CPU
112 | {3834014E-65E6-4B5A-9792-4718E3E7DFD1}.Ad-Hoc|Any CPU.ActiveCfg = Ad-Hoc|iPhone
113 | {3834014E-65E6-4B5A-9792-4718E3E7DFD1}.Ad-Hoc|ARM.ActiveCfg = Ad-Hoc|iPhone
114 | {3834014E-65E6-4B5A-9792-4718E3E7DFD1}.Ad-Hoc|iPhone.ActiveCfg = Ad-Hoc|iPhone
115 | {3834014E-65E6-4B5A-9792-4718E3E7DFD1}.Ad-Hoc|iPhone.Build.0 = Ad-Hoc|iPhone
116 | {3834014E-65E6-4B5A-9792-4718E3E7DFD1}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Ad-Hoc|iPhoneSimulator
117 | {3834014E-65E6-4B5A-9792-4718E3E7DFD1}.Ad-Hoc|iPhoneSimulator.Build.0 = Ad-Hoc|iPhoneSimulator
118 | {3834014E-65E6-4B5A-9792-4718E3E7DFD1}.Ad-Hoc|x64.ActiveCfg = Ad-Hoc|iPhone
119 | {3834014E-65E6-4B5A-9792-4718E3E7DFD1}.Ad-Hoc|x86.ActiveCfg = Ad-Hoc|iPhone
120 | {3834014E-65E6-4B5A-9792-4718E3E7DFD1}.AppStore|Any CPU.ActiveCfg = AppStore|iPhone
121 | {3834014E-65E6-4B5A-9792-4718E3E7DFD1}.AppStore|ARM.ActiveCfg = AppStore|iPhone
122 | {3834014E-65E6-4B5A-9792-4718E3E7DFD1}.AppStore|iPhone.ActiveCfg = AppStore|iPhone
123 | {3834014E-65E6-4B5A-9792-4718E3E7DFD1}.AppStore|iPhone.Build.0 = AppStore|iPhone
124 | {3834014E-65E6-4B5A-9792-4718E3E7DFD1}.AppStore|iPhoneSimulator.ActiveCfg = AppStore|iPhoneSimulator
125 | {3834014E-65E6-4B5A-9792-4718E3E7DFD1}.AppStore|iPhoneSimulator.Build.0 = AppStore|iPhoneSimulator
126 | {3834014E-65E6-4B5A-9792-4718E3E7DFD1}.AppStore|x64.ActiveCfg = AppStore|iPhone
127 | {3834014E-65E6-4B5A-9792-4718E3E7DFD1}.AppStore|x86.ActiveCfg = AppStore|iPhone
128 | {3834014E-65E6-4B5A-9792-4718E3E7DFD1}.Debug|Any CPU.ActiveCfg = Debug|iPhone
129 | {3834014E-65E6-4B5A-9792-4718E3E7DFD1}.Debug|ARM.ActiveCfg = Debug|iPhone
130 | {3834014E-65E6-4B5A-9792-4718E3E7DFD1}.Debug|iPhone.ActiveCfg = Debug|iPhone
131 | {3834014E-65E6-4B5A-9792-4718E3E7DFD1}.Debug|iPhone.Build.0 = Debug|iPhone
132 | {3834014E-65E6-4B5A-9792-4718E3E7DFD1}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
133 | {3834014E-65E6-4B5A-9792-4718E3E7DFD1}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
134 | {3834014E-65E6-4B5A-9792-4718E3E7DFD1}.Debug|x64.ActiveCfg = Debug|iPhone
135 | {3834014E-65E6-4B5A-9792-4718E3E7DFD1}.Debug|x86.ActiveCfg = Debug|iPhone
136 | {3834014E-65E6-4B5A-9792-4718E3E7DFD1}.Release|Any CPU.ActiveCfg = Release|iPhone
137 | {3834014E-65E6-4B5A-9792-4718E3E7DFD1}.Release|ARM.ActiveCfg = Release|iPhone
138 | {3834014E-65E6-4B5A-9792-4718E3E7DFD1}.Release|iPhone.ActiveCfg = Release|iPhone
139 | {3834014E-65E6-4B5A-9792-4718E3E7DFD1}.Release|iPhone.Build.0 = Release|iPhone
140 | {3834014E-65E6-4B5A-9792-4718E3E7DFD1}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
141 | {3834014E-65E6-4B5A-9792-4718E3E7DFD1}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
142 | {3834014E-65E6-4B5A-9792-4718E3E7DFD1}.Release|x64.ActiveCfg = Release|iPhone
143 | {3834014E-65E6-4B5A-9792-4718E3E7DFD1}.Release|x86.ActiveCfg = Release|iPhone
144 | {3834014E-65E6-4B5A-9792-4718E3E7DFD1}.Debug|Any CPU.Build.0 = Debug|iPhone
145 | {3834014E-65E6-4B5A-9792-4718E3E7DFD1}.Release|Any CPU.Build.0 = Release|iPhone
146 | {D752C30D-5472-46DE-8256-E959BFF373FD}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
147 | {D752C30D-5472-46DE-8256-E959BFF373FD}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
148 | {D752C30D-5472-46DE-8256-E959BFF373FD}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
149 | {D752C30D-5472-46DE-8256-E959BFF373FD}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
150 | {D752C30D-5472-46DE-8256-E959BFF373FD}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
151 | {D752C30D-5472-46DE-8256-E959BFF373FD}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
152 | {D752C30D-5472-46DE-8256-E959BFF373FD}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
153 | {D752C30D-5472-46DE-8256-E959BFF373FD}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
154 | {D752C30D-5472-46DE-8256-E959BFF373FD}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
155 | {D752C30D-5472-46DE-8256-E959BFF373FD}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
156 | {D752C30D-5472-46DE-8256-E959BFF373FD}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
157 | {D752C30D-5472-46DE-8256-E959BFF373FD}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
158 | {D752C30D-5472-46DE-8256-E959BFF373FD}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
159 | {D752C30D-5472-46DE-8256-E959BFF373FD}.AppStore|Any CPU.Build.0 = Debug|Any CPU
160 | {D752C30D-5472-46DE-8256-E959BFF373FD}.AppStore|ARM.ActiveCfg = Debug|Any CPU
161 | {D752C30D-5472-46DE-8256-E959BFF373FD}.AppStore|ARM.Build.0 = Debug|Any CPU
162 | {D752C30D-5472-46DE-8256-E959BFF373FD}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
163 | {D752C30D-5472-46DE-8256-E959BFF373FD}.AppStore|iPhone.Build.0 = Debug|Any CPU
164 | {D752C30D-5472-46DE-8256-E959BFF373FD}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
165 | {D752C30D-5472-46DE-8256-E959BFF373FD}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
166 | {D752C30D-5472-46DE-8256-E959BFF373FD}.AppStore|x64.ActiveCfg = Debug|Any CPU
167 | {D752C30D-5472-46DE-8256-E959BFF373FD}.AppStore|x64.Build.0 = Debug|Any CPU
168 | {D752C30D-5472-46DE-8256-E959BFF373FD}.AppStore|x86.ActiveCfg = Debug|Any CPU
169 | {D752C30D-5472-46DE-8256-E959BFF373FD}.AppStore|x86.Build.0 = Debug|Any CPU
170 | {D752C30D-5472-46DE-8256-E959BFF373FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
171 | {D752C30D-5472-46DE-8256-E959BFF373FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
172 | {D752C30D-5472-46DE-8256-E959BFF373FD}.Debug|ARM.ActiveCfg = Debug|Any CPU
173 | {D752C30D-5472-46DE-8256-E959BFF373FD}.Debug|ARM.Build.0 = Debug|Any CPU
174 | {D752C30D-5472-46DE-8256-E959BFF373FD}.Debug|iPhone.ActiveCfg = Debug|Any CPU
175 | {D752C30D-5472-46DE-8256-E959BFF373FD}.Debug|iPhone.Build.0 = Debug|Any CPU
176 | {D752C30D-5472-46DE-8256-E959BFF373FD}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
177 | {D752C30D-5472-46DE-8256-E959BFF373FD}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
178 | {D752C30D-5472-46DE-8256-E959BFF373FD}.Debug|x64.ActiveCfg = Debug|Any CPU
179 | {D752C30D-5472-46DE-8256-E959BFF373FD}.Debug|x64.Build.0 = Debug|Any CPU
180 | {D752C30D-5472-46DE-8256-E959BFF373FD}.Debug|x86.ActiveCfg = Debug|Any CPU
181 | {D752C30D-5472-46DE-8256-E959BFF373FD}.Debug|x86.Build.0 = Debug|Any CPU
182 | {D752C30D-5472-46DE-8256-E959BFF373FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
183 | {D752C30D-5472-46DE-8256-E959BFF373FD}.Release|Any CPU.Build.0 = Release|Any CPU
184 | {D752C30D-5472-46DE-8256-E959BFF373FD}.Release|ARM.ActiveCfg = Release|Any CPU
185 | {D752C30D-5472-46DE-8256-E959BFF373FD}.Release|ARM.Build.0 = Release|Any CPU
186 | {D752C30D-5472-46DE-8256-E959BFF373FD}.Release|iPhone.ActiveCfg = Release|Any CPU
187 | {D752C30D-5472-46DE-8256-E959BFF373FD}.Release|iPhone.Build.0 = Release|Any CPU
188 | {D752C30D-5472-46DE-8256-E959BFF373FD}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
189 | {D752C30D-5472-46DE-8256-E959BFF373FD}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
190 | {D752C30D-5472-46DE-8256-E959BFF373FD}.Release|x64.ActiveCfg = Release|Any CPU
191 | {D752C30D-5472-46DE-8256-E959BFF373FD}.Release|x64.Build.0 = Release|Any CPU
192 | {D752C30D-5472-46DE-8256-E959BFF373FD}.Release|x86.ActiveCfg = Release|Any CPU
193 | {D752C30D-5472-46DE-8256-E959BFF373FD}.Release|x86.Build.0 = Release|Any CPU
194 | EndGlobalSection
195 | GlobalSection(SolutionProperties) = preSolution
196 | HideSolutionNode = FALSE
197 | EndGlobalSection
198 | GlobalSection(ExtensibilityGlobals) = postSolution
199 | SolutionGuid = {21D9A243-8674-4C13-BB6E-7B4FB45478BA}
200 | EndGlobalSection
201 | EndGlobal
202 |
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample/App.xaml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using Plugin.AzurePushNotification;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 |
7 | using Xamarin.Forms;
8 |
9 | namespace AzurePushNotificationSample
10 | {
11 |
12 | public partial class App : Application
13 | {
14 |
15 | AzurePushNotificationSample.MainPage mPage;
16 | public App()
17 | {
18 | InitializeComponent();
19 |
20 | mPage = new AzurePushNotificationSample.MainPage()
21 | {
22 | Message = "Hello Azure Push Notifications!"
23 | };
24 |
25 | MainPage = new NavigationPage(mPage);
26 | }
27 |
28 | protected override async void OnStart()
29 | {
30 |
31 | // Handle when your app starts
32 | CrossAzurePushNotification.Current.OnTokenRefresh += (s, p) =>
33 | {
34 | System.Diagnostics.Debug.WriteLine($"TOKEN REC: {p.Token}");
35 | };
36 | System.Diagnostics.Debug.WriteLine($"TOKEN: {CrossAzurePushNotification.Current.Token}");
37 |
38 | CrossAzurePushNotification.Current.OnNotificationReceived += (s, p) =>
39 | {
40 | try
41 | {
42 | System.Diagnostics.Debug.WriteLine("Received");
43 | if (p.Data.ContainsKey("body"))
44 | {
45 | Device.BeginInvokeOnMainThread(() =>
46 | {
47 | mPage.Message = $"{p.Data["body"]}";
48 | });
49 |
50 | }
51 | }
52 | catch (Exception ex)
53 | {
54 |
55 | }
56 |
57 | };
58 |
59 | CrossAzurePushNotification.Current.OnNotificationOpened += (s, p) =>
60 | {
61 | //System.Diagnostics.Debug.WriteLine(p.Identifier);
62 |
63 | System.Diagnostics.Debug.WriteLine("Opened");
64 | foreach (var data in p.Data)
65 | {
66 | System.Diagnostics.Debug.WriteLine($"{data.Key} : {data.Value}");
67 | }
68 |
69 | if (!string.IsNullOrEmpty(p.Identifier))
70 | {
71 | Device.BeginInvokeOnMainThread(() =>
72 | {
73 | mPage.Message = p.Identifier;
74 | });
75 | }
76 | else if (p.Data.ContainsKey("color"))
77 | {
78 | Device.BeginInvokeOnMainThread(() =>
79 | {
80 | mPage.Navigation.PushAsync(new ContentPage()
81 | {
82 | BackgroundColor = Color.FromHex($"{p.Data["color"]}")
83 |
84 | });
85 | });
86 |
87 | }
88 | else if (p.Data.ContainsKey("aps.alert.title"))
89 | {
90 | Device.BeginInvokeOnMainThread(() =>
91 | {
92 | mPage.Message = $"{p.Data["aps.alert.title"]}";
93 | });
94 |
95 | }
96 | };
97 | CrossAzurePushNotification.Current.OnNotificationDeleted += (s, p) =>
98 | {
99 | System.Diagnostics.Debug.WriteLine("Dismissed");
100 | };
101 |
102 | await CrossAzurePushNotification.Current.RegisterAsync(new string[] { "crossgeeks", "general" });
103 | }
104 |
105 | protected override void OnSleep()
106 | {
107 |
108 | }
109 |
110 | protected override void OnResume()
111 | {
112 |
113 | }
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample/AzureConstants.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace AzurePushNotificationSample
6 | {
7 | public class AzureConstants
8 | {
9 | public const string ListenConnectionString = "YOUR NOTIFICATION HUB CONNECTION STRING GOES HERE";
10 | public const string NotificationHubName = "YOUR NOTIFICATION HUB PATH NAME GOES HERE";
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample/AzurePushNotificationSample.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | *.xaml
15 |
16 |
17 | *.xaml
18 |
19 |
20 |
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample/MainPage.xaml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/samples/AzurePushNotificationSample/AzurePushNotificationSample/MainPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using Plugin.AzurePushNotification;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using Xamarin.Forms;
8 |
9 | namespace AzurePushNotificationSample
10 | {
11 | public partial class MainPage : ContentPage
12 | {
13 | public string Message
14 | {
15 | get
16 | {
17 | return textLabel.Text;
18 | }
19 | set
20 | {
21 | textLabel.Text = value;
22 | }
23 | }
24 | public MainPage()
25 | {
26 | InitializeComponent();
27 |
28 | CrossAzurePushNotification.Current.OnNotificationReceived += (s, p) =>
29 | {
30 | System.Diagnostics.Debug.WriteLine("Received");
31 | if (p.Data.ContainsKey("body"))
32 | {
33 | Device.BeginInvokeOnMainThread(() =>
34 | {
35 | textLabel.Text = $"{p.Data["body"]}";
36 | });
37 |
38 | }
39 | };
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/AzurePushNotification.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29519.181
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Plugin.AzurePushNotification", "Plugin.AzurePushNotification\Plugin.AzurePushNotification.csproj", "{A6FCEF44-D2BA-42C7-B3CB-13667BCD7B54}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B2C5EB1D-AC6D-41FC-A243-7958BB94A528}"
9 | ProjectSection(SolutionItems) = preProject
10 | ..\docs\AndroidCustomization.md = ..\docs\AndroidCustomization.md
11 | ..\docs\FAQ.md = ..\docs\FAQ.md
12 | ..\docs\GettingStarted.md = ..\docs\GettingStarted.md
13 | ..\docs\iOSCustomization.md = ..\docs\iOSCustomization.md
14 | ..\LICENSE = ..\LICENSE
15 | ..\docs\LocalizedPushNotifications.md = ..\docs\LocalizedPushNotifications.md
16 | ..\docs\NotificationActions.md = ..\docs\NotificationActions.md
17 | ..\nuget\Plugin.nuspec = ..\nuget\Plugin.nuspec
18 | ..\README.md = ..\README.md
19 | ..\docs\ReceivingNotifications.md = ..\docs\ReceivingNotifications.md
20 | EndProjectSection
21 | EndProject
22 | Global
23 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
24 | Debug|Any CPU = Debug|Any CPU
25 | Debug|ARM = Debug|ARM
26 | Debug|x64 = Debug|x64
27 | Debug|x86 = Debug|x86
28 | Release|Any CPU = Release|Any CPU
29 | Release|ARM = Release|ARM
30 | Release|x64 = Release|x64
31 | Release|x86 = Release|x86
32 | EndGlobalSection
33 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
34 | {A6FCEF44-D2BA-42C7-B3CB-13667BCD7B54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
35 | {A6FCEF44-D2BA-42C7-B3CB-13667BCD7B54}.Debug|Any CPU.Build.0 = Debug|Any CPU
36 | {A6FCEF44-D2BA-42C7-B3CB-13667BCD7B54}.Debug|ARM.ActiveCfg = Debug|Any CPU
37 | {A6FCEF44-D2BA-42C7-B3CB-13667BCD7B54}.Debug|ARM.Build.0 = Debug|Any CPU
38 | {A6FCEF44-D2BA-42C7-B3CB-13667BCD7B54}.Debug|x64.ActiveCfg = Debug|Any CPU
39 | {A6FCEF44-D2BA-42C7-B3CB-13667BCD7B54}.Debug|x64.Build.0 = Debug|Any CPU
40 | {A6FCEF44-D2BA-42C7-B3CB-13667BCD7B54}.Debug|x86.ActiveCfg = Debug|Any CPU
41 | {A6FCEF44-D2BA-42C7-B3CB-13667BCD7B54}.Debug|x86.Build.0 = Debug|Any CPU
42 | {A6FCEF44-D2BA-42C7-B3CB-13667BCD7B54}.Release|Any CPU.ActiveCfg = Release|Any CPU
43 | {A6FCEF44-D2BA-42C7-B3CB-13667BCD7B54}.Release|Any CPU.Build.0 = Release|Any CPU
44 | {A6FCEF44-D2BA-42C7-B3CB-13667BCD7B54}.Release|ARM.ActiveCfg = Release|Any CPU
45 | {A6FCEF44-D2BA-42C7-B3CB-13667BCD7B54}.Release|ARM.Build.0 = Release|Any CPU
46 | {A6FCEF44-D2BA-42C7-B3CB-13667BCD7B54}.Release|x64.ActiveCfg = Release|Any CPU
47 | {A6FCEF44-D2BA-42C7-B3CB-13667BCD7B54}.Release|x64.Build.0 = Release|Any CPU
48 | {A6FCEF44-D2BA-42C7-B3CB-13667BCD7B54}.Release|x86.ActiveCfg = Release|Any CPU
49 | {A6FCEF44-D2BA-42C7-B3CB-13667BCD7B54}.Release|x86.Build.0 = Release|Any CPU
50 | EndGlobalSection
51 | GlobalSection(SolutionProperties) = preSolution
52 | HideSolutionNode = FALSE
53 | EndGlobalSection
54 | GlobalSection(ExtensibilityGlobals) = postSolution
55 | SolutionGuid = {BE23F6E2-7CBD-4BF6-8649-7E53095B89BF}
56 | EndGlobalSection
57 | EndGlobal
58 |
--------------------------------------------------------------------------------
/src/Plugin.AzurePushNotification/AzurePushNotificationManager.android.cs:
--------------------------------------------------------------------------------
1 | using Android.App;
2 | using Android.Content;
3 | using Android.Content.PM;
4 | using Android.Graphics;
5 | using Android.OS;
6 | using Android.Util;
7 | using Firebase.Iid;
8 | using Firebase.Messaging;
9 | using Java.Interop;
10 | using System;
11 | using System.Collections.Generic;
12 | using System.Collections.ObjectModel;
13 | using System.Linq;
14 | using System.Threading;
15 | using System.Threading.Tasks;
16 | using WindowsAzure.Messaging;
17 |
18 | namespace Plugin.AzurePushNotification
19 | {
20 | ///
21 | /// Implementation for Feature
22 | ///
23 | public class AzurePushNotificationManager : Java.Lang.Object, IAzurePushNotification, Android.Gms.Tasks.IOnCompleteListener
24 | {
25 |
26 | static NotificationHub Hub;
27 | static string DeviceToken { get; set; }
28 | static ICollection _tags = Application.Context.GetSharedPreferences(KeyGroupName, FileCreationMode.Private).GetStringSet(TagsKey, new Collection());
29 | public bool IsRegistered { get { return Application.Context.GetSharedPreferences(KeyGroupName, FileCreationMode.Private).GetBoolean(RegisteredKey, false); } }
30 | public string[] Tags { get { return _tags?.ToArray(); } }
31 |
32 | static NotificationResponse delayedNotificationResponse = null;
33 | internal const string KeyGroupName = "Plugin.AzurePushNotification";
34 | internal const string TagsKey = "TagsKey";
35 | internal static string TokenKey;
36 | internal static string RegisteredKey;
37 | internal const string AppVersionCodeKey = "AppVersionCodeKey";
38 | internal const string AppVersionNameKey = "AppVersionNameKey";
39 | internal const string AppVersionPackageNameKey = "AppVersionPackageNameKey";
40 |
41 | static IList userNotificationCategories = new List();
42 | public static string NotificationContentTitleKey { get; set; }
43 | public static string NotificationContentTextKey { get; set; }
44 | public static string NotificationContentDataKey { get; set; }
45 | public static int IconResource { get; set; }
46 | public static int LargeIconResource { get; set; }
47 | public static Android.Net.Uri SoundUri { get; set; }
48 | public static Color? Color { get; set; }
49 | public static Type NotificationActivityType { get; set; }
50 | public static ActivityFlags? NotificationActivityFlags { get; set; } = ActivityFlags.ClearTop | ActivityFlags.SingleTop;
51 | public static string DefaultNotificationChannelId { get; set; } = "AzurePushNotificationChannel";
52 | public static string DefaultNotificationChannelName { get; set; } = "General";
53 |
54 | static Context _context;
55 |
56 | internal static Type DefaultNotificationActivityType { get; set; } = null;
57 |
58 | static TaskCompletionSource _tokenTcs;
59 |
60 | public Func RetrieveSavedToken { get; set; } = InternalRetrieveSavedToken;
61 | public Action SaveToken { get; set; } = InternalSaveToken;
62 |
63 |
64 | public string Token
65 | {
66 | get
67 | {
68 | return !string.IsNullOrEmpty(TokenKey)? (RetrieveSavedToken?.Invoke() ?? string.Empty): null;
69 | }
70 | internal set
71 | {
72 | if(!string.IsNullOrEmpty(TokenKey))
73 | {
74 | SaveToken?.Invoke(value);
75 | }
76 |
77 | }
78 | }
79 | public static void ProcessIntent(Activity activity,Intent intent, bool enableDelayedResponse = true)
80 | {
81 | DefaultNotificationActivityType = activity.GetType();
82 | Bundle extras = intent?.Extras;
83 | if (extras != null && !extras.IsEmpty)
84 | {
85 | var parameters = new Dictionary();
86 | foreach (var key in extras.KeySet())
87 | {
88 | if (!parameters.ContainsKey(key) && extras.Get(key) != null)
89 | parameters.Add(key, $"{extras.Get(key)}");
90 | }
91 |
92 | NotificationManager manager = _context.GetSystemService(Context.NotificationService) as NotificationManager;
93 | var notificationId = extras.GetInt(DefaultPushNotificationHandler.ActionNotificationIdKey, -1);
94 | if (notificationId != -1)
95 | {
96 | var notificationTag = extras.GetString(DefaultPushNotificationHandler.ActionNotificationTagKey, string.Empty);
97 | if (notificationTag == null)
98 | manager.Cancel(notificationId);
99 | else
100 | manager.Cancel(notificationTag, notificationId);
101 | }
102 |
103 |
104 | var response = new NotificationResponse(parameters, extras.GetString(DefaultPushNotificationHandler.ActionIdentifierKey, string.Empty));
105 |
106 | if (_onNotificationOpened == null && enableDelayedResponse)
107 | delayedNotificationResponse = response;
108 | else
109 | _onNotificationOpened?.Invoke(CrossAzurePushNotification.Current, new AzurePushNotificationResponseEventArgs(response.Data, response.Identifier, response.Type));
110 |
111 | CrossAzurePushNotification.Current.NotificationHandler?.OnOpened(response);
112 | }
113 | }
114 |
115 | public static void Initialize(Context context, string notificationHubConnectionString, string notificationHubPath, bool resetToken, bool createDefaultNotificationChannel = true, bool autoRegistration = true)
116 | {
117 | TokenKey = $"{notificationHubPath}_Token";
118 | RegisteredKey = $"{notificationHubPath}_PushRegistered";
119 |
120 | Hub = new NotificationHub(notificationHubPath, notificationHubConnectionString, Android.App.Application.Context);
121 |
122 | _context = context;
123 |
124 | CrossAzurePushNotification.Current.NotificationHandler = CrossAzurePushNotification.Current.NotificationHandler ?? new DefaultPushNotificationHandler();
125 | FirebaseMessaging.Instance.AutoInitEnabled = autoRegistration;
126 | if (autoRegistration)
127 | {
128 | ThreadPool.QueueUserWorkItem(state =>
129 | {
130 |
131 | var packageName = Application.Context.PackageManager.GetPackageInfo(Application.Context.PackageName, PackageInfoFlags.MetaData).PackageName;
132 | var versionCode = Application.Context.PackageManager.GetPackageInfo(Application.Context.PackageName, PackageInfoFlags.MetaData).VersionCode;
133 | var versionName = Application.Context.PackageManager.GetPackageInfo(Application.Context.PackageName, PackageInfoFlags.MetaData).VersionName;
134 | var prefs = Android.App.Application.Context.GetSharedPreferences(AzurePushNotificationManager.KeyGroupName, FileCreationMode.Private);
135 |
136 | try
137 | {
138 |
139 | var storedVersionName = prefs.GetString(AzurePushNotificationManager.AppVersionNameKey, string.Empty);
140 | var storedVersionCode = prefs.GetString(AzurePushNotificationManager.AppVersionCodeKey, string.Empty);
141 | var storedPackageName = prefs.GetString(AzurePushNotificationManager.AppVersionPackageNameKey, string.Empty);
142 |
143 |
144 | if (!CrossAzurePushNotification.Current.IsRegistered || resetToken || (!string.IsNullOrEmpty(storedPackageName) && (!storedPackageName.Equals(packageName, StringComparison.CurrentCultureIgnoreCase) || !storedVersionName.Equals(versionName, StringComparison.CurrentCultureIgnoreCase) || !storedVersionCode.Equals($"{versionCode}", StringComparison.CurrentCultureIgnoreCase))))
145 | {
146 | ((AzurePushNotificationManager)CrossAzurePushNotification.Current).CleanUp(false);
147 |
148 | }
149 |
150 | }
151 | catch (Exception ex)
152 | {
153 | _onNotificationError?.Invoke(CrossAzurePushNotification.Current, new AzurePushNotificationErrorEventArgs(AzurePushNotificationErrorType.UnregistrationFailed, ex.ToString()));
154 | }
155 | finally
156 | {
157 | var editor = prefs.Edit();
158 | editor.PutString(AzurePushNotificationManager.AppVersionNameKey, $"{versionName}");
159 | editor.PutString(AzurePushNotificationManager.AppVersionCodeKey, $"{versionCode}");
160 | editor.PutString(AzurePushNotificationManager.AppVersionPackageNameKey, $"{packageName}");
161 | editor.Commit();
162 | }
163 |
164 |
165 | CrossAzurePushNotification.Current.RegisterForPushNotifications();
166 |
167 |
168 | });
169 | }
170 |
171 |
172 | if (Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O && createDefaultNotificationChannel)
173 | {
174 | // Create channel to show notifications.
175 | string channelId = DefaultNotificationChannelId;
176 | string channelName = DefaultNotificationChannelName;
177 | NotificationManager notificationManager = (NotificationManager)context.GetSystemService(Context.NotificationService);
178 |
179 | notificationManager.CreateNotificationChannel(new NotificationChannel(channelId,
180 | channelName, NotificationImportance.Default));
181 | }
182 |
183 |
184 | System.Diagnostics.Debug.WriteLine(CrossAzurePushNotification.Current.Token);
185 | }
186 |
187 | async Task GetTokenAsync()
188 | {
189 | _tokenTcs = new TaskCompletionSource();
190 | FirebaseInstanceId.Instance.GetInstanceId().AddOnCompleteListener(this);
191 |
192 | string retVal = null;
193 |
194 | try
195 | {
196 | retVal = await _tokenTcs.Task;
197 | }
198 | catch (Exception ex)
199 | {
200 | _onNotificationError?.Invoke(CrossAzurePushNotification.Current, new AzurePushNotificationErrorEventArgs(AzurePushNotificationErrorType.RegistrationFailed, $"{ex}"));
201 | }
202 |
203 | return retVal;
204 | }
205 | public static void Initialize(Context context, string notificationHubConnectionString, string notificationHubPath, NotificationUserCategory[] notificationCategories, bool resetToken, bool createDefaultNotificationChannel = true,bool autoRegistration = true)
206 | {
207 |
208 | Initialize(context, notificationHubConnectionString, notificationHubPath, resetToken, createDefaultNotificationChannel, autoRegistration);
209 | RegisterUserNotificationCategories(notificationCategories);
210 |
211 | }
212 |
213 |
214 | public void RegisterForPushNotifications()
215 | {
216 | FirebaseMessaging.Instance.AutoInitEnabled = true;
217 | System.Threading.Tasks.Task.Run(async () =>
218 | {
219 | var token = await GetTokenAsync();
220 | if (!string.IsNullOrEmpty(token))
221 | {
222 | Token = token;
223 | }
224 | });
225 |
226 | }
227 | public void UnregisterForPushNotifications()
228 | {
229 | FirebaseMessaging.Instance.AutoInitEnabled = false;
230 | Reset();
231 | }
232 |
233 | public void Reset()
234 | {
235 | try
236 | {
237 | ThreadPool.QueueUserWorkItem(state =>
238 | {
239 | CleanUp();
240 | });
241 | }
242 | catch (Exception ex)
243 | {
244 | _onNotificationError?.Invoke(CrossAzurePushNotification.Current, new AzurePushNotificationErrorEventArgs(AzurePushNotificationErrorType.UnregistrationFailed,ex.ToString()));
245 | }
246 |
247 |
248 | }
249 |
250 | void CleanUp(bool clearAll = true)
251 | {
252 | if(clearAll)
253 | {
254 | CrossAzurePushNotification.Current.UnregisterAsync();
255 | }
256 |
257 | FirebaseInstanceId.Instance.DeleteInstanceId();
258 | Token = string.Empty;
259 |
260 | }
261 |
262 |
263 | public static void Initialize(Context context, string notificationHubConnectionString, string notificationHubPath, IPushNotificationHandler pushNotificationHandler, bool resetToken, bool createDefaultNotificationChannel = true,bool autoRegistration = true)
264 | {
265 | CrossAzurePushNotification.Current.NotificationHandler = pushNotificationHandler;
266 | Initialize(context,notificationHubConnectionString,notificationHubPath, resetToken, createDefaultNotificationChannel, autoRegistration);
267 | }
268 |
269 | public static void ClearUserNotificationCategories()
270 | {
271 | userNotificationCategories.Clear();
272 | }
273 |
274 |
275 | static AzurePushNotificationDataEventHandler _onNotificationReceived;
276 | public event AzurePushNotificationDataEventHandler OnNotificationReceived
277 | {
278 | add
279 | {
280 | _onNotificationReceived += value;
281 | }
282 | remove
283 | {
284 | _onNotificationReceived -= value;
285 | }
286 | }
287 |
288 | static AzurePushNotificationDataEventHandler _onNotificationDeleted;
289 | public event AzurePushNotificationDataEventHandler OnNotificationDeleted
290 | {
291 | add
292 | {
293 | _onNotificationDeleted += value;
294 | }
295 | remove
296 | {
297 | _onNotificationDeleted -= value;
298 | }
299 | }
300 |
301 | static AzurePushNotificationResponseEventHandler _onNotificationOpened;
302 | public event AzurePushNotificationResponseEventHandler OnNotificationOpened
303 | {
304 | add
305 | {
306 | var previousVal = _onNotificationOpened;
307 | _onNotificationOpened += value;
308 | if (delayedNotificationResponse != null && previousVal == null)
309 | {
310 | var tmpParams = delayedNotificationResponse;
311 | _onNotificationOpened?.Invoke(CrossAzurePushNotification.Current, new AzurePushNotificationResponseEventArgs(tmpParams.Data, tmpParams.Identifier, tmpParams.Type));
312 | delayedNotificationResponse = null;
313 | }
314 | }
315 | remove
316 | {
317 | _onNotificationOpened -= value;
318 | }
319 | }
320 |
321 | static AzurePushNotificationTokenEventHandler _onTokenRefresh;
322 | public event AzurePushNotificationTokenEventHandler OnTokenRefresh
323 | {
324 | add
325 | {
326 | _onTokenRefresh += value;
327 | }
328 | remove
329 | {
330 | _onTokenRefresh -= value;
331 | }
332 | }
333 |
334 | static AzurePushNotificationErrorEventHandler _onNotificationError;
335 | public event AzurePushNotificationErrorEventHandler OnNotificationError
336 | {
337 | add
338 | {
339 | _onNotificationError += value;
340 | }
341 | remove
342 | {
343 | _onNotificationError -= value;
344 | }
345 | }
346 |
347 |
348 |
349 | public IPushNotificationHandler NotificationHandler { get; set; }
350 |
351 | public bool IsEnabled => FirebaseMessaging.Instance.AutoInitEnabled;
352 |
353 | public NotificationUserCategory[] GetUserNotificationCategories()
354 | {
355 | return userNotificationCategories?.ToArray();
356 | }
357 | public static void RegisterUserNotificationCategories(NotificationUserCategory[] notificationCategories)
358 | {
359 | if (notificationCategories != null && notificationCategories.Length > 0)
360 | {
361 | ClearUserNotificationCategories();
362 |
363 | foreach (var userCat in notificationCategories)
364 | {
365 | userNotificationCategories.Add(userCat);
366 | }
367 |
368 | }
369 | else
370 | {
371 | ClearUserNotificationCategories();
372 | }
373 | }
374 |
375 |
376 | public async Task RegisterAsync(string[] tags)
377 | {
378 | if (Hub != null)
379 | {
380 | _tags = tags;
381 | await Task.Run(() =>
382 | {
383 | if (!string.IsNullOrEmpty(DeviceToken))
384 | {
385 | if(IsRegistered && !string.IsNullOrEmpty(Token))
386 | {
387 | try
388 | {
389 | Hub.UnregisterAll(Token);
390 | }
391 | catch (Exception ex)
392 | {
393 | System.Diagnostics.Debug.WriteLine($"AzurePushNotification - Unregister- Error - {ex.Message}");
394 |
395 | _onNotificationError?.Invoke(CrossAzurePushNotification.Current, new AzurePushNotificationErrorEventArgs(AzurePushNotificationErrorType.NotificationHubUnregistrationFailed, ex.Message));
396 | }
397 | }
398 |
399 |
400 | try
401 | {
402 | Registration hubRegistration = null;
403 |
404 |
405 | if(tags !=null && tags.Length > 0)
406 | {
407 | hubRegistration = Hub.Register(DeviceToken,tags);
408 | }
409 | else
410 | {
411 | hubRegistration = Hub.Register(DeviceToken);
412 | }
413 |
414 | var editor = Application.Context.GetSharedPreferences(KeyGroupName, FileCreationMode.Private).Edit();
415 | editor.PutBoolean(RegisteredKey, true);
416 | editor.PutStringSet(TagsKey, _tags);
417 | editor.Commit();
418 |
419 | }
420 | catch (Exception ex)
421 | {
422 | System.Diagnostics.Debug.WriteLine($"AzurePushNotification - Register - Error - {ex.Message}");
423 | _onNotificationError?.Invoke(CrossAzurePushNotification.Current, new AzurePushNotificationErrorEventArgs(AzurePushNotificationErrorType.NotificationHubRegistrationFailed, ex.Message));
424 | }
425 | }
426 |
427 |
428 | });
429 | }
430 | }
431 |
432 |
433 | public async Task UnregisterAsync()
434 | {
435 | await Task.Run(() =>
436 | {
437 | if (Hub != null && !string.IsNullOrEmpty(Token))
438 | {
439 | try
440 | {
441 | Hub.UnregisterAll(Token);
442 |
443 | }
444 | catch (Exception ex)
445 | {
446 | System.Diagnostics.Debug.WriteLine($"AzurePushNotification - Error - {ex.Message}");
447 |
448 | _onNotificationError?.Invoke(CrossAzurePushNotification.Current, new AzurePushNotificationErrorEventArgs(AzurePushNotificationErrorType.NotificationHubUnregistrationFailed,ex.Message));
449 | }
450 | finally
451 | {
452 | // FirebaseInstanceId.Instance.DeleteInstanceId();
453 | //Token = string.Empty;
454 |
455 | _tags = new Collection();
456 | var editor = Application.Context.GetSharedPreferences(KeyGroupName, FileCreationMode.Private).Edit();
457 | editor.PutBoolean(RegisteredKey, false);
458 | editor.PutStringSet(TagsKey, _tags);
459 | editor.Commit();
460 | }
461 | }
462 | });
463 | }
464 |
465 | public void ClearAllNotifications()
466 | {
467 | NotificationManager manager = Application.Context.GetSystemService(Context.NotificationService) as NotificationManager;
468 | manager.CancelAll();
469 | }
470 |
471 | public void RemoveNotification(int id)
472 | {
473 | NotificationManager manager = Application.Context.GetSystemService(Context.NotificationService) as NotificationManager;
474 | manager.Cancel(id);
475 | }
476 |
477 | public void RemoveNotification(string tag, int id)
478 | {
479 | if (string.IsNullOrEmpty(tag))
480 | {
481 | RemoveNotification(id);
482 | }
483 | else
484 | {
485 | NotificationManager manager = Application.Context.GetSystemService(Context.NotificationService) as NotificationManager;
486 | manager.Cancel(tag, id);
487 | }
488 |
489 | }
490 |
491 | public void OnComplete(Android.Gms.Tasks.Task task)
492 | {
493 | try
494 | {
495 | if (task.IsSuccessful)
496 | {
497 | string token = task.Result.JavaCast().Token;
498 | _tokenTcs?.TrySetResult(token);
499 | }
500 | else
501 | {
502 | _tokenTcs?.TrySetException(task.Exception);
503 | }
504 |
505 | }
506 | catch (Exception ex)
507 | {
508 | _tokenTcs?.TrySetException(ex);
509 | }
510 | }
511 |
512 | #region internal methods
513 |
514 | internal static string InternalRetrieveSavedToken()
515 | {
516 | return Application.Context.GetSharedPreferences(KeyGroupName, FileCreationMode.Private).GetString(TokenKey, string.Empty);
517 | }
518 |
519 | internal static void InternalSaveToken(string token)
520 | {
521 | var editor = Application.Context.GetSharedPreferences(KeyGroupName, FileCreationMode.Private).Edit();
522 | editor.PutString(TokenKey, token);
523 | editor.Commit();
524 | }
525 | //Raises event for push notification token refresh
526 | internal static async void RegisterToken(string token)
527 | {
528 | DeviceToken = token;
529 | _onTokenRefresh?.Invoke(CrossAzurePushNotification.Current, new AzurePushNotificationTokenEventArgs(token));
530 | await CrossAzurePushNotification.Current.RegisterAsync(_tags?.ToArray());
531 | CrossAzurePushNotification.Current.SaveToken?.Invoke(token);
532 |
533 | }
534 | internal static void RegisterData(IDictionary data)
535 | {
536 | _onNotificationReceived?.Invoke(CrossAzurePushNotification.Current, new AzurePushNotificationDataEventArgs(data));
537 | }
538 | internal static void RegisterDelete(IDictionary data)
539 | {
540 | _onNotificationDeleted?.Invoke(CrossAzurePushNotification.Current, new AzurePushNotificationDataEventArgs(data));
541 | }
542 |
543 | #endregion
544 | }
545 | }
--------------------------------------------------------------------------------
/src/Plugin.AzurePushNotification/CrossAzurePushNotification.shared.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Plugin.AzurePushNotification
4 | {
5 | ///
6 | /// Cross platform AzurePushNotification implemenations
7 | ///
8 | public class CrossAzurePushNotification
9 | {
10 | static Lazy Implementation = new Lazy(() => CreateAzurePushNotification(), System.Threading.LazyThreadSafetyMode.PublicationOnly);
11 |
12 | ///
13 | /// Current settings to use
14 | ///
15 | public static IAzurePushNotification Current
16 | {
17 | get
18 | {
19 | var ret = Implementation.Value;
20 | if (ret == null)
21 | {
22 | throw NotImplementedInReferenceAssembly();
23 | }
24 | return ret;
25 | }
26 | }
27 |
28 | static IAzurePushNotification CreateAzurePushNotification()
29 | {
30 | #if NETSTANDARD2_0
31 | return null;
32 | #else
33 | return new AzurePushNotificationManager();
34 | #endif
35 | }
36 |
37 | internal static Exception NotImplementedInReferenceAssembly()
38 | {
39 | return new NotImplementedException("This functionality is not implemented in the portable version of this assembly. You should reference the NuGet package from your main application project in order to reference the platform-specific implementation.");
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/Plugin.AzurePushNotification/DefaultPushNotificationHandler.android.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | using Android.App;
7 | using Android.Content;
8 | using Android.Content.PM;
9 | using Android.Content.Res;
10 | using Android.Graphics;
11 | using Android.Media;
12 | using Android.OS;
13 | using Android.Runtime;
14 | using Android.Support.V4.App;
15 | using Android.Views;
16 | using Android.Widget;
17 | using Java.Util;
18 |
19 | namespace Plugin.AzurePushNotification
20 | {
21 | public class DefaultPushNotificationHandler : IPushNotificationHandler
22 | {
23 |
24 | public const string DomainTag = "DefaultPushNotificationHandler";
25 |
26 | ///
27 | /// Title
28 | ///
29 | public const string TitleKey = "title";
30 | ///
31 | /// Text
32 | ///
33 | public const string TextKey = "text";
34 | ///
35 | /// Subtitle
36 | ///
37 | public const string SubtitleKey = "subtitle";
38 | ///
39 | /// Message
40 | ///
41 | public const string MessageKey = "message";
42 | ///
43 | /// Message
44 | ///
45 | public const string BodyKey = "body";
46 | ///
47 | /// Alert
48 | ///
49 | public const string AlertKey = "alert";
50 |
51 | ///
52 | /// Id
53 | ///
54 | public const string IdKey = "id";
55 |
56 | ///
57 | /// Tag
58 | ///
59 | public const string TagKey = "tag";
60 |
61 | ///
62 | /// Action Click
63 | ///
64 | public const string ActionKey = "click_action";
65 |
66 | ///
67 | /// Category
68 | ///
69 | public const string CategoryKey = "category";
70 |
71 | ///
72 | /// Silent
73 | ///
74 | public const string SilentKey = "silent";
75 |
76 | ///
77 | /// ActionNotificationId
78 | ///
79 | public const string ActionNotificationIdKey = "action_notification_id";
80 |
81 | ///
82 | /// ActionNotificationTag
83 | ///
84 | public const string ActionNotificationTagKey = "action_notification_tag";
85 |
86 | ///
87 | /// ActionIdentifeir
88 | ///
89 | public const string ActionIdentifierKey = "action_identifier";
90 |
91 | ///
92 | /// Color
93 | ///
94 | public const string ColorKey = "color";
95 |
96 | ///
97 | /// Icon
98 | ///
99 | public const string IconKey = "icon";
100 |
101 | ///
102 | /// Large Icon
103 | ///
104 | public const string LargeIconKey = "large_icon";
105 |
106 | ///
107 | /// Sound
108 | ///
109 | public const string SoundKey = "sound";
110 |
111 | ///
112 | /// Priority
113 | ///
114 | public const string PriorityKey = "priority";
115 |
116 | ///
117 | /// Channel id
118 | ///
119 | public const string ChannelIdKey = "channel_id";
120 |
121 | public virtual void OnOpened(NotificationResponse response)
122 | {
123 | System.Diagnostics.Debug.WriteLine($"{DomainTag} - OnOpened");
124 | }
125 |
126 | public virtual void OnReceived(IDictionary parameters)
127 | {
128 | System.Diagnostics.Debug.WriteLine($"{DomainTag} - OnReceived");
129 |
130 | if (parameters.TryGetValue(SilentKey, out object silent) && (silent.ToString() == "true" || silent.ToString() == "1"))
131 | return;
132 |
133 | Context context = Application.Context;
134 |
135 | int notifyId = 0;
136 | string title = context.ApplicationInfo.LoadLabel(context.PackageManager);
137 | var message = string.Empty;
138 | var tag = string.Empty;
139 |
140 | if (!string.IsNullOrEmpty(AzurePushNotificationManager.NotificationContentTextKey) && parameters.TryGetValue(AzurePushNotificationManager.NotificationContentTextKey, out object notificationContentText))
141 | message = notificationContentText.ToString();
142 | else if (parameters.TryGetValue(AlertKey, out object alert))
143 | message = $"{alert}";
144 | else if (parameters.TryGetValue(BodyKey, out object body))
145 | message = $"{body}";
146 | else if (parameters.TryGetValue(MessageKey, out object messageContent))
147 | message = $"{messageContent}";
148 | else if (parameters.TryGetValue(SubtitleKey, out object subtitle))
149 | message = $"{subtitle}";
150 | else if (parameters.TryGetValue(TextKey, out object text))
151 | message = $"{text}";
152 |
153 | if (!string.IsNullOrEmpty(AzurePushNotificationManager.NotificationContentTitleKey) && parameters.TryGetValue(AzurePushNotificationManager.NotificationContentTitleKey, out object notificationContentTitle))
154 | title = notificationContentTitle.ToString();
155 | else if (parameters.TryGetValue(TitleKey, out object titleContent))
156 | {
157 | if (!string.IsNullOrEmpty(message))
158 | title = $"{titleContent}";
159 | else
160 | message = $"{titleContent}";
161 | }
162 |
163 | if (parameters.TryGetValue(IdKey, out object id))
164 | {
165 | try
166 | {
167 | notifyId = Convert.ToInt32(id);
168 | }
169 | catch (Exception ex)
170 | {
171 | // Keep the default value of zero for the notify_id, but log the conversion problem.
172 | System.Diagnostics.Debug.WriteLine($"Failed to convert {id} to an integer {ex}");
173 | }
174 | }
175 |
176 | if (parameters.TryGetValue(TagKey, out object tagContent))
177 | tag = tagContent.ToString();
178 |
179 |
180 | try
181 | {
182 | if (parameters.TryGetValue(SoundKey, out object sound))
183 | {
184 | var soundName = sound.ToString();
185 |
186 | int soundResId = context.Resources.GetIdentifier(soundName, "raw", context.PackageName);
187 | if (soundResId == 0 && soundName.IndexOf('.') != -1)
188 | {
189 | soundName = soundName.Substring(0, soundName.LastIndexOf('.'));
190 | soundResId = context.Resources.GetIdentifier(soundName, "raw", context.PackageName);
191 | }
192 |
193 | AzurePushNotificationManager.SoundUri = new Android.Net.Uri.Builder()
194 | .Scheme(ContentResolver.SchemeAndroidResource)
195 | .Path($"{context.PackageName}/{soundResId}")
196 | .Build();
197 |
198 | }
199 | }
200 | catch (Resources.NotFoundException ex)
201 | {
202 | System.Diagnostics.Debug.WriteLine(ex.ToString());
203 | }
204 | catch (Exception ex)
205 | {
206 | System.Diagnostics.Debug.WriteLine(ex.ToString());
207 | }
208 |
209 |
210 | if (AzurePushNotificationManager.SoundUri == null)
211 | AzurePushNotificationManager.SoundUri = RingtoneManager.GetDefaultUri(RingtoneType.Notification);
212 |
213 | try
214 | {
215 | if (parameters.TryGetValue(IconKey, out object icon) && icon != null)
216 | {
217 | try
218 | {
219 | AzurePushNotificationManager.IconResource = context.Resources.GetIdentifier($"{icon}", "drawable", Application.Context.PackageName);
220 | if (AzurePushNotificationManager.IconResource == 0)
221 | {
222 | AzurePushNotificationManager.IconResource = context.Resources.GetIdentifier($"{icon}", "mipmap", Application.Context.PackageName);
223 | }
224 | }
225 | catch (Resources.NotFoundException ex)
226 | {
227 | System.Diagnostics.Debug.WriteLine(ex.ToString());
228 | }
229 | }
230 |
231 | if (AzurePushNotificationManager.IconResource == 0)
232 | AzurePushNotificationManager.IconResource = context.ApplicationInfo.Icon;
233 | else
234 | {
235 | string name = context.Resources.GetResourceName(AzurePushNotificationManager.IconResource);
236 | if (name == null)
237 | AzurePushNotificationManager.IconResource = context.ApplicationInfo.Icon;
238 | }
239 | }
240 | catch (Resources.NotFoundException ex)
241 | {
242 | AzurePushNotificationManager.IconResource = context.ApplicationInfo.Icon;
243 | System.Diagnostics.Debug.WriteLine(ex.ToString());
244 | }
245 |
246 | try
247 | {
248 | if (parameters.TryGetValue(LargeIconKey, out object largeIcon) && largeIcon != null)
249 | {
250 | AzurePushNotificationManager.LargeIconResource = context.Resources.GetIdentifier($"{largeIcon}", "drawable", Application.Context.PackageName);
251 | if (AzurePushNotificationManager.LargeIconResource == 0)
252 | {
253 | AzurePushNotificationManager.LargeIconResource = context.Resources.GetIdentifier($"{largeIcon}", "mipmap", Application.Context.PackageName);
254 | }
255 | }
256 |
257 | if (AzurePushNotificationManager.LargeIconResource != 0)
258 | {
259 | string name = context.Resources.GetResourceName(AzurePushNotificationManager.LargeIconResource);
260 | if (name == null)
261 | AzurePushNotificationManager.LargeIconResource = 0;
262 | }
263 | }
264 | catch (Resources.NotFoundException ex)
265 | {
266 | AzurePushNotificationManager.LargeIconResource = 0;
267 | System.Diagnostics.Debug.WriteLine(ex.ToString());
268 | }
269 |
270 | if (parameters.TryGetValue(ColorKey, out object color) && color != null)
271 | {
272 | try
273 | {
274 | AzurePushNotificationManager.Color = Color.ParseColor(color.ToString());
275 | }
276 | catch (Exception ex)
277 | {
278 | System.Diagnostics.Debug.WriteLine($"{DomainTag} - Failed to parse color {ex}");
279 | }
280 | }
281 |
282 | Intent resultIntent = typeof(Activity).IsAssignableFrom(AzurePushNotificationManager.NotificationActivityType) ? new Intent(Application.Context, AzurePushNotificationManager.NotificationActivityType) : (AzurePushNotificationManager.DefaultNotificationActivityType == null ? context.PackageManager.GetLaunchIntentForPackage(context.PackageName) : new Intent(Application.Context, AzurePushNotificationManager.DefaultNotificationActivityType));
283 |
284 | Bundle extras = new Bundle();
285 | foreach (var p in parameters)
286 | extras.PutString(p.Key, p.Value.ToString());
287 |
288 | if (extras != null)
289 | {
290 | extras.PutInt(ActionNotificationIdKey, notifyId);
291 | extras.PutString(ActionNotificationTagKey, tag);
292 | resultIntent.PutExtras(extras);
293 | }
294 |
295 | if (AzurePushNotificationManager.NotificationActivityFlags != null)
296 | {
297 | resultIntent.SetFlags(AzurePushNotificationManager.NotificationActivityFlags.Value);
298 | }
299 | int requestCode = new Java.Util.Random().NextInt();
300 | var pendingIntent = PendingIntent.GetActivity(context, requestCode, resultIntent,PendingIntentFlags.UpdateCurrent);
301 |
302 | var chanId = AzurePushNotificationManager.DefaultNotificationChannelId;
303 | if (parameters.TryGetValue(ChannelIdKey, out object channelId) && channelId != null)
304 | {
305 | chanId = $"{channelId}";
306 | }
307 |
308 | var notificationBuilder = new NotificationCompat.Builder(context, chanId)
309 | .SetSmallIcon(AzurePushNotificationManager.IconResource)
310 | .SetContentTitle(title)
311 | .SetContentText(message)
312 | .SetAutoCancel(true)
313 | .SetContentIntent(pendingIntent);
314 |
315 | if(AzurePushNotificationManager.LargeIconResource != 0)
316 | {
317 | Bitmap largeIconBitmap = BitmapFactory.DecodeResource(context.Resources, AzurePushNotificationManager.LargeIconResource);
318 | notificationBuilder.SetLargeIcon(largeIconBitmap);
319 | }
320 | var deleteIntent = new Intent(context,typeof(PushNotificationDeletedReceiver));
321 | var pendingDeleteIntent = PendingIntent.GetBroadcast(context, requestCode, deleteIntent,PendingIntentFlags.CancelCurrent);
322 | notificationBuilder.SetDeleteIntent(pendingDeleteIntent);
323 |
324 | if (Build.VERSION.SdkInt < Android.OS.BuildVersionCodes.O)
325 | {
326 | if (parameters.TryGetValue(PriorityKey, out object priority) && priority != null)
327 | {
328 | var priorityValue = $"{priority}";
329 | if (!string.IsNullOrEmpty(priorityValue))
330 | {
331 | switch (priorityValue.ToLower())
332 | {
333 | case "max":
334 | notificationBuilder.SetPriority((int)Android.App.NotificationPriority.Max);
335 | notificationBuilder.SetVibrate(new long[] { 1000, 1000, 1000, 1000, 1000 });
336 | break;
337 | case "high":
338 | notificationBuilder.SetPriority((int)Android.App.NotificationPriority.High);
339 | notificationBuilder.SetVibrate(new long[] { 1000, 1000, 1000, 1000, 1000 });
340 | break;
341 | case "default":
342 | notificationBuilder.SetPriority((int)Android.App.NotificationPriority.Default);
343 | notificationBuilder.SetVibrate(new long[] { 1000, 1000, 1000, 1000, 1000 });
344 | break;
345 | case "low":
346 | notificationBuilder.SetPriority((int)Android.App.NotificationPriority.Low);
347 | break;
348 | case "min":
349 | notificationBuilder.SetPriority((int)Android.App.NotificationPriority.Min);
350 | break;
351 | default:
352 | notificationBuilder.SetPriority((int)Android.App.NotificationPriority.Default);
353 | notificationBuilder.SetVibrate(new long[] { 1000, 1000, 1000, 1000, 1000 });
354 | break;
355 | }
356 |
357 | }
358 | else
359 | {
360 | notificationBuilder.SetVibrate(new long[] { 1000, 1000, 1000, 1000, 1000 });
361 | }
362 |
363 | }
364 | else
365 | {
366 | notificationBuilder.SetVibrate(new long[] { 1000, 1000, 1000, 1000, 1000 });
367 | }
368 |
369 |
370 | try
371 | {
372 |
373 | notificationBuilder.SetSound(AzurePushNotificationManager.SoundUri);
374 | }
375 | catch (Exception ex)
376 | {
377 | System.Diagnostics.Debug.WriteLine($"{DomainTag} - Failed to set sound {ex}");
378 | }
379 | }
380 |
381 | // Try to resolve (and apply) localized parameters
382 | ResolveLocalizedParameters(notificationBuilder, parameters);
383 |
384 | if (AzurePushNotificationManager.Color != null)
385 | notificationBuilder.SetColor(AzurePushNotificationManager.Color.Value);
386 |
387 | if (Build.VERSION.SdkInt >= BuildVersionCodes.JellyBean)
388 | {
389 | // Using BigText notification style to support long message
390 | var style = new NotificationCompat.BigTextStyle();
391 | style.BigText(message);
392 | notificationBuilder.SetStyle(style);
393 | }
394 |
395 | string category = string.Empty;
396 | if (parameters.TryGetValue(CategoryKey, out object categoryContent))
397 | category = categoryContent.ToString();
398 |
399 | if (parameters.TryGetValue(ActionKey, out object actionContent))
400 | category = actionContent.ToString();
401 |
402 | var notificationCategories = CrossAzurePushNotification.Current?.GetUserNotificationCategories();
403 | if (notificationCategories != null && notificationCategories.Length > 0)
404 | {
405 | IntentFilter intentFilter = null;
406 | foreach (var userCat in notificationCategories)
407 | {
408 | if (userCat != null && userCat.Actions != null && userCat.Actions.Count > 0)
409 | {
410 |
411 | foreach (var action in userCat.Actions)
412 | {
413 | var aRequestCode = Guid.NewGuid().GetHashCode();
414 | if (userCat.Category.Equals(category, StringComparison.CurrentCultureIgnoreCase))
415 | {
416 | Intent actionIntent = null;
417 | PendingIntent pendingActionIntent = null;
418 |
419 |
420 | if (action.Type == NotificationActionType.Foreground)
421 | {
422 | actionIntent = typeof(Activity).IsAssignableFrom(AzurePushNotificationManager.NotificationActivityType) ? new Intent(Application.Context, AzurePushNotificationManager.NotificationActivityType) : (AzurePushNotificationManager.DefaultNotificationActivityType == null ? context.PackageManager.GetLaunchIntentForPackage(context.PackageName) : new Intent(Application.Context, AzurePushNotificationManager.DefaultNotificationActivityType));
423 |
424 | if (AzurePushNotificationManager.NotificationActivityFlags != null)
425 | {
426 | actionIntent.SetFlags(AzurePushNotificationManager.NotificationActivityFlags.Value);
427 | }
428 |
429 | extras.PutString(ActionIdentifierKey, action.Id);
430 | actionIntent.PutExtras(extras);
431 | pendingActionIntent = PendingIntent.GetActivity(context, aRequestCode, actionIntent, PendingIntentFlags.UpdateCurrent);
432 |
433 | }
434 | else
435 | {
436 | actionIntent = new Intent(context, typeof(PushNotificationActionReceiver));
437 | extras.PutString(ActionIdentifierKey, action.Id);
438 | actionIntent.PutExtras(extras);
439 | pendingActionIntent = PendingIntent.GetBroadcast(context, aRequestCode, actionIntent, PendingIntentFlags.UpdateCurrent);
440 |
441 | }
442 |
443 | notificationBuilder.AddAction(context.Resources.GetIdentifier(action.Icon, "drawable", Application.Context.PackageName), action.Title, pendingActionIntent);
444 | }
445 | }
446 | }
447 | }
448 |
449 | }
450 |
451 | OnBuildNotification(notificationBuilder, parameters);
452 |
453 | NotificationManager notificationManager = (NotificationManager)context.GetSystemService(Context.NotificationService);
454 | notificationManager.Notify(tag, notifyId, notificationBuilder.Build());
455 | }
456 |
457 | ///
458 | /// Resolves the localized parameters using the string resources, combining the key and the passed arguments of the notification.
459 | ///
460 | /// Notification builder.
461 | /// Parameters.
462 | void ResolveLocalizedParameters(NotificationCompat.Builder notificationBuilder, IDictionary parameters)
463 | {
464 | string getLocalizedString(string name, params string[] arguments)
465 | {
466 | var context = notificationBuilder.MContext;
467 | var resources = context.Resources;
468 | var identifier = resources.GetIdentifier(name, "string", context.PackageName);
469 | var sanitizedArgs = arguments?.Where(it => it != null).Select(it => new Java.Lang.String(it)).Cast().ToArray();
470 |
471 | try { return resources.GetString(identifier, sanitizedArgs ?? new Java.Lang.Object[] { }); }
472 | catch (UnknownFormatConversionException ex)
473 | {
474 | System.Diagnostics.Debug.WriteLine($"{DomainTag}.ResolveLocalizedParameters - Incorrect string arguments {ex}");
475 | return null;
476 | }
477 | }
478 |
479 | // Resolve title localization
480 | if (parameters.TryGetValue("title_loc_key", out object titleKey))
481 | {
482 | parameters.TryGetValue("title_loc_args", out object titleArgs);
483 |
484 | var localizedTitle = getLocalizedString(titleKey.ToString(), titleArgs as string[]);
485 | if (localizedTitle != null)
486 | notificationBuilder.SetContentTitle(localizedTitle);
487 | }
488 |
489 | // Resolve body localization
490 | if (parameters.TryGetValue("body_loc_key", out object bodyKey))
491 | {
492 | parameters.TryGetValue("body_loc_args", out object bodyArgs);
493 |
494 | var localizedBody = getLocalizedString(bodyKey.ToString(), bodyArgs as string[]);
495 | if (localizedBody != null)
496 | notificationBuilder.SetContentText(localizedBody);
497 | }
498 | }
499 |
500 | public virtual void OnError(string error)
501 | {
502 | System.Diagnostics.Debug.WriteLine($"{DomainTag} - OnError - {error}");
503 | }
504 |
505 | ///
506 | /// Override to provide customization of the notification to build.
507 | ///
508 | /// Notification builder.
509 | /// Notification parameters.
510 | public virtual void OnBuildNotification(NotificationCompat.Builder notificationBuilder, IDictionary parameters) { }
511 | }
512 | }
513 |
--------------------------------------------------------------------------------
/src/Plugin.AzurePushNotification/DefaultPushNotificationHandler.apple.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | using Foundation;
7 | using UIKit;
8 |
9 | namespace Plugin.AzurePushNotification
10 | {
11 | public class DefaultPushNotificationHandler : IPushNotificationHandler
12 | {
13 | public const string DomainTag = "DefaultPushNotificationHandler";
14 |
15 | public virtual void OnError(string error)
16 | {
17 | System.Diagnostics.Debug.WriteLine($"{DomainTag} - OnError - {error}");
18 | }
19 |
20 | public virtual void OnOpened(NotificationResponse response)
21 | {
22 | System.Diagnostics.Debug.WriteLine($"{DomainTag} - OnOpened");
23 | }
24 |
25 | public virtual void OnReceived(IDictionary parameters)
26 | {
27 | System.Diagnostics.Debug.WriteLine($"{DomainTag} - OnReceived");
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/Plugin.AzurePushNotification/IAzurePushNotification.shared.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Threading.Tasks;
4 |
5 | namespace Plugin.AzurePushNotification
6 | {
7 | public enum AzurePushNotificationErrorType
8 | {
9 | Unknown,
10 | PermissionDenied,
11 | RegistrationFailed,
12 | UnregistrationFailed,
13 | NotificationHubRegistrationFailed,
14 | NotificationHubUnregistrationFailed
15 | }
16 |
17 | public delegate void AzurePushNotificationTokenEventHandler(object source, AzurePushNotificationTokenEventArgs e);
18 |
19 | public class AzurePushNotificationTokenEventArgs : EventArgs
20 | {
21 | public string Token { get; }
22 |
23 | public AzurePushNotificationTokenEventArgs(string token)
24 | {
25 | Token = token;
26 | }
27 |
28 | }
29 |
30 | public delegate void AzurePushNotificationErrorEventHandler(object source, AzurePushNotificationErrorEventArgs e);
31 |
32 | public class AzurePushNotificationErrorEventArgs : EventArgs
33 | {
34 | public AzurePushNotificationErrorType Type;
35 | public string Message { get; }
36 |
37 | public AzurePushNotificationErrorEventArgs(AzurePushNotificationErrorType type, string message)
38 | {
39 | Type = type;
40 | Message = message;
41 | }
42 |
43 | }
44 |
45 | public delegate void AzurePushNotificationDataEventHandler(object source, AzurePushNotificationDataEventArgs e);
46 |
47 | public class AzurePushNotificationDataEventArgs : EventArgs
48 | {
49 | public IDictionary Data { get; }
50 |
51 | public AzurePushNotificationDataEventArgs(IDictionary data)
52 | {
53 | Data = data;
54 | }
55 |
56 | }
57 |
58 |
59 | public delegate void AzurePushNotificationResponseEventHandler(object source, AzurePushNotificationResponseEventArgs e);
60 |
61 | public class AzurePushNotificationResponseEventArgs : EventArgs
62 | {
63 | public string Identifier { get; }
64 |
65 | public IDictionary Data { get; }
66 |
67 | public NotificationCategoryType Type { get; }
68 |
69 | public AzurePushNotificationResponseEventArgs(IDictionary data, string identifier = "", NotificationCategoryType type = NotificationCategoryType.Default)
70 | {
71 | Identifier = identifier;
72 | Data = data;
73 | Type = type;
74 | }
75 |
76 | }
77 |
78 | ///
79 | /// Interface for AzurePushNotification
80 | ///
81 | public interface IAzurePushNotification
82 | {
83 | ///
84 | /// Get all user notification categories
85 | ///
86 | NotificationUserCategory[] GetUserNotificationCategories();
87 | ///
88 | /// Get all subscribed tags
89 | ///
90 | string[] Tags { get; }
91 | ///
92 | /// Subscribe to multiple tags
93 | ///
94 | Task RegisterAsync(string[] tags);
95 | ///
96 | /// Unsubscribe all tags
97 | ///
98 | Task UnregisterAsync();
99 | ///
100 | /// Notification handler to receive, customize notification feedback and provide user actions
101 | ///
102 | IPushNotificationHandler NotificationHandler { get; set; }
103 |
104 | ///
105 | /// Event triggered when token is refreshed
106 | ///
107 | event AzurePushNotificationTokenEventHandler OnTokenRefresh;
108 | ///
109 | /// Event triggered when a notification is opened
110 | ///
111 | event AzurePushNotificationResponseEventHandler OnNotificationOpened;
112 | ///
113 | /// Event triggered when a notification is received
114 | ///
115 | event AzurePushNotificationDataEventHandler OnNotificationReceived;
116 | ///
117 | /// Event triggered when a notification is deleted (Android Only)
118 | ///
119 | event AzurePushNotificationDataEventHandler OnNotificationDeleted;
120 | ///
121 | /// Event triggered when there's an error
122 | ///
123 | event AzurePushNotificationErrorEventHandler OnNotificationError;
124 | ///
125 | /// Register push notifications on demand
126 | ///
127 | ///
128 | void RegisterForPushNotifications();
129 | ///
130 | /// Unregister push notifications on demand
131 | ///
132 | ///
133 | void UnregisterForPushNotifications();
134 | ///
135 | /// Push notification token
136 | ///
137 | string Token { get; }
138 |
139 | ///
140 | /// Delegate to feed token back to the plugin
141 | ///
142 | Func RetrieveSavedToken { get; set; }
143 | ///
144 | /// Delegate to save the token
145 | ///
146 | Action SaveToken { get; set; }
147 |
148 | ///
149 | /// Indicates if push notifications are enabled
150 | ///
151 | bool IsEnabled { get; }
152 |
153 | ///
154 | /// Indicates if is registered in notification hub
155 | ///
156 | bool IsRegistered { get; }
157 |
158 | ///
159 | /// Clear all notifications
160 | ///
161 | void ClearAllNotifications();
162 |
163 | ///
164 | /// Remove specific id notification
165 | ///
166 | void RemoveNotification(int id);
167 |
168 | ///
169 | /// Remove specific id and tag notification
170 | ///
171 | void RemoveNotification(string tag, int id);
172 | }
173 | }
174 |
--------------------------------------------------------------------------------
/src/Plugin.AzurePushNotification/IPushNotificationHandler.shared.cs:
--------------------------------------------------------------------------------
1 |
2 |
3 | using System.Collections.Generic;
4 |
5 | namespace Plugin.AzurePushNotification
6 | {
7 | public interface IPushNotificationHandler
8 | {
9 | //Method triggered when an error occurs
10 | void OnError(string error);
11 | //Method triggered when a notification is opened
12 | void OnOpened(NotificationResponse response);
13 | //Method triggered when a notification is received
14 | void OnReceived(IDictionary parameters);
15 | }
16 | }
--------------------------------------------------------------------------------
/src/Plugin.AzurePushNotification/NotificationActionType.shared.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace Plugin.AzurePushNotification
6 | {
7 | public enum NotificationActionType
8 | {
9 | Default,
10 | AuthenticationRequired, //Only applies for iOS
11 | Foreground,
12 | Destructive //Only applies for iOS
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/Plugin.AzurePushNotification/NotificationCategoryType.shared.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Plugin.AzurePushNotification
8 | {
9 | //This just applies for iOS on Android is always set as default when used
10 | public enum NotificationCategoryType
11 | {
12 | Default,
13 | Custom,
14 | Dismiss
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/Plugin.AzurePushNotification/NotificationPriority.shared.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace Plugin.AzurePushNotification
6 | {
7 | public enum NotificationPriority
8 | {
9 | Max,
10 | High,
11 | Default,
12 | Low,
13 | Min
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/Plugin.AzurePushNotification/NotificationResponse.shared.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Plugin.AzurePushNotification
8 | {
9 | public class NotificationResponse
10 | {
11 | public string Identifier { get; }
12 |
13 | public IDictionary Data { get; }
14 |
15 | public NotificationCategoryType Type { get; }
16 |
17 | public NotificationResponse(IDictionary data, string identifier = "", NotificationCategoryType type = NotificationCategoryType.Default)
18 | {
19 | Identifier = identifier;
20 | Data = data;
21 | Type = type;
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/Plugin.AzurePushNotification/NotificationUserCategory.shared.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Plugin.AzurePushNotification
8 | {
9 | public class NotificationUserCategory
10 | {
11 | public string Category { get; }
12 | public List Actions { get; }
13 |
14 | public NotificationCategoryType Type { get; }
15 |
16 | public NotificationUserCategory(string category, List actions, NotificationCategoryType type = NotificationCategoryType.Default)
17 | {
18 | Category = category;
19 | Actions = actions;
20 | Type = type;
21 | }
22 | }
23 |
24 | public class NotificationUserAction
25 | {
26 | public string Id { get; }
27 | public string Title { get; }
28 | public NotificationActionType Type { get; }
29 | public string Icon { get; }
30 | public NotificationUserAction(string id, string title, NotificationActionType type = NotificationActionType.Default, string icon = "")
31 | {
32 | Id = id;
33 | Title = title;
34 | Type = type;
35 | Icon = icon;
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/Plugin.AzurePushNotification/PNMessagingService.android.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 |
4 | using Android.App;
5 | using Android.Content;
6 | using Firebase.Messaging;
7 |
8 | namespace Plugin.AzurePushNotification
9 | {
10 | [Service]
11 | [IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
12 | public class PNMessagingService : FirebaseMessagingService
13 | {
14 | public override void OnMessageReceived(RemoteMessage message)
15 | {
16 | var parameters = new Dictionary();
17 | var notification = message.GetNotification();
18 | if (notification != null)
19 | {
20 | if (!string.IsNullOrEmpty(notification.Body))
21 | parameters.Add("body", notification.Body);
22 |
23 | if (!string.IsNullOrEmpty(notification.BodyLocalizationKey))
24 | parameters.Add("body_loc_key", notification.BodyLocalizationKey);
25 |
26 | var bodyLocArgs = notification.GetBodyLocalizationArgs();
27 | if (bodyLocArgs != null && bodyLocArgs.Any())
28 | parameters.Add("body_loc_args", bodyLocArgs);
29 |
30 | if (!string.IsNullOrEmpty(notification.Title))
31 | parameters.Add("title", notification.Title);
32 |
33 | if (!string.IsNullOrEmpty(notification.TitleLocalizationKey))
34 | parameters.Add("title_loc_key", notification.TitleLocalizationKey);
35 |
36 | var titleLocArgs = notification.GetTitleLocalizationArgs();
37 | if (titleLocArgs != null && titleLocArgs.Any())
38 | parameters.Add("title_loc_args", titleLocArgs);
39 |
40 | if (!string.IsNullOrEmpty(notification.Tag))
41 | parameters.Add("tag", notification.Tag);
42 |
43 | if (!string.IsNullOrEmpty(notification.Sound))
44 | parameters.Add("sound", notification.Sound);
45 |
46 | if (!string.IsNullOrEmpty(notification.Icon))
47 | parameters.Add("icon", notification.Icon);
48 |
49 | if (notification.Link != null)
50 | parameters.Add("link_path", notification.Link.Path);
51 |
52 | if (!string.IsNullOrEmpty(notification.ClickAction))
53 | parameters.Add("click_action", notification.ClickAction);
54 |
55 | if (!string.IsNullOrEmpty(notification.Color))
56 | parameters.Add("color", notification.Color);
57 | }
58 | foreach (var d in message.Data)
59 | {
60 | if (!parameters.ContainsKey(d.Key))
61 | parameters.Add(d.Key, d.Value);
62 |
63 | }
64 |
65 | //Fix localization arguments parsing
66 | string[] localizationKeys=new string[]{ "title_loc_args", "body_loc_args"};
67 | foreach(var locKey in localizationKeys)
68 | {
69 | if (parameters.ContainsKey(locKey) && parameters[locKey] is string parameterValue)
70 | {
71 | if (parameterValue.StartsWith("[") && parameterValue.EndsWith("]") && parameterValue.Length > 2)
72 | {
73 |
74 | var arrayValues = parameterValue.Substring(1, parameterValue.Length - 2);
75 | parameters[locKey] = arrayValues.Split(',').Select(t => t.Trim()).ToArray();
76 | }
77 | else
78 | {
79 | parameters[locKey] = new string[] { };
80 | }
81 | }
82 | }
83 |
84 | AzurePushNotificationManager.RegisterData(parameters);
85 | CrossAzurePushNotification.Current.NotificationHandler?.OnReceived(parameters);
86 | }
87 |
88 | public override void OnNewToken(string p0)
89 | {
90 | AzurePushNotificationManager.RegisterToken(p0);
91 | System.Diagnostics.Debug.WriteLine($"REFRESHED TOKEN: {p0}");
92 | }
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/src/Plugin.AzurePushNotification/Plugin.AzurePushNotification.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0;MonoAndroid90;MonoAndroid10.0;Xamarin.iOS10;
5 | Plugin.AzurePushNotification
6 | Plugin.AzurePushNotification
7 | Plugin.AzurePushNotification
8 | $(AssemblyName) ($(TargetFramework))
9 | 2.0.0
10 | 2.0.0
11 | 2.0.0
12 | true
13 | en
14 | default
15 | $(DefineConstants);
16 |
17 | false
18 | false
19 |
20 | latest
21 | https://github.com/CrossGeeks/AzurePushNotificationPlugin/blob/master/LICENSE.md
22 | https://github.com/CrossGeeks/AzurePushNotificationPlugin
23 | https://github.com/CrossGeeks/AzurePushNotificationPlugin/blob/master/art/icon.png?raw=true
24 | https://github.com/CrossGeeks/AzurePushNotificationPlugin
25 | iOS,Android,azure,notifications hub,push notifications,xamarin,plugins,fcm,apn
26 |
27 | Azure Push Notification Plugin for Xamarin
28 | Receive and handle azure push notifications across Xamarin.iOS and Xamarin.Android
29 | Receive and handle azure push notifications across Xamarin.iOS and Xamarin.Android
30 | [Fix] iOS 13 fix and dependencies upgraded
31 | crossgeeks,rdelrosario
32 | Rendy Del Rosario
33 | Copyright 2017 CrossGeeks
34 | true
35 |
36 |
37 |
38 |
39 | full
40 | true
41 | false
42 |
43 |
44 |
45 | true
46 | pdbonly
47 | true
48 |
49 |
50 |
51 | 1701;1702;1591
52 | bin\$(Configuration)\$(TargetFramework)\Plugin.AzurePushNotification.xml
53 | Rendy Del Rosario
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/src/Plugin.AzurePushNotification/PushNotificationActionReceiver.android.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | using Android.App;
7 | using Android.Content;
8 | using Android.OS;
9 | using Android.Runtime;
10 | using Android.Views;
11 | using Android.Widget;
12 |
13 | namespace Plugin.AzurePushNotification
14 | {
15 | [BroadcastReceiver]
16 | public class PushNotificationActionReceiver : BroadcastReceiver
17 | {
18 | public override void OnReceive(Context context, Intent intent)
19 | {
20 | IDictionary parameters = new Dictionary();
21 | var extras = intent.Extras;
22 |
23 | if (extras != null && !extras.IsEmpty)
24 | {
25 | foreach (var key in extras.KeySet())
26 | {
27 | parameters.Add(key, $"{extras.Get(key)}");
28 | System.Diagnostics.Debug.WriteLine(key, $"{extras.Get(key)}");
29 | }
30 | }
31 |
32 | AzurePushNotificationManager.RegisterData(parameters);
33 |
34 | NotificationManager manager = context.GetSystemService(Context.NotificationService) as NotificationManager;
35 | var notificationId = extras.GetInt(DefaultPushNotificationHandler.ActionNotificationIdKey, -1);
36 | if (notificationId != -1)
37 | {
38 | var notificationTag = extras.GetString(DefaultPushNotificationHandler.ActionNotificationTagKey, string.Empty);
39 |
40 | if (notificationTag == null)
41 | manager.Cancel(notificationId);
42 | else
43 | manager.Cancel(notificationTag, notificationId);
44 |
45 | }
46 | }
47 | }
48 | }
--------------------------------------------------------------------------------
/src/Plugin.AzurePushNotification/PushNotificationDeletedReceiver.android.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Android.App;
3 | using Android.Content;
4 |
5 | namespace Plugin.AzurePushNotification
6 | {
7 | [BroadcastReceiver]
8 | public class PushNotificationDeletedReceiver : BroadcastReceiver
9 | {
10 | public override void OnReceive(Context context, Intent intent)
11 | {
12 | IDictionary parameters = new Dictionary();
13 | var extras = intent.Extras;
14 |
15 | if (extras != null && !extras.IsEmpty)
16 | {
17 | foreach (var key in extras.KeySet())
18 | {
19 | parameters.Add(key, $"{extras.Get(key)}");
20 | System.Diagnostics.Debug.WriteLine(key, $"{extras.Get(key)}");
21 | }
22 | }
23 |
24 | AzurePushNotificationManager.RegisterDelete(parameters);
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------