├── .gitattributes
├── .github
└── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── .gitignore
├── LICENSE
├── README.md
├── art
├── icon.ai
└── icon.png
├── cd-pipeline.yml
├── ci-pipeline.yml
├── docs
├── AndroidSetup.md
├── FAQ.md
├── GettingStarted.md
├── GoogleFirebaseConsoleSetup.md
├── References.md
└── iOSSetup.md
├── images
├── ConfigurationFileAndroid.PNG
├── ConfigurationFileiOS.PNG
├── Entitlementsplist.PNG
├── FirebaseAuthSignInMethod.PNG
├── FirebaseConsoleAddToAndroid.PNG
├── FirebaseConsoleAddToPlatform.PNG
├── FirebaseConsoleAddToiOS.PNG
├── FirebaseConsoleCreateApp.PNG
├── FirebaseConsoleEnableAuthGoogle.PNG
├── FirebaseConsoleSettings.PNG
├── googleclient.gif
├── iOSInfoplist.PNG
├── iOSInfoplistBundleID.PNG
└── iOSReversedClientID.PNG
├── samples
├── GoogleClientSample.sln
├── GoogleClientSample
│ ├── GoogleClientSample.Android
│ │ ├── Assets
│ │ │ └── AboutAssets.txt
│ │ ├── FodyWeavers.xml
│ │ ├── FodyWeavers.xsd
│ │ ├── GoogleClientSample.Android.csproj
│ │ ├── MainActivity.cs
│ │ ├── Properties
│ │ │ ├── AndroidManifest.xml
│ │ │ └── AssemblyInfo.cs
│ │ ├── Resources
│ │ │ ├── AboutResources.txt
│ │ │ ├── Resource.designer.cs
│ │ │ ├── drawable-hdpi
│ │ │ │ ├── ic_launcher_crossgeeks.png
│ │ │ │ ├── ic_launcher_crossgeeks_drop_shadow.png
│ │ │ │ └── icon.png
│ │ │ ├── drawable-xhdpi
│ │ │ │ ├── ic_launcher_crossgeeks.png
│ │ │ │ ├── ic_launcher_crossgeeks_drop_shadow.png
│ │ │ │ └── icon.png
│ │ │ ├── drawable-xxhdpi
│ │ │ │ ├── ic_launcher_crossgeeks.png
│ │ │ │ ├── ic_launcher_crossgeeks_drop_shadow.png
│ │ │ │ └── icon.png
│ │ │ ├── drawable
│ │ │ │ ├── googlelogo.png
│ │ │ │ ├── ic_launcher_crossgeeks.png
│ │ │ │ ├── ic_launcher_crossgeeks_drop_shadow.png
│ │ │ │ └── icon.png
│ │ │ ├── google-services.json
│ │ │ ├── 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
│ │ │ │ └── styles.xml
│ │ └── google-services.json
│ ├── GoogleClientSample.iOS
│ │ ├── AppDelegate.cs
│ │ ├── Assets.xcassets
│ │ │ ├── AppIcon.appiconset
│ │ │ │ ├── Contents.json
│ │ │ │ ├── Icon-60@2x.png
│ │ │ │ ├── Icon-76.png
│ │ │ │ ├── Icon-76@2x.png
│ │ │ │ ├── Icon-Small-40.png
│ │ │ │ ├── Icon-Small-40@2x.png
│ │ │ │ ├── Icon-Small.png
│ │ │ │ └── Icon-Small@2x.png
│ │ │ └── leo.imageset
│ │ │ │ └── Contents.json
│ │ ├── Entitlements.plist
│ │ ├── FodyWeavers.xml
│ │ ├── FodyWeavers.xsd
│ │ ├── GoogleClientSample.iOS.csproj
│ │ ├── GoogleService-Info.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@3x.png
│ │ │ ├── Icon-Small-40@3x.png
│ │ │ ├── Icon-Small@3x.png
│ │ │ └── LaunchScreen.storyboard
│ └── GoogleClientSample
│ │ ├── App.xaml
│ │ ├── App.xaml.cs
│ │ ├── FodyWeavers.xml
│ │ ├── GoogleClientSample.projitems
│ │ ├── GoogleClientSample.shproj
│ │ ├── MainPage.xaml
│ │ ├── MainPage.xaml.cs
│ │ ├── Models
│ │ └── UserProfile.cs
│ │ ├── ViewModels
│ │ └── LoginPageViewModel.cs
│ │ └── Views
│ │ ├── Converter
│ │ └── InvertBooleanConverter.cs
│ │ ├── LoginPage.xaml
│ │ └── LoginPage.xaml.cs
└── README.md
└── src
├── GoogleClient.sln
└── Plugin.GoogleClient
├── CrossGoogleClient.shared.cs
├── GoogleClientException.shared.cs
├── GoogleClientManager.android.cs
├── GoogleClientManager.apple.cs
├── GoogleUser.shared.cs
├── IGoogleClientManager.shared.cs
└── Plugin.GoogleClient.csproj
/.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 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 |
5 | ---
6 |
7 | **Describe the bug**
8 | A clear and concise description of what the bug is.
9 |
10 | **To Reproduce**
11 | Steps to reproduce the behavior:
12 | 1. Go to '...'
13 | 2. Click on '....'
14 | 3. Scroll down to '....'
15 | 4. See error
16 |
17 | **Expected behavior**
18 | A clear and concise description of what you expected to happen.
19 |
20 | **Screenshots**
21 | If applicable, add screenshots to help explain your problem.
22 |
23 | **Desktop (please complete the following information):**
24 | - OS: [e.g. iOS]
25 | - Browser [e.g. chrome, safari]
26 | - Version [e.g. 22]
27 |
28 | **Smartphone (please complete the following information):**
29 | - Device: [e.g. iPhone6]
30 | - OS: [e.g. iOS8.1]
31 | - Browser [e.g. stock browser, safari]
32 | - Version [e.g. 22]
33 |
34 | **Additional context**
35 | Add any other context about the problem here.
36 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 |
5 | ---
6 |
7 | **Is your feature request related to a problem? Please describe.**
8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
9 |
10 | **Describe the solution you'd like**
11 | A clear and concise description of what you want to happen.
12 |
13 | **Describe alternatives you've considered**
14 | A clear and concise description of any alternative solutions or features you've considered.
15 |
16 | **Additional context**
17 | Add any other context or screenshots about the feature request here.
18 |
--------------------------------------------------------------------------------
/.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 Rendy Del Rosario
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 | # Google Client Plugin for Xamarin iOS and Android
2 |
3 | [](https://dev.azure.com/CrossGeeks/Plugins/_build/latest?definitionId=3&branchName=master)
4 |
5 | Cross platform plugin for handling Google authentication.
6 |
7 |
8 |
9 |
10 |
11 | ### Setup
12 | * Available on Nuget: https://www.nuget.org/packages/Plugin.GoogleClient
13 | [](https://www.nuget.org/packages/Plugin.GoogleClient)
14 | * Install into your .NETStandard project and Client projects.
15 | * Create your [Google Firebase Console Platform](docs/GoogleFirebaseConsoleSetup.md) application.
16 | * Follow the [Android](docs/AndroidSetup.md) and [iOS](GoogleClient/docs/iOSSetup.md) guides
17 | * Check out [Getting Started](docs/GettingStarted.md)
18 |
19 | **Platform Support**
20 |
21 | |Platform|Version|
22 | | ------------------- | :------------------: |
23 | |Xamarin.iOS|iOS 8+|
24 | |Xamarin.Android|API 15+|
25 |
26 | ### API Usage
27 |
28 | Call **CrossGoogleClient.Current** from any project to gain access to API.
29 |
30 | ## Features
31 |
32 | - Authentication
33 |
34 | ## Documentation
35 |
36 | Here you will find detailed documentation on setting up and using the Google Client Plugin for Xamarin
37 |
38 | * [Google Firebase Console Setup](docs/GoogleFirebaseConsoleSetup.md)
39 | * [Android Setup](docs/AndroidSetup.md)
40 | * [iOS Setup](docs/iOSSetup.md)
41 |
42 | ### Google Client Sample Application
43 | * [Google Client Sample App](samples)
44 |
45 | ### References
46 | * [Documentation References](docs/References.md)
47 | * Google Sign In SDK Bindings by [Xamarin](https://github.com/xamarin):
48 |
49 | - [Xamarin.GooglePlayServices.Auth](https://www.nuget.org/packages/Xamarin.GooglePlayServices.Auth/)
50 |
51 | - [Xamarin.Google.iOS.SignIn](https://www.nuget.org/packages/Xamarin.Google.iOS.SignIn/)
52 |
53 | ### Contributors
54 |
55 | * [Luis Pujols](https://github.com/pujolsluis)
56 | * [Rendy Del Rosario](https://github.com/rdelrosario)
57 | * [RomaRudyak](https://github.com/RomaRudyak)
58 | * [Thiago Carvalho](https://github.com/stealthcold)
59 | * [Nathalia](https://github.com/natsoragge)
60 | * [NGumby](https://github.com/NGumby)
61 |
--------------------------------------------------------------------------------
/art/icon.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/art/icon.ai
--------------------------------------------------------------------------------
/art/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/art/icon.png
--------------------------------------------------------------------------------
/cd-pipeline.yml:
--------------------------------------------------------------------------------
1 | variables:
2 | MONO_VERSION: 6_4_0
3 | NETCORE_VERSION: '3.0.x'
4 | XCODE_VERSION: 11.1
5 |
6 | # set the version numbering, this results in 1.0.1 for the first build incrementing that way.
7 | name: 2.1$(rev:.r)
8 |
9 | # Defines that a commit to the master branch should trigger this build
10 | trigger:
11 | - master
12 |
13 | # Defines that PRs against this branch should also trigger this build
14 | pr:
15 | - master
16 |
17 | # the machine and prerequisites to run this build on
18 | pool:
19 | vmImage: macos-10.14
20 |
21 | # The different steps in our build
22 | steps:
23 |
24 | - bash: sudo $AGENT_HOMEDIRECTORY/scripts/select-xamarin-sdk.sh $(MONO_VERSION)
25 | displayName: Switch to the latest Xamarin SDK
26 |
27 | - 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
28 | displayName: Switch to the latest Xcode
29 |
30 | - task: UseDotNet@2
31 | displayName: 'Use .Net Core sdk'
32 | inputs:
33 | version: $(NETCORE_VERSION)
34 | includePreviewVersions: false
35 |
36 | # build and pack a beta version of the NuGet package. Versioning is done through the name tag in this definition.
37 | - task: MSBuild@1
38 | displayName: 'Build & Pack beta build'
39 | inputs:
40 | solution: 'src/Plugin.GoogleClient/Plugin.GoogleClient.csproj'
41 | configuration: 'Release'
42 | 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)'
43 | clean: true
44 |
45 | # build and pack a final version of the NuGet package. Versioning is done through the name tag in this definition.
46 | - task: MSBuild@1
47 | displayName: 'Build & Pack final build'
48 | inputs:
49 | solution: 'src/Plugin.GoogleClient/Plugin.GoogleClient.csproj'
50 | configuration: 'Release'
51 | 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)'
52 | clean: true
53 |
54 | # copy all the nupkg files created to the artifact directory
55 | - task: CopyFiles@2
56 | displayName: 'Copy Files to: $(build.artifactstagingdirectory)'
57 | inputs:
58 | SourceFolder: '$(build.sourcesdirectory)'
59 | Contents: '**\*.nupkg'
60 | TargetFolder: '$(build.artifactstagingdirectory)'
61 |
62 | # publish the artifacts as results of the build
63 | - task: PublishBuildArtifacts@1
64 | displayName: 'Publish Artifact: drop'
65 |
--------------------------------------------------------------------------------
/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/AndroidSetup.md:
--------------------------------------------------------------------------------
1 | # Android Setup
2 |
3 | * Install Plugin.GoogleClient package into your Android project.
4 |
5 | ## Prerequisites
6 | - Compatible Android device that runs Android 4.0+ and includes the Google Play Store or an emulator with an AVD that runs the Google APIs platform based on Android 4.2+ and has Google Play services 11.6+
7 | - The latest version of the Android SDK, including the SDK Tools component. You can get the latest SDK from the Android SDK Manager in Visual Studio.
8 | - Project configured to compile against Android 4.0(Ice Cream Sandwich) or newer.
9 | - The Google Play services SDK:
10 | 1. **Visual Studio 2017 Tools > Android > Android SDK Manager.**
11 | 2. Scroll to the bottom of the package list and select **Extras > Google Repository.** The page is downloaded to your computer and installed in your SDK environment where the android SDK on you're Visual Studio is Installed.
12 |
13 | 3. Complete the [Google Firebase Console Setup](GoogleFirebaseConsoleSetup.md) to include the required configuration file to your projects.
14 |
15 | ## AndroidManifest.xml
16 |
17 | Add this permission.
18 | ```xml
19 |
20 | ```
21 |
22 | ## MainActivity.cs
23 |
24 | - On the **OnCreate** method just after calling base.OnCreate:
25 | ```cs
26 | GoogleClientManager.Initialize(this);
27 | ```
28 |
29 | - Override the **OnActivityResult** method:
30 | ```cs
31 | protected override void OnActivityResult(int requestCode, Result resultCode, Android.Content.Intent data)
32 | {
33 | base.OnActivityResult(requestCode, resultCode, data);
34 | GoogleClientManager.OnAuthCompleted(requestCode, resultCode, data);
35 | }
36 | ```
37 |
38 | <= Back to [Table of Contents](../README.md)
39 |
--------------------------------------------------------------------------------
/docs/FAQ.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/docs/FAQ.md
--------------------------------------------------------------------------------
/docs/GettingStarted.md:
--------------------------------------------------------------------------------
1 | ### Getting Started
2 |
3 | If developing an application that supports iOS and Android, make sure you installed the NuGet package into your NETStandard project and Client projects.
4 |
5 | ### Setup
6 | * [Google Firebase Console Setup](GoogleFirebaseConsoleSetup.md)
7 | * [Android Setup](AndroidSetup.md)
8 | * [iOS Setup](iOSSetup.md)
9 |
10 | ### Login
11 |
12 | Here is an example on how to launch the login to the Google Client:
13 |
14 | ```cs
15 | CrossGoogleClient.Current.LoginAsync();
16 | ```
17 |
18 | This method returns a Google User which contains the basic profile of the user that was authenticated, with the following structure:
19 |
20 | ```cs
21 | public class GoogleUser
22 | {
23 | public string Id { get; set; }
24 | public string Name { get; set; }
25 | public string GivenName { get; set; }
26 | public string FamilyName { get; set; }
27 | public string Email { get; set; }
28 | public Uri Picture { get; set; }
29 | }
30 | ```
31 |
32 | ### Logout
33 |
34 | Here is an example on how to logout of the Google Client:
35 |
36 | ```cs
37 | CrossGoogleClient.Current.Logout();
38 | ```
39 |
40 | ### Available Properties
41 | * **AccessToken** (Signed In user access token)
42 | * **IdToken** (Signed In user id token)
43 |
44 | ### Events
45 |
46 | All async methods also trigger events:
47 |
48 | Login event:
49 |
50 | ```cs
51 | CrossGoogleClient.Current.OnLogin += (s,a)=>
52 | {
53 | switch (a.Status)
54 | {
55 | case GoogleActionStatus.Completed:
56 | //Logged in succesfully
57 | break;
58 | }
59 | };
60 | ```
61 |
62 |
63 | ### Exceptions
64 | Types of exceptions the user can handle from the Google Client plugin.
65 | ```cs
66 | // Indicates Google Client Plugin was not initialized correctly on the platform.
67 | GoogleClientNotInitializedErrorException
68 |
69 | // Indicates Google Sign In could not complete it's process correctly.
70 | SignInDefaultErrorException
71 |
72 | // Indicates an unknown error has occured.
73 | SignInUnknownErrorException
74 |
75 | // Indicates a problem reading or writing to the application keychain.
76 | SignInKeychainErrorException
77 |
78 | /* Indicates no appropriate applications are installed on the user's device which can handle
79 | sign-in. This code will only ever be returned if using webview and switching to browser have
80 | both been disabled. */
81 | SignInNoSignInHandlersInstalledErrorException
82 |
83 | /* Indicates there are no auth tokens in the keychain. This error code will be returned by
84 | signInSilently if the user has never signed in before with the given scopes, or if they have
85 | since signed out. */
86 | SignInHasNoAuthInKeychainErrorException
87 |
88 | // Indicates the user canceled the sign in request.
89 | SignInCanceledErrorException
90 |
91 | // Indicates the client attempted to call a method from an API that failed to connect.
92 | SignInApiNotConnectedErrorException
93 |
94 | // Indicates The client attempted to connect to the service with an invalid account name specified.
95 | SignInInvalidAccountErrorException
96 |
97 | // Indicates a network error occurred. Retrying should resolve the problem.
98 | SignInNetworkErrorException
99 |
100 | // Indicates an internal error occurred.
101 | SignInInternalErrorException
102 |
103 | // Indicates the client attempted to connect to the service but the user is not signed in.
104 | SignInRequiredErrorException
105 |
106 | // Indicates the sign in attempt didn't succeed with the current account.
107 | SignInFailedErrorException
108 | ```
109 |
110 | ### Enabling Server Auth Code or RequestIdToken Programmatically (Optional)
111 | If you have a more complex development flow, that integrates CI in which it's better to just set your Server Client ID and RequestIdToken programmatically for the Plugin you can do so, sending the Web Client Id on each projects Initialize method respectively.
112 |
113 | - Relevant Google Documentation about this topic:
114 |
115 | [Authenticate with a backend server](https://developers.google.com/identity/sign-in/android/backend-auth)
116 |
117 | [Get your backend server's OAuth 2.0 client ID](https://developers.google.com/identity/sign-in/android/start-integrating#get_your_backend_servers_oauth_20_client_id)
118 |
119 | #### Android
120 | ```cs
121 | /* 1st Parameter (MainActivity), 2nd Parameter enables the ServerAuthCode
122 | 3rd Parameter enables the RequestIdToken.
123 | (You pass the server web client id to both parameters).
124 | */
125 | GoogleClientManager.Initialize(this, "Xewa3121FDvbam", "Xewa3121FDvbam");
126 | ```
127 | After applying this changes, you should now be able to see that your AccessToken no longer returns null when you access it on the plugin after a successful login.
128 |
129 | #### iOS
130 | ```cs
131 | GoogleClientManager.Initialize("Xewa3121FDvbam");
132 | ```
133 |
134 |
135 | ### Silent Login
136 | If you wish to silently login your users if they have already authenticated on their device without the need to interact with the UI from the Google Sign In SDK and simply set your UI on the Authenticated state.
137 |
138 | You can now do this simply calling this line of code:
139 | ```cs
140 | CrossGoogleClient.Current.SilentLoginAsync();
141 | ```
142 |
143 | ### Enable Additional Scopes and API's
144 | In case you wish to enable additional Scopes and API’s to access different types of information, you can now do so simply by passing in 2 new parameters containing arrays with the scopes and API’s you want to enable on the Google Plugin Initialize method.
145 |
146 | Signature of the initialize methods:
147 | ```cs
148 | //Android initialize method.
149 | public static void Initialize(
150 | Activity activity,
151 | string serverClientId = null,
152 | string clientId = null,
153 | Api[] apis = null,
154 | string[] scopes = null)
155 | ```
156 |
157 | ```cs
158 | //iOS initialize method.
159 | public static void Initialize(
160 | string serverClientId = null,
161 | string[] scopes = null)
162 | ```
163 |
164 | <= Back to [Table of Contents](../../README.md)
165 |
--------------------------------------------------------------------------------
/docs/GoogleFirebaseConsoleSetup.md:
--------------------------------------------------------------------------------
1 | # Google Firebase Console Setup Android & iOS
2 | ## Android Setup
3 | **1.** First of all, we will have to create an application on the Google Firebase Console. You can access it [here.](https://console.firebase.google.com/)
4 |
5 | 
6 |
7 | ## Enable Google Authentication
8 | After creating your project, go to the Authentication section in the left hamburger menu of the Firebase Console, and press Select Sign In Method.
9 |
10 | 
11 |
12 |
13 | In the Sign-in provides options, select and enable Google.
14 |
15 | 
16 |
17 | ## Configuration File
18 | After creating your project and enabling Google Sign In on the Google Firebase Console, we will need a configuration file for our application, you can generate the file from your project settings section (press the settings knob).
19 |
20 | 
21 |
22 | **2.** Select the platform you wish to generate the configuration file for, in this case we will select **Android**.
23 |
24 | 
25 |
26 | **3.** After selecting Android, we will need to fill out the form with the information of our App, to enable Google Sign-In, and to do so we will need to provide Google with the package name, the name of the App and a SHA-1 certificate.
27 |
28 | 
29 |
30 | For our example application we will use a debug key, but to publish your app to the store, you will need a different SHA-1 key. You can read more about it [here](https://docs.microsoft.com/en-us/xamarin/android/platform/maps-and-location/maps/obtaining-a-google-maps-api-key?tabs=vswin#Obtaining_your_Signing_Key_Fingerprint).
31 |
32 | For the SHA-1 debug key you will need to modify the command below, open a CMD or Terminal and paste the bash:
33 |
34 | **macOS**
35 | ```bash
36 | keytool -list -v -keystore /Users/[USERNAME]/.local/share/Xamarin/Mono\ for\ Android/debug.keystore -alias androiddebugkey -storepass android -keypass android
37 | ```
38 |
39 | **Windows**
40 |
41 | ```bash
42 | keytool -list -v -keystore "C:\Users\[USERNAME]\AppData\Local\Xamarin\Mono for Android\debug.keystore" -alias androiddebugkey -storepass android -keypass android
43 |
44 | ```
45 | Other alternative is to adding this method and calling it on the MainActivity OnCreate method to get the SHA 1 printed on the application output:
46 |
47 | ```cs
48 | public static void PrintHashKey (Context pContext)
49 | {
50 | try {
51 | PackageInfo info = Android.App.Application.Context.PackageManager.GetPackageInfo (Android.App.Application.Context.PackageName, PackageInfoFlags.Signatures);
52 | foreach (var signature in info.Signatures) {
53 | MessageDigest md = MessageDigest.GetInstance ("SHA");
54 | md.Update (signature.ToByteArray ());
55 |
56 | System.Diagnostics.Debug.WriteLine (BitConverter.ToString(md.Digest ()).Replace ("-", ":"));
57 | }
58 | } catch (NoSuchAlgorithmException e) {
59 | System.Diagnostics.Debug.WriteLine (e);
60 | } catch (Exception e) {
61 | System.Diagnostics.Debug.WriteLine (e);
62 | }
63 | }
64 | ```
65 |
66 | **4.** Finally, you will be able to download the **google-services.json** file and add it to your **Xamarin.Android** project. Make sure build action is **GoogleServicesJson**
67 |
68 | > The **GoogleServicesJson** build action may be unavailable in visual studio for mac, manually add the following to YourProject.Android.csproj
69 | ```xml
70 |
71 |
72 |
73 | ```
74 |
75 | 
76 |
77 |
78 | >**Note:**
79 | >If you replace the google-servies.json file on the sample project and change the Xamarin.Android package name of the project to yours, the android sample project should work.
80 |
81 |
82 | ## iOS Setup
83 | We will also need to create a configuration file for iOS, which you can get in the settings section of you're project in Firebase Console, the steps are very similar to the one we just did for android, you will select the Application name we initially created and your **application bundle id**. This time there will be no need to add SHA-1 certificate, so go ahead and enable the Google Sign-In option.
84 |
85 | You can find your application bundle id by opening the **Info.plist** file in your iOS Project.
86 | 
87 |
88 | Fill out the form with the required information and register the App.
89 |
90 | 
91 |
92 |
93 | 2. Download the **GoogleService-Info.plist** file and add it to your **Xamarin.iOS** project, **Important:** you must set the Build Action of this file as a BundleResource so the Plugin can find it as part of the app bundle at runtime.
94 |
95 | 
96 |
97 | 3. Next we will have to add the URL Scheme to our project. So Open the **GoogleService-Info.plist** file and copy the `REVERSED_CLIENT_ID` value.
98 | 
99 |
100 | 4. Then open the Xamarin.iOS **Info.plist** file, go to the Advanced tab, create a new URL with the editor role and paste it in the URL Scheme Field.
101 | 
102 |
103 |
104 | >**Note:**
105 | >To be able to run the iOS project on the simulator, you will have to enable Keychain sharing on the **Entitlements.plist**:
106 |
107 | 
108 |
109 | Key chain sharing on iOS, need entitlements and for that we need a valid provision profile, find out more about it [here.](https://developer.apple.com/library/content/documentation/IDEs/Conceptual/AppDistributionGuide/MaintainingProfiles/MaintainingProfiles.html)
110 |
111 |
112 | After you have completed the integration of the configurations file to your project you're ready for the final steps in the [Android Setup](AndroidSetup.md) and [iOS Setup](iOSSetup.md) guides.
113 |
114 | ----------
115 | <= Back to [Table of Contents](../../README.md)
116 |
--------------------------------------------------------------------------------
/docs/References.md:
--------------------------------------------------------------------------------
1 | # References
2 | - https://montemagno.com/new-plugin-for-xamarin-multi-target-templates-for-visual-studio-2017/
3 | - https://causerexception.com/2017/12/03/google-native-login-with-xamarin-forms/
4 | - https://console.developers.google.com/cloud-resource-manager
5 | - https://developers.google.com/identity/sign-in/android/sign-in
6 | - https://github.com/xamarin/google-apis
7 | - https://developer.apple.com/library/content/documentation/IDEs/Conceptual/AppDistributionGuide/MaintainingProfiles/MaintainingProfiles.html
8 | - https://components.xamarin.com/view/googleiossignin
9 | - https://developers.google.com/identity/sign-in/ios/start
10 | - https://stackoverflow.com/questions/39487368/xamarin-auth-store-keychain-not-working-after-ios10-upgrade/39576798#39576798
11 | - https://developer.apple.com/library/content/documentation/IDEs/Conceptual/AppDistributionGuide/AddingCapabilities/AddingCapabilities.html
12 | - https://developer.xamarin.com/samples/monodroid/google-services/SigninQuickstart/
13 | - https://developer.xamarin.com/guides/android/platform_features/maps_and_location/maps/obtaining_a_google_maps_api_key/
14 | - http://evgenii.com/blog/sharing-keychain-in-ios/
15 | - https://msdn.microsoft.com/en-us/library/018hxwa8(v=vs.110).aspx
16 |
--------------------------------------------------------------------------------
/docs/iOSSetup.md:
--------------------------------------------------------------------------------
1 | # iOS Setup
2 |
3 | * Install Plugin.GoogleClient package into your iOS project.
4 |
5 | ## Prerequisites
6 | 1. Complete the [Google Firebase Console Setup](GoogleFirebaseConsoleSetup.md) to include the required configuration file to you're projects.
7 |
8 | ## AppDelegate.cs
9 | - On the FinishedLaunching method just after calling global::Xamarin.Forms.Forms.Init():
10 | ```cs
11 | GoogleClientManager.Initialize();
12 | ```
13 |
14 | ## Override OpenUrl method
15 | Override the OpenUrl method from AppDelegate class:
16 | ```cs
17 | public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options)
18 | {
19 | return GoogleClientManager.OnOpenUrl(app, url, options);
20 | }
21 | ```
22 |
23 |
24 | <= Back to [Table of Contents](../README.md)
25 |
--------------------------------------------------------------------------------
/images/ConfigurationFileAndroid.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/images/ConfigurationFileAndroid.PNG
--------------------------------------------------------------------------------
/images/ConfigurationFileiOS.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/images/ConfigurationFileiOS.PNG
--------------------------------------------------------------------------------
/images/Entitlementsplist.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/images/Entitlementsplist.PNG
--------------------------------------------------------------------------------
/images/FirebaseAuthSignInMethod.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/images/FirebaseAuthSignInMethod.PNG
--------------------------------------------------------------------------------
/images/FirebaseConsoleAddToAndroid.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/images/FirebaseConsoleAddToAndroid.PNG
--------------------------------------------------------------------------------
/images/FirebaseConsoleAddToPlatform.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/images/FirebaseConsoleAddToPlatform.PNG
--------------------------------------------------------------------------------
/images/FirebaseConsoleAddToiOS.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/images/FirebaseConsoleAddToiOS.PNG
--------------------------------------------------------------------------------
/images/FirebaseConsoleCreateApp.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/images/FirebaseConsoleCreateApp.PNG
--------------------------------------------------------------------------------
/images/FirebaseConsoleEnableAuthGoogle.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/images/FirebaseConsoleEnableAuthGoogle.PNG
--------------------------------------------------------------------------------
/images/FirebaseConsoleSettings.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/images/FirebaseConsoleSettings.PNG
--------------------------------------------------------------------------------
/images/googleclient.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/images/googleclient.gif
--------------------------------------------------------------------------------
/images/iOSInfoplist.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/images/iOSInfoplist.PNG
--------------------------------------------------------------------------------
/images/iOSInfoplistBundleID.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/images/iOSInfoplistBundleID.PNG
--------------------------------------------------------------------------------
/images/iOSReversedClientID.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/images/iOSReversedClientID.PNG
--------------------------------------------------------------------------------
/samples/GoogleClientSample.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.27428.2015
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GoogleClientSample.Android", "GoogleClientSample\GoogleClientSample.Android\GoogleClientSample.Android.csproj", "{B76A75BD-7702-4D34-B24A-35FFC6BD67F4}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GoogleClientSample.iOS", "GoogleClientSample\GoogleClientSample.iOS\GoogleClientSample.iOS.csproj", "{7A5621F7-4621-4ABA-9F37-531B755149AE}"
9 | EndProject
10 | Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "GoogleClientSample", "GoogleClientSample\GoogleClientSample\GoogleClientSample.shproj", "{8105EAC0-7139-4222-8EA5-19AD7430CA07}"
11 | EndProject
12 | Global
13 | GlobalSection(SharedMSBuildProjectFiles) = preSolution
14 | GoogleClientSample\GoogleClientSample\GoogleClientSample.projitems*{7a5621f7-4621-4aba-9f37-531b755149ae}*SharedItemsImports = 4
15 | GoogleClientSample\GoogleClientSample\GoogleClientSample.projitems*{8105eac0-7139-4222-8ea5-19ad7430ca07}*SharedItemsImports = 13
16 | GoogleClientSample\GoogleClientSample\GoogleClientSample.projitems*{b76a75bd-7702-4d34-b24a-35ffc6bd67f4}*SharedItemsImports = 4
17 | EndGlobalSection
18 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
19 | Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
20 | Ad-Hoc|iPhone = Ad-Hoc|iPhone
21 | Ad-Hoc|iPhoneSimulator = Ad-Hoc|iPhoneSimulator
22 | AppStore|Any CPU = AppStore|Any CPU
23 | AppStore|iPhone = AppStore|iPhone
24 | AppStore|iPhoneSimulator = AppStore|iPhoneSimulator
25 | Debug|Any CPU = Debug|Any CPU
26 | Debug|iPhone = Debug|iPhone
27 | Debug|iPhoneSimulator = Debug|iPhoneSimulator
28 | Release|Any CPU = Release|Any CPU
29 | Release|iPhone = Release|iPhone
30 | Release|iPhoneSimulator = Release|iPhoneSimulator
31 | EndGlobalSection
32 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
33 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
34 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
35 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}.Ad-Hoc|Any CPU.Deploy.0 = Release|Any CPU
36 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
37 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
38 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}.Ad-Hoc|iPhone.Deploy.0 = Release|Any CPU
39 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
40 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
41 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}.Ad-Hoc|iPhoneSimulator.Deploy.0 = Release|Any CPU
42 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
43 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}.AppStore|Any CPU.Build.0 = Release|Any CPU
44 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}.AppStore|Any CPU.Deploy.0 = Release|Any CPU
45 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}.AppStore|iPhone.ActiveCfg = Release|Any CPU
46 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}.AppStore|iPhone.Build.0 = Release|Any CPU
47 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}.AppStore|iPhone.Deploy.0 = Release|Any CPU
48 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
49 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
50 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}.AppStore|iPhoneSimulator.Deploy.0 = Release|Any CPU
51 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
52 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}.Debug|Any CPU.Build.0 = Debug|Any CPU
53 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
54 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}.Debug|iPhone.ActiveCfg = Debug|Any CPU
55 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}.Debug|iPhone.Build.0 = Debug|Any CPU
56 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}.Debug|iPhone.Deploy.0 = Debug|Any CPU
57 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
58 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
59 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}.Debug|iPhoneSimulator.Deploy.0 = Debug|Any CPU
60 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
61 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}.Release|Any CPU.Build.0 = Release|Any CPU
62 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}.Release|Any CPU.Deploy.0 = Release|Any CPU
63 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}.Release|iPhone.ActiveCfg = Release|Any CPU
64 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}.Release|iPhone.Build.0 = Release|Any CPU
65 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}.Release|iPhone.Deploy.0 = Release|Any CPU
66 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
67 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
68 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU
69 | {7A5621F7-4621-4ABA-9F37-531B755149AE}.Ad-Hoc|Any CPU.ActiveCfg = Ad-Hoc|iPhone
70 | {7A5621F7-4621-4ABA-9F37-531B755149AE}.Ad-Hoc|iPhone.ActiveCfg = Ad-Hoc|iPhone
71 | {7A5621F7-4621-4ABA-9F37-531B755149AE}.Ad-Hoc|iPhone.Build.0 = Ad-Hoc|iPhone
72 | {7A5621F7-4621-4ABA-9F37-531B755149AE}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Ad-Hoc|iPhoneSimulator
73 | {7A5621F7-4621-4ABA-9F37-531B755149AE}.Ad-Hoc|iPhoneSimulator.Build.0 = Ad-Hoc|iPhoneSimulator
74 | {7A5621F7-4621-4ABA-9F37-531B755149AE}.AppStore|Any CPU.ActiveCfg = AppStore|iPhone
75 | {7A5621F7-4621-4ABA-9F37-531B755149AE}.AppStore|iPhone.ActiveCfg = AppStore|iPhone
76 | {7A5621F7-4621-4ABA-9F37-531B755149AE}.AppStore|iPhone.Build.0 = AppStore|iPhone
77 | {7A5621F7-4621-4ABA-9F37-531B755149AE}.AppStore|iPhoneSimulator.ActiveCfg = AppStore|iPhoneSimulator
78 | {7A5621F7-4621-4ABA-9F37-531B755149AE}.AppStore|iPhoneSimulator.Build.0 = AppStore|iPhoneSimulator
79 | {7A5621F7-4621-4ABA-9F37-531B755149AE}.Debug|Any CPU.ActiveCfg = Debug|iPhone
80 | {7A5621F7-4621-4ABA-9F37-531B755149AE}.Debug|iPhone.ActiveCfg = Debug|iPhone
81 | {7A5621F7-4621-4ABA-9F37-531B755149AE}.Debug|iPhone.Build.0 = Debug|iPhone
82 | {7A5621F7-4621-4ABA-9F37-531B755149AE}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
83 | {7A5621F7-4621-4ABA-9F37-531B755149AE}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
84 | {7A5621F7-4621-4ABA-9F37-531B755149AE}.Release|Any CPU.ActiveCfg = Release|iPhone
85 | {7A5621F7-4621-4ABA-9F37-531B755149AE}.Release|iPhone.ActiveCfg = Release|iPhone
86 | {7A5621F7-4621-4ABA-9F37-531B755149AE}.Release|iPhone.Build.0 = Release|iPhone
87 | {7A5621F7-4621-4ABA-9F37-531B755149AE}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
88 | {7A5621F7-4621-4ABA-9F37-531B755149AE}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
89 | {7A5621F7-4621-4ABA-9F37-531B755149AE}.Debug|Any CPU.Build.0 = Debug|iPhone
90 | EndGlobalSection
91 | GlobalSection(SolutionProperties) = preSolution
92 | HideSolutionNode = FALSE
93 | EndGlobalSection
94 | GlobalSection(ExtensibilityGlobals) = postSolution
95 | SolutionGuid = {04D4BAEC-52F0-4193-913C-9215B1E554DC}
96 | EndGlobalSection
97 | EndGlobal
98 |
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.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/GoogleClientSample/GoogleClientSample.Android/FodyWeavers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.Android/FodyWeavers.xsd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Used to control if the On_PropertyName_Changed feature is enabled.
12 |
13 |
14 |
15 |
16 | Used to change the name of the method that fires the notify event. This is a string that accepts multiple values in a comma separated form.
17 |
18 |
19 |
20 |
21 | Used to control if equality checks should be inserted. If false, equality checking will be disabled for the project.
22 |
23 |
24 |
25 |
26 | Used to control if equality checks should use the Equals method resolved from the base class.
27 |
28 |
29 |
30 |
31 | Used to control if equality checks should use the static Equals method resolved from the base class.
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.
40 |
41 |
42 |
43 |
44 | A comma-separated list of error codes that can be safely ignored in assembly verification.
45 |
46 |
47 |
48 |
49 | 'false' to turn off automatic generation of the XML Schema file.
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.Android/GoogleClientSample.Android.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | {B76A75BD-7702-4D34-B24A-35FFC6BD67F4}
7 | {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
8 | Library
9 | GoogleClientSample.Droid
10 | GoogleClientSample.Android
11 | v10.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 |
51 |
52 |
53 |
54 |
55 | 4.4.0.991477
56 |
57 |
58 | 2.6.1
59 |
60 |
61 | 28.0.0.3
62 |
63 |
64 | 28.0.0.3
65 |
66 |
67 | 28.0.0.3
68 |
69 |
70 | 28.0.0.3
71 |
72 |
73 | 28.0.0.3
74 |
75 |
76 | 28.0.0.3
77 |
78 |
79 | 28.0.0.3
80 |
81 |
82 | 71.1600.0
83 |
84 |
85 | 71.1620.0
86 |
87 |
88 | 2.0.18-beta
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 | Designer
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.Android/MainActivity.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | using Android.App;
4 | using Android.Content;
5 | using Android.Content.PM;
6 | using Android.Runtime;
7 | using Android.Views;
8 | using Android.Widget;
9 | using Android.OS;
10 | using Plugin.GoogleClient;
11 | using Java.Security;
12 |
13 | namespace GoogleClientSample.Droid
14 | {
15 | [Activity(Label = "Google Client Sample", Icon = "@drawable/ic_launcher_crossgeeks", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
16 | public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
17 | {
18 | protected override void OnCreate(Bundle bundle)
19 | {
20 | TabLayoutResource = Resource.Layout.Tabbar;
21 | ToolbarResource = Resource.Layout.Toolbar;
22 |
23 | base.OnCreate(bundle);
24 | GoogleClientManager.Initialize(this, null, "505504259657-mm99o1b838kmbrnkabshqpf5fd00sbsf.apps.googleusercontent.com");
25 | global::Xamarin.Forms.Forms.Init(this, bundle);
26 | LoadApplication(new App());
27 | }
28 |
29 | protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
30 | {
31 | base.OnActivityResult(requestCode, resultCode, data);
32 | GoogleClientManager.OnAuthCompleted(requestCode, resultCode, data);
33 | }
34 | }
35 | }
36 |
37 |
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.Android/Properties/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.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("GoogleClientSample.Android")]
10 | [assembly: AssemblyDescription("")]
11 | [assembly: AssemblyConfiguration("")]
12 | [assembly: AssemblyCompany("")]
13 | [assembly: AssemblyProduct("GoogleClientSample.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/GoogleClientSample/GoogleClientSample.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/GoogleClientSample/GoogleClientSample.Android/Resources/drawable-hdpi/ic_launcher_crossgeeks.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/samples/GoogleClientSample/GoogleClientSample.Android/Resources/drawable-hdpi/ic_launcher_crossgeeks.png
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.Android/Resources/drawable-hdpi/ic_launcher_crossgeeks_drop_shadow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/samples/GoogleClientSample/GoogleClientSample.Android/Resources/drawable-hdpi/ic_launcher_crossgeeks_drop_shadow.png
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.Android/Resources/drawable-hdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/samples/GoogleClientSample/GoogleClientSample.Android/Resources/drawable-hdpi/icon.png
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.Android/Resources/drawable-xhdpi/ic_launcher_crossgeeks.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/samples/GoogleClientSample/GoogleClientSample.Android/Resources/drawable-xhdpi/ic_launcher_crossgeeks.png
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.Android/Resources/drawable-xhdpi/ic_launcher_crossgeeks_drop_shadow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/samples/GoogleClientSample/GoogleClientSample.Android/Resources/drawable-xhdpi/ic_launcher_crossgeeks_drop_shadow.png
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.Android/Resources/drawable-xhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/samples/GoogleClientSample/GoogleClientSample.Android/Resources/drawable-xhdpi/icon.png
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.Android/Resources/drawable-xxhdpi/ic_launcher_crossgeeks.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/samples/GoogleClientSample/GoogleClientSample.Android/Resources/drawable-xxhdpi/ic_launcher_crossgeeks.png
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.Android/Resources/drawable-xxhdpi/ic_launcher_crossgeeks_drop_shadow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/samples/GoogleClientSample/GoogleClientSample.Android/Resources/drawable-xxhdpi/ic_launcher_crossgeeks_drop_shadow.png
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.Android/Resources/drawable-xxhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/samples/GoogleClientSample/GoogleClientSample.Android/Resources/drawable-xxhdpi/icon.png
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.Android/Resources/drawable/googlelogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/samples/GoogleClientSample/GoogleClientSample.Android/Resources/drawable/googlelogo.png
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.Android/Resources/drawable/ic_launcher_crossgeeks.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/samples/GoogleClientSample/GoogleClientSample.Android/Resources/drawable/ic_launcher_crossgeeks.png
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.Android/Resources/drawable/ic_launcher_crossgeeks_drop_shadow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/samples/GoogleClientSample/GoogleClientSample.Android/Resources/drawable/ic_launcher_crossgeeks_drop_shadow.png
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.Android/Resources/drawable/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/samples/GoogleClientSample/GoogleClientSample.Android/Resources/drawable/icon.png
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.Android/Resources/google-services.json:
--------------------------------------------------------------------------------
1 | {
2 | "project_info": {
3 | "project_number": "505504259657",
4 | "firebase_url": "https://clientsample-52b27.firebaseio.com",
5 | "project_id": "clientsample-52b27",
6 | "storage_bucket": "clientsample-52b27.appspot.com"
7 | },
8 | "client": [
9 | {
10 | "client_info": {
11 | "mobilesdk_app_id": "1:505504259657:android:dd621fd341b2ba28",
12 | "android_client_info": {
13 | "package_name": "com.crossgeeks.googleclientsample"
14 | }
15 | },
16 | "oauth_client": [
17 | {
18 | "client_id": "505504259657-8s3rgbidlpgavegu9ma6vuqnct4k2a7u.apps.googleusercontent.com",
19 | "client_type": 1,
20 | "android_info": {
21 | "package_name": "com.crossgeeks.googleclientsample",
22 | "certificate_hash": "b9daef0ad70a49a265023f51bfbced726e82a286"
23 | }
24 | },
25 | {
26 | "client_id": "505504259657-mm99o1b838kmbrnkabshqpf5fd00sbsf.apps.googleusercontent.com",
27 | "client_type": 3
28 | }
29 | ],
30 | "api_key": [
31 | {
32 | "current_key": "AIzaSyD34SCPikRhx289aXorO5ei6PBRB7USVUA"
33 | }
34 | ],
35 | "services": {
36 | "analytics_service": {
37 | "status": 1
38 | },
39 | "appinvite_service": {
40 | "status": 2,
41 | "other_platform_oauth_client": [
42 | {
43 | "client_id": "505504259657-mm99o1b838kmbrnkabshqpf5fd00sbsf.apps.googleusercontent.com",
44 | "client_type": 3
45 | }
46 | ]
47 | },
48 | "ads_service": {
49 | "status": 2
50 | }
51 | }
52 | }
53 | ],
54 | "configuration_version": "1"
55 | }
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.Android/Resources/layout/Main.axml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.Android/Resources/layout/Tabbar.axml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.Android/Resources/layout/Toolbar.axml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.Android/Resources/mipmap-hdpi/Icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/samples/GoogleClientSample/GoogleClientSample.Android/Resources/mipmap-hdpi/Icon.png
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.Android/Resources/mipmap-mdpi/Icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/samples/GoogleClientSample/GoogleClientSample.Android/Resources/mipmap-mdpi/Icon.png
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.Android/Resources/mipmap-xhdpi/Icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/samples/GoogleClientSample/GoogleClientSample.Android/Resources/mipmap-xhdpi/Icon.png
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.Android/Resources/mipmap-xxhdpi/Icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/samples/GoogleClientSample/GoogleClientSample.Android/Resources/mipmap-xxhdpi/Icon.png
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.Android/Resources/mipmap-xxxhdpi/Icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/samples/GoogleClientSample/GoogleClientSample.Android/Resources/mipmap-xxxhdpi/Icon.png
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.Android/Resources/values/Strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Hello World, Click Me!
4 | GoogleClientSample.Droid
5 |
6 |
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.Android/Resources/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
26 |
27 |
30 |
31 |
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.Android/google-services.json:
--------------------------------------------------------------------------------
1 | {
2 | "project_info": {
3 | "project_number": "505504259657",
4 | "firebase_url": "https://clientsample-52b27.firebaseio.com",
5 | "project_id": "clientsample-52b27",
6 | "storage_bucket": "clientsample-52b27.appspot.com"
7 | },
8 | "client": [
9 | {
10 | "client_info": {
11 | "mobilesdk_app_id": "1:505504259657:android:dd621fd341b2ba28",
12 | "android_client_info": {
13 | "package_name": "com.crossgeeks.googleclientsample"
14 | }
15 | },
16 | "oauth_client": [
17 | {
18 | "client_id": "505504259657-8s3rgbidlpgavegu9ma6vuqnct4k2a7u.apps.googleusercontent.com",
19 | "client_type": 1,
20 | "android_info": {
21 | "package_name": "com.crossgeeks.googleclientsample",
22 | "certificate_hash": "b9daef0ad70a49a265023f51bfbced726e82a286"
23 | }
24 | },
25 | {
26 | "client_id": "505504259657-tsdi9ej6db1nj6jm4tj33sgjniufepi5.apps.googleusercontent.com",
27 | "client_type": 1,
28 | "android_info": {
29 | "package_name": "com.crossgeeks.googleclientsample",
30 | "certificate_hash": "5c451933d2822b8f046241faa68a66e1991c0623"
31 | }
32 | },
33 | {
34 | "client_id": "505504259657-mm99o1b838kmbrnkabshqpf5fd00sbsf.apps.googleusercontent.com",
35 | "client_type": 3
36 | }
37 | ],
38 | "api_key": [
39 | {
40 | "current_key": "AIzaSyD34SCPikRhx289aXorO5ei6PBRB7USVUA"
41 | }
42 | ],
43 | "services": {
44 | "analytics_service": {
45 | "status": 1
46 | },
47 | "appinvite_service": {
48 | "status": 2,
49 | "other_platform_oauth_client": [
50 | {
51 | "client_id": "505504259657-mm99o1b838kmbrnkabshqpf5fd00sbsf.apps.googleusercontent.com",
52 | "client_type": 3
53 | },
54 | {
55 | "client_id": "505504259657-7lj235iheopgtflq21rgim3qleikt0oi.apps.googleusercontent.com",
56 | "client_type": 2,
57 | "ios_info": {
58 | "bundle_id": "com.nopeia.googlesampleios"
59 | }
60 | }
61 | ]
62 | },
63 | "ads_service": {
64 | "status": 2
65 | }
66 | }
67 | },
68 | {
69 | "client_info": {
70 | "mobilesdk_app_id": "1:505504259657:android:9c7e463802d0713a",
71 | "android_client_info": {
72 | "package_name": "com.nopeia.googleloginauth"
73 | }
74 | },
75 | "oauth_client": [
76 | {
77 | "client_id": "505504259657-uphhbr17qbn3sgusmm1vusdgpc0njnsq.apps.googleusercontent.com",
78 | "client_type": 1,
79 | "android_info": {
80 | "package_name": "com.nopeia.googleloginauth",
81 | "certificate_hash": "b9daef0ad70a49a265023f51bfbced726e82a286"
82 | }
83 | },
84 | {
85 | "client_id": "505504259657-mm99o1b838kmbrnkabshqpf5fd00sbsf.apps.googleusercontent.com",
86 | "client_type": 3
87 | }
88 | ],
89 | "api_key": [
90 | {
91 | "current_key": "AIzaSyD34SCPikRhx289aXorO5ei6PBRB7USVUA"
92 | }
93 | ],
94 | "services": {
95 | "analytics_service": {
96 | "status": 1
97 | },
98 | "appinvite_service": {
99 | "status": 2,
100 | "other_platform_oauth_client": [
101 | {
102 | "client_id": "505504259657-mm99o1b838kmbrnkabshqpf5fd00sbsf.apps.googleusercontent.com",
103 | "client_type": 3
104 | },
105 | {
106 | "client_id": "505504259657-7lj235iheopgtflq21rgim3qleikt0oi.apps.googleusercontent.com",
107 | "client_type": 2,
108 | "ios_info": {
109 | "bundle_id": "com.nopeia.googlesampleios"
110 | }
111 | }
112 | ]
113 | },
114 | "ads_service": {
115 | "status": 2
116 | }
117 | }
118 | },
119 | {
120 | "client_info": {
121 | "mobilesdk_app_id": "1:505504259657:android:a4638c15b2dad68e",
122 | "android_client_info": {
123 | "package_name": "com.nopeia.googlesampleios"
124 | }
125 | },
126 | "oauth_client": [
127 | {
128 | "client_id": "505504259657-psd0akor412vq4pn6cq8knvdou7dplf2.apps.googleusercontent.com",
129 | "client_type": 1,
130 | "android_info": {
131 | "package_name": "com.nopeia.googlesampleios",
132 | "certificate_hash": "5c451933d2822b8f046241faa68a66e1991c0623"
133 | }
134 | },
135 | {
136 | "client_id": "505504259657-mm99o1b838kmbrnkabshqpf5fd00sbsf.apps.googleusercontent.com",
137 | "client_type": 3
138 | }
139 | ],
140 | "api_key": [
141 | {
142 | "current_key": "AIzaSyD34SCPikRhx289aXorO5ei6PBRB7USVUA"
143 | }
144 | ],
145 | "services": {
146 | "analytics_service": {
147 | "status": 1
148 | },
149 | "appinvite_service": {
150 | "status": 2,
151 | "other_platform_oauth_client": [
152 | {
153 | "client_id": "505504259657-mm99o1b838kmbrnkabshqpf5fd00sbsf.apps.googleusercontent.com",
154 | "client_type": 3
155 | },
156 | {
157 | "client_id": "505504259657-7lj235iheopgtflq21rgim3qleikt0oi.apps.googleusercontent.com",
158 | "client_type": 2,
159 | "ios_info": {
160 | "bundle_id": "com.nopeia.googlesampleios"
161 | }
162 | }
163 | ]
164 | },
165 | "ads_service": {
166 | "status": 2
167 | }
168 | }
169 | },
170 | {
171 | "client_info": {
172 | "mobilesdk_app_id": "1:505504259657:android:388cbbd0d60de47b",
173 | "android_client_info": {
174 | "package_name": "com.yepyep.mobile"
175 | }
176 | },
177 | "oauth_client": [
178 | {
179 | "client_id": "505504259657-jvtaibe857b3p05u2ir1la7jjkg926dt.apps.googleusercontent.com",
180 | "client_type": 1,
181 | "android_info": {
182 | "package_name": "com.yepyep.mobile",
183 | "certificate_hash": "b9daef0ad70a49a265023f51bfbced726e82a286"
184 | }
185 | },
186 | {
187 | "client_id": "505504259657-mm99o1b838kmbrnkabshqpf5fd00sbsf.apps.googleusercontent.com",
188 | "client_type": 3
189 | }
190 | ],
191 | "api_key": [
192 | {
193 | "current_key": "AIzaSyD34SCPikRhx289aXorO5ei6PBRB7USVUA"
194 | }
195 | ],
196 | "services": {
197 | "analytics_service": {
198 | "status": 1
199 | },
200 | "appinvite_service": {
201 | "status": 2,
202 | "other_platform_oauth_client": [
203 | {
204 | "client_id": "505504259657-mm99o1b838kmbrnkabshqpf5fd00sbsf.apps.googleusercontent.com",
205 | "client_type": 3
206 | },
207 | {
208 | "client_id": "505504259657-7lj235iheopgtflq21rgim3qleikt0oi.apps.googleusercontent.com",
209 | "client_type": 2,
210 | "ios_info": {
211 | "bundle_id": "com.nopeia.googlesampleios"
212 | }
213 | }
214 | ]
215 | },
216 | "ads_service": {
217 | "status": 2
218 | }
219 | }
220 | }
221 | ],
222 | "configuration_version": "1"
223 | }
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.iOS/AppDelegate.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 |
5 | using Foundation;
6 | using Plugin.GoogleClient;
7 | using UIKit;
8 |
9 | namespace GoogleClientSample.iOS
10 | {
11 | // The UIApplicationDelegate for the application. This class is responsible for launching the
12 | // User Interface of the application, as well as listening (and optionally responding) to
13 | // application events from iOS.
14 | [Register("AppDelegate")]
15 | public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
16 | {
17 | //
18 | // This method is invoked when the application has loaded and is ready to run. In this
19 | // method you should instantiate the window, load the UI into it and then make the window
20 | // visible.
21 | //
22 | // You have 17 seconds to return from this method, or iOS will terminate your application.
23 | //
24 | public override bool FinishedLaunching(UIApplication app, NSDictionary options)
25 | {
26 | global::Xamarin.Forms.Forms.Init();
27 |
28 | GoogleClientManager.Initialize();
29 | LoadApplication(new App());
30 | return base.FinishedLaunching(app, options);
31 | }
32 |
33 | public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options)
34 | {
35 | base.OpenUrl(app, url, options);
36 | return GoogleClientManager.OnOpenUrl(app, url, options);
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.iOS/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {"images":[{"idiom":"iphone","filename":"Icon-60@2x.png","size":"60x60","scale":"2x"},{"idiom":"ipad","filename":"Icon-76.png","size":"76x76","scale":"1x"},{"idiom":"ipad","filename":"Icon-76@2x.png","size":"76x76","scale":"2x"},{"idiom":"iphone","filename":"Icon-Small.png","size":"29x29","scale":"1x"},{"idiom":"ipad","filename":"Icon-Small.png","size":"29x29","scale":"1x"},{"idiom":"iphone","filename":"Icon-Small@2x.png","size":"29x29","scale":"2x"},{"idiom":"ipad","filename":"Icon-Small@2x.png","size":"29x29","scale":"2x"},{"idiom":"ipad","filename":"Icon-Small-40.png","size":"40x40","scale":"1x"},{"idiom":"iphone","filename":"Icon-Small-40@2x.png","size":"40x40","scale":"2x"},{"idiom":"ipad","filename":"Icon-Small-40@2x.png","size":"40x40","scale":"2x"}],"info":{"version":1,"author":"xcode"}}
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/samples/GoogleClientSample/GoogleClientSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon-76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/samples/GoogleClientSample/GoogleClientSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon-76.png
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/samples/GoogleClientSample/GoogleClientSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon-Small-40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/samples/GoogleClientSample/GoogleClientSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon-Small-40.png
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/samples/GoogleClientSample/GoogleClientSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@2x.png
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon-Small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/samples/GoogleClientSample/GoogleClientSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon-Small.png
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/samples/GoogleClientSample/GoogleClientSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.iOS/Assets.xcassets/leo.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x"
10 | },
11 | {
12 | "idiom" : "universal",
13 | "scale" : "3x"
14 | },
15 | {
16 | "idiom" : "iphone",
17 | "scale" : "1x"
18 | },
19 | {
20 | "idiom" : "iphone",
21 | "scale" : "2x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "scale" : "3x"
26 | },
27 | {
28 | "idiom" : "ipad",
29 | "scale" : "1x"
30 | },
31 | {
32 | "idiom" : "ipad",
33 | "scale" : "2x"
34 | },
35 | {
36 | "idiom" : "watch",
37 | "scale" : "2x"
38 | },
39 | {
40 | "idiom" : "tv",
41 | "scale" : "1x"
42 | },
43 | {
44 | "idiom" : "mac",
45 | "scale" : "1x"
46 | },
47 | {
48 | "idiom" : "mac",
49 | "scale" : "2x"
50 | }
51 | ],
52 | "info" : {
53 | "version" : 1,
54 | "author" : "xcode"
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.iOS/Entitlements.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | keychain-access-groups
6 |
7 | $(AppIdentifierPrefix)CNAL8C4H5U.com.crossgeeks.yepyep
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.iOS/FodyWeavers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.iOS/FodyWeavers.xsd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Used to control if the On_PropertyName_Changed feature is enabled.
12 |
13 |
14 |
15 |
16 | Used to change the name of the method that fires the notify event. This is a string that accepts multiple values in a comma separated form.
17 |
18 |
19 |
20 |
21 | Used to control if equality checks should be inserted. If false, equality checking will be disabled for the project.
22 |
23 |
24 |
25 |
26 | Used to control if equality checks should use the Equals method resolved from the base class.
27 |
28 |
29 |
30 |
31 | Used to control if equality checks should use the static Equals method resolved from the base class.
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.
40 |
41 |
42 |
43 |
44 | A comma-separated list of error codes that can be safely ignored in assembly verification.
45 |
46 |
47 |
48 |
49 | 'false' to turn off automatic generation of the XML Schema file.
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.iOS/GoogleClientSample.iOS.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | iPhoneSimulator
6 | 8.0.30703
7 | 2.0
8 | {7A5621F7-4621-4ABA-9F37-531B755149AE}
9 | {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
10 | Exe
11 | GoogleClientSample.iOS
12 | Resources
13 | GoogleClientSample.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 | iPhone Developer
30 | Entitlements.plist
31 | -v -v -v
32 |
33 |
34 | none
35 | true
36 | bin\iPhoneSimulator\Release
37 | prompt
38 | 4
39 | None
40 | x86_64
41 | false
42 | YEPYEP DEV
43 | iPhone Developer
44 | Entitlements.plist
45 |
46 |
47 | true
48 | full
49 | false
50 | bin\iPhone\Debug
51 | DEBUG
52 | prompt
53 | 4
54 | false
55 | ARM64
56 | iPhone Developer
57 | true
58 | Entitlements.plist
59 |
60 |
61 | none
62 | true
63 | bin\iPhone\Release
64 | prompt
65 | 4
66 | ARM64
67 | false
68 | iPhone Developer
69 | Entitlements.plist
70 |
71 |
72 | none
73 | True
74 | bin\iPhone\Ad-Hoc
75 | prompt
76 | 4
77 | False
78 | ARM64
79 | True
80 | Automatic:AdHoc
81 | iPhone Distribution
82 | Entitlements.plist
83 |
84 |
85 | none
86 | True
87 | bin\iPhone\AppStore
88 | prompt
89 | 4
90 | False
91 | ARM64
92 | Automatic:AppStore
93 | iPhone Distribution
94 | Entitlements.plist
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.6.1
129 |
130 |
131 | 6.1.0
132 |
133 |
134 | 0.4.11
135 |
136 |
137 | 5.0.1
138 |
139 |
140 | 2.0.18-beta
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.iOS/GoogleService-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | AD_UNIT_ID_FOR_BANNER_TEST
6 | ca-app-pub-3940256099942544/2934735716
7 | AD_UNIT_ID_FOR_INTERSTITIAL_TEST
8 | ca-app-pub-3940256099942544/4411468910
9 | CLIENT_ID
10 | 1058623930382-jo6489ffkd82seoget0bdbksbpmit4gv.apps.googleusercontent.com
11 | REVERSED_CLIENT_ID
12 | com.googleusercontent.apps.1058623930382-jo6489ffkd82seoget0bdbksbpmit4gv
13 | API_KEY
14 | AIzaSyCoa1wjdnaKEjDxRw3tSiEa8m2neCDujd8
15 | GCM_SENDER_ID
16 | 1058623930382
17 | PLIST_VERSION
18 | 1
19 | BUNDLE_ID
20 | com.crossgeeks.yepyep
21 | PROJECT_ID
22 | signinios-fe30c
23 | STORAGE_BUCKET
24 | signinios-fe30c.appspot.com
25 | IS_ADS_ENABLED
26 |
27 | IS_ANALYTICS_ENABLED
28 |
29 | IS_APPINVITE_ENABLED
30 |
31 | IS_GCM_ENABLED
32 |
33 | IS_SIGNIN_ENABLED
34 |
35 | GOOGLE_APP_ID
36 | 1:1058623930382:ios:10f7dca260690682
37 | DATABASE_URL
38 | https://signinios-fe30c.firebaseio.com
39 |
40 |
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.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 | 10.3
25 | CFBundleDisplayName
26 | Google Client Sample
27 | CFBundleIdentifier
28 | com.crossgeeks.googleclientsample
29 | CFBundleVersion
30 | 1.0
31 | UILaunchStoryboardName
32 | LaunchScreen
33 | CFBundleName
34 | GoogleClientSample
35 | CFBundleURLTypes
36 |
37 |
38 | CFBundleURLName
39 | Google Services
40 | CFBundleURLSchemes
41 |
42 | com.googleusercontent.apps.1058623930382-jo6489ffkd82seoget0bdbksbpmit4gv
43 |
44 | CFBundleURLTypes
45 | Editor
46 |
47 |
48 | CFBundleURLSchemes
49 |
50 | com.crossgeeks.yepyep
51 |
52 |
53 |
54 | XSAppIconAssets
55 | Assets.xcassets/AppIcon.appiconset
56 |
57 |
58 |
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.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 GoogleClientSample.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/GoogleClientSample/GoogleClientSample.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("GoogleClientSample.iOS")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("GoogleClientSample.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/GoogleClientSample/GoogleClientSample.iOS/Resources/Default-568h@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/samples/GoogleClientSample/GoogleClientSample.iOS/Resources/Default-568h@2x.png
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.iOS/Resources/Default-Portrait.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/samples/GoogleClientSample/GoogleClientSample.iOS/Resources/Default-Portrait.png
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.iOS/Resources/Default-Portrait@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/samples/GoogleClientSample/GoogleClientSample.iOS/Resources/Default-Portrait@2x.png
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.iOS/Resources/Default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/samples/GoogleClientSample/GoogleClientSample.iOS/Resources/Default.png
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.iOS/Resources/Default@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/samples/GoogleClientSample/GoogleClientSample.iOS/Resources/Default@2x.png
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.iOS/Resources/Icon-60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/samples/GoogleClientSample/GoogleClientSample.iOS/Resources/Icon-60@3x.png
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.iOS/Resources/Icon-Small-40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/samples/GoogleClientSample/GoogleClientSample.iOS/Resources/Icon-Small-40@3x.png
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.iOS/Resources/Icon-Small@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CrossGeeks/GoogleClientPlugin/6d5854fbbc832417b1a6d76c0450106ecff48c9f/samples/GoogleClientSample/GoogleClientSample.iOS/Resources/Icon-Small@3x.png
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample.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/GoogleClientSample/GoogleClientSample/App.xaml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using GoogleClientSample.Views;
2 | using Xamarin.Forms;
3 |
4 | namespace GoogleClientSample
5 | {
6 | public partial class App : Application
7 | {
8 | public App ()
9 | {
10 | InitializeComponent();
11 |
12 | MainPage = new NavigationPage(new LoginPage());
13 | }
14 |
15 | protected override void OnStart ()
16 | {
17 | // Handle when your app starts
18 | }
19 |
20 | protected override void OnSleep ()
21 | {
22 | // Handle when your app sleeps
23 | }
24 |
25 | protected override void OnResume ()
26 | {
27 | // Handle when your app resumes
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample/FodyWeavers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample/GoogleClientSample.projitems:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath)
5 | true
6 | {8105EAC0-7139-4222-8EA5-19AD7430CA07}
7 |
8 |
9 | GoogleClientSample
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | App.xaml
18 |
19 |
20 | MainPage.xaml
21 |
22 |
23 |
24 |
25 |
26 | LoginPage.xaml
27 | Code
28 |
29 |
30 |
31 |
32 | Designer
33 | MSBuild:Compile
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample/GoogleClientSample.shproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {8105EAC0-7139-4222-8EA5-19AD7430CA07}
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample/MainPage.xaml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample/MainPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Xamarin.Forms;
7 |
8 | namespace GoogleClientSample
9 | {
10 | public partial class MainPage : ContentPage
11 | {
12 | public MainPage()
13 | {
14 | InitializeComponent();
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample/Models/UserProfile.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Text;
5 | using Plugin.GoogleClient.Shared;
6 |
7 | // If you wish to create your custom UserProfile just replace the Google Client Google User with your own UserProfile Model
8 | namespace GoogleClientSample.Models
9 | {
10 | public class UserProfile : INotifyPropertyChanged
11 | {
12 | public string Name { get; set; }
13 | public string Email { get; set; }
14 | public Uri Picture { get; set; }
15 | public event PropertyChangedEventHandler PropertyChanged;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample/ViewModels/LoginPageViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | using System.ComponentModel;
4 | using System.Diagnostics;
5 | using System.Windows.Input;
6 | using GoogleClientSample.Models;
7 | using Plugin.GoogleClient;
8 | using Plugin.GoogleClient.Shared;
9 | using Xamarin.Forms;
10 |
11 | namespace GoogleClientSample.ViewModels
12 | {
13 | public class LoginPageViewModel : INotifyPropertyChanged
14 | {
15 | public UserProfile User { get; set; } = new UserProfile();
16 | public string Name
17 | {
18 | get => User.Name;
19 | set => User.Name = value;
20 | }
21 |
22 | public string Email
23 | {
24 | get => User.Email;
25 | set => User.Email = value;
26 | }
27 |
28 | public Uri Picture
29 | {
30 | get => User.Picture;
31 | set => User.Picture = value;
32 | }
33 |
34 | public bool IsLoggedIn { get; set; }
35 |
36 | public string Token { get; set; }
37 |
38 | public ICommand LoginCommand { get; set; }
39 | public ICommand LogoutCommand { get; set; }
40 | private readonly IGoogleClientManager _googleClientManager;
41 | public event PropertyChangedEventHandler PropertyChanged;
42 |
43 | public LoginPageViewModel()
44 | {
45 | LoginCommand = new Command(LoginAsync);
46 | LogoutCommand = new Command(Logout);
47 |
48 | _googleClientManager = CrossGoogleClient.Current;
49 |
50 |
51 | IsLoggedIn = false;
52 | }
53 |
54 | public async void LoginAsync()
55 | {
56 | _googleClientManager.OnLogin += OnLoginCompleted;
57 | try
58 | {
59 | await _googleClientManager.LoginAsync();
60 | }
61 | catch (GoogleClientSignInNetworkErrorException e)
62 | {
63 | await App.Current.MainPage.DisplayAlert("Error", e.Message, "OK");
64 | }
65 | catch (GoogleClientSignInCanceledErrorException e)
66 | {
67 | await App.Current.MainPage.DisplayAlert("Error", e.Message, "OK");
68 | }
69 | catch (GoogleClientSignInInvalidAccountErrorException e)
70 | {
71 | await App.Current.MainPage.DisplayAlert("Error", e.Message, "OK");
72 | }
73 | catch (GoogleClientSignInInternalErrorException e)
74 | {
75 | await App.Current.MainPage.DisplayAlert("Error", e.Message, "OK");
76 | }
77 | catch (GoogleClientNotInitializedErrorException e)
78 | {
79 | await App.Current.MainPage.DisplayAlert("Error", e.Message, "OK");
80 | }
81 | catch (GoogleClientBaseException e)
82 | {
83 | await App.Current.MainPage.DisplayAlert("Error", e.Message, "OK");
84 | }
85 |
86 | }
87 |
88 |
89 | private void OnLoginCompleted(object sender, GoogleClientResultEventArgs loginEventArgs)
90 | {
91 | if (loginEventArgs.Data != null)
92 | {
93 | GoogleUser googleUser = loginEventArgs.Data;
94 | User.Name = googleUser.Name;
95 | User.Email = googleUser.Email;
96 | User.Picture = googleUser.Picture;
97 | var GivenName = googleUser.GivenName;
98 | var FamilyName = googleUser.FamilyName;
99 |
100 |
101 | // Log the current User email
102 | Debug.WriteLine(User.Email);
103 | IsLoggedIn = true;
104 |
105 | var token = CrossGoogleClient.Current.ActiveToken;
106 | Token = token;
107 | }
108 | else
109 | {
110 | App.Current.MainPage.DisplayAlert("Error", loginEventArgs.Message, "OK");
111 | }
112 |
113 | _googleClientManager.OnLogin -= OnLoginCompleted;
114 |
115 | }
116 |
117 | public void Logout()
118 | {
119 | _googleClientManager.OnLogout += OnLogoutCompleted;
120 | _googleClientManager.Logout();
121 | }
122 |
123 | private void OnLogoutCompleted(object sender, EventArgs loginEventArgs)
124 | {
125 | IsLoggedIn = false;
126 | User.Email = "Offline";
127 | _googleClientManager.OnLogout -= OnLogoutCompleted;
128 | }
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample/Views/Converter/InvertBooleanConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Globalization;
3 | using Xamarin.Forms;
4 |
5 | namespace GoogleClientSample.Views.Converter
6 | {
7 | public class InvertBooleanConverter : IValueConverter
8 | {
9 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
10 | {
11 | return !(bool) value;
12 | }
13 |
14 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
15 | {
16 | return !(bool) value;
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample/Views/LoginPage.xaml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
24 |
25 |
26 |
31 |
32 |
36 |
41 |
45 |
48 |
50 |
53 |
55 |
58 |
60 |
61 |
62 |
63 |
64 |
69 |
70 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/samples/GoogleClientSample/GoogleClientSample/Views/LoginPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using GoogleClientSample.ViewModels;
7 | using Xamarin.Forms;
8 | using Xamarin.Forms.Xaml;
9 |
10 | namespace GoogleClientSample.Views
11 | {
12 | [XamlCompilation(XamlCompilationOptions.Compile)]
13 | public partial class LoginPage : ContentPage
14 | {
15 | public LoginPage ()
16 | {
17 | InitializeComponent ();
18 | BindingContext = new LoginPageViewModel();
19 |
20 | this.Title = "Home";
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/samples/README.md:
--------------------------------------------------------------------------------
1 | # Google Client Sample App
2 |
3 | Sample project to demostrate how to use the Google Client plugin, if you wish to compile the project you must:
4 | * Clone the Repo
5 | * Open the GoogleClientSample Project in your Visual Studio IDE.
6 | * Create your [Google Firebase Console Platform](../docs/GoogleFirebaseConsoleSetup.md) application.
7 | * Deploy the App to your device the end result should look like this:
8 |
9 |
10 |
11 |
12 |
13 | * Check out [Getting Started](../docs/GettingStarted.md)
14 |
15 | **Platform Support**
16 |
17 | |Platform|Version|
18 | | ------------------- | :------------------: |
19 | |Xamarin.iOS|iOS 8+|
20 | |Xamarin.Android|API 15+|
21 |
22 | ### API Usage
23 |
24 | Call **CrossGoogleClient.Current** from any project or PCL to gain access to API.
25 |
26 | ## Features
27 |
28 | - Authentication
29 |
30 | ## Documentation
31 |
32 | Here you will find detailed documentation on setting up and using the Google Client Plugin for Xamarin
33 |
34 | * [Google Firebase Console Setup](../docs/GoogleFirebaseConsoleSetup.md)
35 | * [Android Setup](../docs/AndroidSetup.md)
36 | * [iOS Setup](../docs/iOSSetup.md)
37 |
38 | ### References
39 | * [Documentation References](../docs//References.md)
40 |
41 | ### Contributors
42 |
43 | * [Luis Pujols](https://github.com/pujolsluis)
44 | * [Rendy Del Rosario](https://github.com/rdelrosario)
--------------------------------------------------------------------------------
/src/GoogleClient.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.27428.2002
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GoogleClient", "Plugin.GoogleClient\Plugin.GoogleClient.csproj", "{7B1E2E0A-ECD2-43F4-B64C-3949679C4430}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {7B1E2E0A-ECD2-43F4-B64C-3949679C4430}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {7B1E2E0A-ECD2-43F4-B64C-3949679C4430}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {7B1E2E0A-ECD2-43F4-B64C-3949679C4430}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {7B1E2E0A-ECD2-43F4-B64C-3949679C4430}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {4F2A671A-4A49-45CE-A65E-8B4444D7764F}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/src/Plugin.GoogleClient/CrossGoogleClient.shared.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Plugin.GoogleClient
4 | {
5 | ///
6 | /// Cross GoogleClient
7 | ///
8 | public static class CrossGoogleClient
9 | {
10 | static Lazy implementation = new Lazy(() => CreateGoogleClient(), System.Threading.LazyThreadSafetyMode.PublicationOnly);
11 |
12 | ///
13 | /// Gets if the plugin is supported on the current platform.
14 | ///
15 | public static bool IsSupported => implementation.Value == null ? false : true;
16 |
17 |
18 |
19 | ///
20 | /// Current plugin implementation to use
21 | ///
22 | public static IGoogleClientManager Current
23 | {
24 | get
25 | {
26 | IGoogleClientManager ret = implementation.Value;
27 | if (ret == null)
28 | {
29 | throw NotImplementedInReferenceAssembly();
30 | }
31 |
32 |
33 | return ret;
34 | }
35 | }
36 |
37 | static IGoogleClientManager CreateGoogleClient()
38 | {
39 | #if NETSTANDARD2_0
40 | return null;
41 | #else
42 | return new GoogleClientManager();
43 | #endif
44 | }
45 |
46 | internal static Exception NotImplementedInReferenceAssembly() =>
47 | 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.");
48 |
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/Plugin.GoogleClient/GoogleClientException.shared.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | namespace Plugin.GoogleClient.Shared
3 | {
4 | public class GoogleClientBaseException : Exception
5 | {
6 | public const string SignInDefaultErrorMessage = "The Google Sign In could not complete it's process correctly. Make sure you have added google-services.json file to your project and the SHA certificate fingerprint to your Firebase Android App in the Firebase Console Portal";
7 | public const string SignInUnknownErrorMessage = "An unknown error has occured.";
8 | public const string SignInKeychainErrorMessage = "There was a problem reading or writing to the application keychain.";
9 | public const string SignInNoSignInHandlersInstalledErrorMessage = "No appropriate applications are installed on the user's device which can handle sign-in.";
10 | public const string SignInHasNoAuthInKeychainErrorMessage = "There are no auth tokens in the keychain.";
11 | public const string SignInCanceledErrorMessage = "The Sign In request was cancelled by the user";
12 | public const string SignInApiNotConnectedErrorMessage = "API failed to connect.";
13 | public const string SignInInvalidAccountErrorMessage = "Attempted to connect to the service with an invalid account name specified.";
14 | public const string SignInNetworkErrorMessage = "A network error occurred. Retrying should resolve the problem.";
15 | public const string SignInInternalErrorMessage = "An internal error occurred. Retrying should resolve the problem.";
16 | public const string SignInRequiredErrorMessage = "The client attempted to connect to the service but the user is not signed in.";
17 | public const string SignInFailedErrorMessage = "The sign in attempt didn't succeed with the current account.";
18 | public const string ClientNotInitializedErrorMessage = "The Google Plugin is not initialized correctly.";
19 |
20 |
21 | public GoogleClientBaseException() : base(SignInDefaultErrorMessage) { }
22 | public GoogleClientBaseException(string message) : base(message) { }
23 | public GoogleClientBaseException(string message, System.Exception inner) : base(message, inner) { }
24 | }
25 |
26 | // Indicates an unknown error has occured.
27 | public class GoogleClientNotInitializedErrorException : GoogleClientBaseException
28 | {
29 | public GoogleClientNotInitializedErrorException() : base(SignInUnknownErrorMessage) { }
30 | public GoogleClientNotInitializedErrorException(string message) : base(message) { }
31 | public GoogleClientNotInitializedErrorException(string message, System.Exception inner) : base(message, inner) { }
32 | }
33 |
34 | // Indicates an unknown error has occured.
35 | public class GoogleClientSignInUnknownErrorException : GoogleClientBaseException
36 | {
37 | public GoogleClientSignInUnknownErrorException() : base(SignInUnknownErrorMessage) { }
38 | public GoogleClientSignInUnknownErrorException(string message) : base(message) { }
39 | public GoogleClientSignInUnknownErrorException(string message, System.Exception inner) : base(message, inner) { }
40 | }
41 |
42 | // Indicates a problem reading or writing to the application keychain.
43 | public class GoogleClientSignInKeychainErrorException : GoogleClientBaseException
44 | {
45 | public GoogleClientSignInKeychainErrorException() : base(SignInKeychainErrorMessage) { }
46 | public GoogleClientSignInKeychainErrorException(string message) : base(message) { }
47 | public GoogleClientSignInKeychainErrorException(string message, System.Exception inner) : base(message, inner) { }
48 | }
49 |
50 | // Indicates no appropriate applications are installed on the user's device which can handle
51 | // sign-in. This code will only ever be returned if using webview and switching to browser have
52 | // both been disabled.
53 | public class GoogleClientSignInNoSignInHandlersInstalledErrorException : GoogleClientBaseException
54 | {
55 | public GoogleClientSignInNoSignInHandlersInstalledErrorException() : base(SignInNoSignInHandlersInstalledErrorMessage) { }
56 | public GoogleClientSignInNoSignInHandlersInstalledErrorException(string message) : base(message) { }
57 | public GoogleClientSignInNoSignInHandlersInstalledErrorException(string message, System.Exception inner) : base(message, inner) { }
58 | }
59 |
60 | // Indicates there are no auth tokens in the keychain. This error code will be returned by
61 | // signInSilently if the user has never signed in before with the given scopes, or if they have
62 | // since signed out.
63 | public class GoogleClientSignInHasNoAuthInKeychainErrorException : GoogleClientBaseException
64 | {
65 | public GoogleClientSignInHasNoAuthInKeychainErrorException() : base(SignInHasNoAuthInKeychainErrorMessage) { }
66 | public GoogleClientSignInHasNoAuthInKeychainErrorException(string message) : base(message) { }
67 | public GoogleClientSignInHasNoAuthInKeychainErrorException(string message, System.Exception inner) : base(message, inner) { }
68 | }
69 |
70 | // Indicates the user canceled the sign in request.
71 | public class GoogleClientSignInCanceledErrorException : GoogleClientBaseException
72 | {
73 | public GoogleClientSignInCanceledErrorException() : base(SignInCanceledErrorMessage) { }
74 | public GoogleClientSignInCanceledErrorException(string message) : base(message) { }
75 | public GoogleClientSignInCanceledErrorException(string message, System.Exception inner) : base(message, inner) { }
76 | }
77 |
78 | // Indicates the client attempted to call a method from an API that failed to connect.
79 | public class GoogleClientSignInApiNotConnectedErrorException : GoogleClientBaseException
80 | {
81 | public GoogleClientSignInApiNotConnectedErrorException() : base(SignInApiNotConnectedErrorMessage) { }
82 | public GoogleClientSignInApiNotConnectedErrorException(string message) : base(message) { }
83 | public GoogleClientSignInApiNotConnectedErrorException(string message, System.Exception inner) : base(message, inner) { }
84 | }
85 |
86 | // Indicates The client attempted to connect to the service with an invalid account name specified.
87 | public class GoogleClientSignInInvalidAccountErrorException : GoogleClientBaseException
88 | {
89 | public GoogleClientSignInInvalidAccountErrorException() : base(SignInInvalidAccountErrorMessage) { }
90 | public GoogleClientSignInInvalidAccountErrorException(string message) : base(message) { }
91 | public GoogleClientSignInInvalidAccountErrorException(string message, System.Exception inner) : base(message, inner) { }
92 | }
93 |
94 | // Indicates a network error occurred. Retrying should resolve the problem.
95 | public class GoogleClientSignInNetworkErrorException : GoogleClientBaseException
96 | {
97 | public GoogleClientSignInNetworkErrorException() : base(SignInNetworkErrorMessage) { }
98 | public GoogleClientSignInNetworkErrorException(string message) : base(message) { }
99 | public GoogleClientSignInNetworkErrorException(string message, System.Exception inner) : base(message, inner) { }
100 | }
101 |
102 | // Indicates an internal error occurred.
103 | public class GoogleClientSignInInternalErrorException : GoogleClientBaseException
104 | {
105 | public GoogleClientSignInInternalErrorException() : base(SignInInternalErrorMessage) { }
106 | public GoogleClientSignInInternalErrorException(string message) : base(message) { }
107 | public GoogleClientSignInInternalErrorException(string message, System.Exception inner) : base(message, inner) { }
108 | }
109 |
110 | // Indicates the client attempted to connect to the service but the user is not signed in.
111 | public class GoogleClientSignInRequiredErrorErrorException : GoogleClientBaseException
112 | {
113 | public GoogleClientSignInRequiredErrorErrorException() : base(SignInRequiredErrorMessage) { }
114 | public GoogleClientSignInRequiredErrorErrorException(string message) : base(message) { }
115 | public GoogleClientSignInRequiredErrorErrorException(string message, System.Exception inner) : base(message, inner) { }
116 | }
117 |
118 | // Indicates the sign in attempt didn't succeed with the current account.
119 | public class GoogleClientSignInFailedErrorException : GoogleClientBaseException
120 | {
121 | public GoogleClientSignInFailedErrorException() : base(SignInFailedErrorMessage) { }
122 | public GoogleClientSignInFailedErrorException(string message) : base(message) { }
123 | public GoogleClientSignInFailedErrorException(string message, System.Exception inner) : base(message, inner) { }
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/src/Plugin.GoogleClient/GoogleClientManager.android.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 | using System.Linq;
4 | using Android.App;
5 | using Android.Content;
6 | using Android.Gms.Auth.Api.SignIn;
7 | using Android.Gms.Common;
8 | using Android.Gms.Common.Apis;
9 | using Plugin.GoogleClient.Shared;
10 | using Android.Gms.Tasks;
11 | using Java.Interop;
12 | using Android.Gms.Auth;
13 |
14 | namespace Plugin.GoogleClient
15 | {
16 | ///
17 | /// Implementation for GoogleClient
18 | ///
19 | public class GoogleClientManager : Java.Lang.Object, IGoogleClientManager, IOnCompleteListener
20 | {
21 | // Class Debug Tag
22 | static string Tag = typeof(GoogleClientManager).FullName;
23 | static int AuthActivityID = 9637;
24 | public static Activity CurrentActivity { get; set; }
25 | static TaskCompletionSource> _loginTcs;
26 | static string _serverClientId;
27 | static string _clientId;
28 | static string[] _initScopes = new string[0];
29 |
30 | GoogleSignInClient mGoogleSignInClient;
31 |
32 | public GoogleUser CurrentUser
33 | {
34 | get
35 | {
36 | GoogleSignInAccount userAccount = GoogleSignIn.GetLastSignedInAccount(CurrentActivity);
37 | return userAccount !=null ?new GoogleUser
38 | {
39 | Id = userAccount.Id,
40 | Name = userAccount.DisplayName,
41 | GivenName = userAccount.GivenName,
42 | FamilyName = userAccount.FamilyName,
43 | Email = userAccount.Email,
44 | Picture = new Uri((userAccount.PhotoUrl != null ? $"{userAccount.PhotoUrl}" : $"https://autisticdating.net/imgs/profile-placeholder.jpg"))
45 | }: null;
46 | }
47 | }
48 |
49 | static readonly string[] DefaultScopes = new []
50 | {
51 | Scopes.Profile
52 | };
53 |
54 |
55 | internal GoogleClientManager()
56 | {
57 | if (CurrentActivity == null)
58 | {
59 | throw new GoogleClientNotInitializedErrorException(GoogleClientBaseException.ClientNotInitializedErrorMessage);
60 | }
61 |
62 | var gopBuilder = new GoogleSignInOptions.Builder(GoogleSignInOptions.DefaultSignIn)
63 | .RequestEmail();
64 |
65 | if(!string.IsNullOrWhiteSpace(_serverClientId))
66 | {
67 | gopBuilder.RequestServerAuthCode(_serverClientId, false);
68 | }
69 |
70 | if(!string.IsNullOrWhiteSpace(_clientId))
71 | {
72 | gopBuilder.RequestIdToken(_clientId);
73 | }
74 |
75 | foreach (var s in _initScopes)
76 | {
77 | gopBuilder.RequestScopes(new Scope(s));
78 | }
79 |
80 | GoogleSignInOptions googleSignInOptions = gopBuilder.Build();
81 |
82 | // Build a GoogleSignInClient with the options specified by gso.
83 | mGoogleSignInClient = GoogleSignIn.GetClient(CurrentActivity, googleSignInOptions);
84 | }
85 |
86 | public static void Initialize(
87 | Activity activity,
88 | string serverClientId = null,
89 | string clientId = null,
90 | string[] scopes = null,
91 | int requestCode = 9637)
92 | {
93 | CurrentActivity = activity;
94 | _serverClientId = serverClientId;
95 | _clientId = clientId;
96 | _initScopes = DefaultScopes.Concat(scopes ?? new string[0]).ToArray();
97 | AuthActivityID = requestCode;
98 | }
99 |
100 | EventHandler> _onLogin;
101 | public event EventHandler> OnLogin
102 | {
103 | add => _onLogin += value;
104 | remove => _onLogin -= value;
105 | }
106 |
107 | public async Task> LoginAsync()
108 | {
109 | if (CurrentActivity == null || mGoogleSignInClient == null)
110 | {
111 | throw new GoogleClientNotInitializedErrorException(GoogleClientBaseException.ClientNotInitializedErrorMessage);
112 | }
113 |
114 | _loginTcs = new TaskCompletionSource>();
115 |
116 | GoogleSignInAccount account = GoogleSignIn.GetLastSignedInAccount(CurrentActivity);
117 |
118 |
119 | if (account!=null)
120 | {
121 | OnSignInSuccessful(account);
122 | }
123 | else
124 | {
125 | Intent intent = mGoogleSignInClient.SignInIntent;
126 | CurrentActivity?.StartActivityForResult(intent, AuthActivityID);
127 | }
128 |
129 | return await _loginTcs.Task;
130 | }
131 |
132 | public async Task> SilentLoginAsync()
133 | {
134 |
135 | if (CurrentActivity == null || mGoogleSignInClient == null)
136 | {
137 | throw new GoogleClientNotInitializedErrorException(GoogleClientBaseException.ClientNotInitializedErrorMessage);
138 | }
139 |
140 | _loginTcs = new TaskCompletionSource>();
141 |
142 | GoogleSignInAccount account = GoogleSignIn.GetLastSignedInAccount(CurrentActivity);
143 |
144 | if (account != null)
145 | {
146 | OnSignInSuccessful(account);
147 | }
148 | else
149 | {
150 | GoogleSignInAccount userAccount = await mGoogleSignInClient.SilentSignInAsync();
151 | OnSignInSuccessful(userAccount);
152 | }
153 |
154 | return await _loginTcs.Task;
155 | }
156 |
157 | EventHandler _onLogout;
158 | public event EventHandler OnLogout
159 | {
160 | add => _onLogout += value;
161 | remove => _onLogout -= value;
162 | }
163 |
164 | protected virtual void OnLogoutCompleted(EventArgs e) => _onLogout?.Invoke(this, e);
165 |
166 | public void Logout()
167 | {
168 | if (CurrentActivity == null || mGoogleSignInClient == null)
169 | {
170 | throw new GoogleClientNotInitializedErrorException(GoogleClientBaseException.ClientNotInitializedErrorMessage);
171 | }
172 |
173 | if (GoogleSignIn.GetLastSignedInAccount(CurrentActivity)!=null)
174 | {
175 | //Auth.GoogleSignInApi.SignOut(GoogleApiClient);
176 | _idToken = null;
177 | _accessToken = null;
178 | mGoogleSignInClient.SignOut();
179 | //GoogleApiClient.Disconnect();
180 |
181 | // Log the state of the client
182 | //Debug.WriteLine(Tag + ": The user has logged out succesfully? " + !GoogleApiClient.IsConnected);
183 |
184 | // Send the logout result to the receivers
185 | OnLogoutCompleted(EventArgs.Empty);
186 | }
187 | }
188 |
189 | public bool IsLoggedIn
190 | {
191 | get
192 | {
193 | if (CurrentActivity == null)
194 | {
195 | throw new GoogleClientNotInitializedErrorException(GoogleClientBaseException.ClientNotInitializedErrorMessage);
196 | }
197 | return GoogleSignIn.GetLastSignedInAccount(CurrentActivity) != null;
198 | }
199 | }
200 |
201 | public string IdToken { get { return _idToken; } }
202 | public string AccessToken { get { return _accessToken; } }
203 | static string _idToken { get; set; }
204 | static string _accessToken { get; set; }
205 |
206 | EventHandler _onError;
207 | public event EventHandler OnError
208 | {
209 | add => _onError += value;
210 | remove => _onError -= value;
211 | }
212 |
213 | protected virtual void OnGoogleClientError(GoogleClientErrorEventArgs e) => _onError?.Invoke(this, e);
214 |
215 | public static void OnAuthCompleted(int requestCode, Result resultCode, Intent data)
216 | {
217 | if (requestCode != AuthActivityID)
218 | {
219 | return;
220 | }
221 | GoogleSignIn.GetSignedInAccountFromIntent(data).AddOnCompleteListener(CrossGoogleClient.Current as IOnCompleteListener);
222 |
223 | }
224 |
225 | async void OnSignInSuccessful(GoogleSignInAccount userAccount)
226 | {
227 | GoogleUser googleUser = new GoogleUser
228 | {
229 | Id = userAccount.Id,
230 | Name = userAccount.DisplayName,
231 | GivenName = userAccount.GivenName,
232 | FamilyName = userAccount.FamilyName,
233 | Email = userAccount.Email,
234 | Picture = new Uri((userAccount.PhotoUrl != null ? $"{userAccount.PhotoUrl}" : $"https://autisticdating.net/imgs/profile-placeholder.jpg"))
235 | };
236 |
237 | _idToken = userAccount.IdToken;
238 | System.Console.WriteLine($"Id Token: {_idToken}");
239 |
240 |
241 | if (userAccount.GrantedScopes != null && userAccount.GrantedScopes.Count>0)
242 | {
243 | var scopes = $"oauth2:{string.Join(' ', userAccount.GrantedScopes.Select(s => s.ScopeUri).ToArray())}";
244 | System.Console.WriteLine($"Scopes: {scopes}");
245 | var tcs = new TaskCompletionSource();
246 | System.Threading.Tasks.Task.Run(() =>
247 | {
248 | try
249 | {
250 | tcs.TrySetResult(GoogleAuthUtil.GetToken(Application.Context, userAccount.Account, scopes));
251 | }
252 | catch (Exception ex)
253 | {
254 | tcs.TrySetResult(string.Empty);
255 | System.Console.WriteLine($"Ex: {ex}");
256 | }
257 | });
258 |
259 | _accessToken = await tcs.Task;
260 |
261 | System.Console.WriteLine($"Access Token: {_accessToken}");
262 | }
263 |
264 | var googleArgs =
265 | new GoogleClientResultEventArgs(googleUser, GoogleActionStatus.Completed);
266 |
267 | // Send the result to the receivers
268 | _onLogin?.Invoke(CrossGoogleClient.Current, googleArgs);
269 | _loginTcs.TrySetResult(new GoogleResponse(googleArgs));
270 | }
271 |
272 | void OnSignInFailed(ApiException apiException)
273 | {
274 | GoogleClientErrorEventArgs errorEventArgs = new GoogleClientErrorEventArgs();
275 | Exception exception = null;
276 |
277 | switch (apiException.StatusCode)
278 | {
279 | case GoogleSignInStatusCodes.InternalError:
280 | errorEventArgs.Error = GoogleClientErrorType.SignInInternalError;
281 | errorEventArgs.Message = GoogleClientBaseException.SignInInternalErrorMessage;
282 | exception = new GoogleClientSignInInternalErrorException();
283 | break;
284 | case GoogleSignInStatusCodes.ApiNotConnected:
285 | errorEventArgs.Error = GoogleClientErrorType.SignInApiNotConnectedError;
286 | errorEventArgs.Message = GoogleClientBaseException.SignInApiNotConnectedErrorMessage;
287 | exception = new GoogleClientSignInApiNotConnectedErrorException();
288 | break;
289 | case GoogleSignInStatusCodes.NetworkError:
290 | errorEventArgs.Error = GoogleClientErrorType.SignInNetworkError;
291 | errorEventArgs.Message = GoogleClientBaseException.SignInNetworkErrorMessage;
292 | exception = new GoogleClientSignInNetworkErrorException();
293 | break;
294 | case GoogleSignInStatusCodes.InvalidAccount:
295 | errorEventArgs.Error = GoogleClientErrorType.SignInInvalidAccountError;
296 | errorEventArgs.Message = GoogleClientBaseException.SignInInvalidAccountErrorMessage;
297 | exception = new GoogleClientSignInInvalidAccountErrorException();
298 | break;
299 | case GoogleSignInStatusCodes.SignInRequired:
300 | errorEventArgs.Error = GoogleClientErrorType.SignInRequiredError;
301 | errorEventArgs.Message = GoogleClientBaseException.SignInRequiredErrorMessage;
302 | exception = new GoogleClientSignInRequiredErrorErrorException();
303 | break;
304 | case GoogleSignInStatusCodes.SignInFailed:
305 | errorEventArgs.Error = GoogleClientErrorType.SignInFailedError;
306 | errorEventArgs.Message = GoogleClientBaseException.SignInFailedErrorMessage;
307 | exception = new GoogleClientSignInFailedErrorException();
308 | break;
309 | case GoogleSignInStatusCodes.SignInCancelled:
310 | errorEventArgs.Error = GoogleClientErrorType.SignInCanceledError;
311 | errorEventArgs.Message = GoogleClientBaseException.SignInCanceledErrorMessage;
312 | exception = new GoogleClientSignInCanceledErrorException();
313 | break;
314 | default:
315 | errorEventArgs.Error = GoogleClientErrorType.SignInDefaultError;
316 | errorEventArgs.Message = apiException.Message;
317 | exception = new GoogleClientBaseException(
318 | string.IsNullOrEmpty(apiException.Message)
319 | ? GoogleClientBaseException.SignInDefaultErrorMessage
320 | : apiException.Message
321 | );
322 | break;
323 | }
324 |
325 | _onError?.Invoke(CrossGoogleClient.Current, errorEventArgs);
326 | _loginTcs.TrySetException(exception);
327 | }
328 |
329 |
330 | public void OnComplete(Android.Gms.Tasks.Task task)
331 | {
332 | if(!task.IsSuccessful)
333 | {
334 | //Failed
335 | OnSignInFailed(task.Exception.JavaCast());
336 | }
337 | else
338 | {
339 | var userAccount = task.Result.JavaCast();
340 |
341 | OnSignInSuccessful(userAccount);
342 |
343 | }
344 |
345 |
346 | }
347 | }
348 | }
349 |
--------------------------------------------------------------------------------
/src/Plugin.GoogleClient/GoogleClientManager.apple.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.Threading.Tasks;
4 | using System.Linq;
5 | using Foundation;
6 | using Google.SignIn;
7 | using Plugin.GoogleClient.Shared;
8 | using UIKit;
9 | using GoogleUser = Plugin.GoogleClient.Shared.GoogleUser;
10 |
11 | namespace Plugin.GoogleClient
12 | {
13 | ///
14 | /// Implementation for GoogleClient
15 | ///
16 | ///
17 | public class GoogleClientManager : NSObject, IGoogleClientManager, ISignInDelegate
18 | {
19 | // Class Debug Tag
20 | private String Tag = typeof(GoogleClientManager).FullName;
21 |
22 | public string IdToken { get { return _idToken; } }
23 | public string AccessToken { get { return _accessToken; } }
24 | static string _idToken { get; set; }
25 | static string _accessToken { get; set; }
26 | static string _clientId { get; set; }
27 |
28 | public GoogleUser CurrentUser
29 | {
30 | get
31 | {
32 | if (SignIn.SharedInstance.HasPreviousSignIn)
33 | SignIn.SharedInstance.RestorePreviousSignIn();
34 |
35 | var user = SignIn.SharedInstance.CurrentUser;
36 | return user!=null? new GoogleUser
37 | {
38 | Id = user.UserId,
39 | Name = user.Profile.Name,
40 | GivenName = user.Profile.GivenName,
41 | FamilyName = user.Profile.FamilyName,
42 | Email = user.Profile.Email,
43 | Picture = user.Profile.HasImage
44 | ? new Uri(user.Profile.GetImageUrl(500).ToString())
45 | : new Uri(string.Empty)
46 | }: null;
47 | }
48 | }
49 |
50 | public bool IsLoggedIn
51 | {
52 | get
53 | {
54 | return SignIn.SharedInstance.HasPreviousSignIn;
55 | }
56 | }
57 |
58 | /*
59 | public DateTime TokenExpirationDate { get { return _tokenExpirationDate; } }
60 | DateTime _tokenExpirationDate { get; set; }
61 | */
62 | static TaskCompletionSource> _loginTcs;
63 |
64 | public static void Initialize(
65 | string clientId = null,
66 | params string[] scopes
67 | )
68 | {
69 | SignIn.SharedInstance.Delegate = CrossGoogleClient.Current as ISignInDelegate;
70 | if (scopes != null && scopes.Length > 0)
71 | {
72 |
73 | var currentScopes = SignIn.SharedInstance.Scopes;
74 | var initScopes = currentScopes
75 | .Concat(scopes)
76 | .Distinct()
77 | .ToArray();
78 |
79 |
80 | SignIn.SharedInstance.Scopes = initScopes;
81 | }
82 |
83 | SignIn.SharedInstance.ClientId = string.IsNullOrWhiteSpace(clientId)
84 | ? GetClientIdFromGoogleServiceDictionary()
85 | : clientId;
86 | //SignIn.SharedInstance.ShouldFetchBasicProfile = true;
87 | }
88 |
89 | static string GetClientIdFromGoogleServiceDictionary()
90 | {
91 | var googleServiceDictionary = NSDictionary.FromFile("GoogleService-Info.plist");
92 | _clientId = googleServiceDictionary["CLIENT_ID"].ToString();
93 | return googleServiceDictionary["CLIENT_ID"].ToString();
94 | }
95 |
96 | EventHandler> _onLogin;
97 | event EventHandler> IGoogleClientManager.OnLogin
98 | {
99 | add => _onLogin += value;
100 | remove => _onLogin -= value;
101 | }
102 |
103 | EventHandler _onLogout;
104 | public event EventHandler OnLogout
105 | {
106 | add => _onLogout += value;
107 | remove => _onLogout -= value;
108 | }
109 |
110 | public void Login()
111 | {
112 | UpdatePresentedViewController();
113 |
114 | SignIn.SharedInstance.SignInUser();
115 | }
116 |
117 | public async Task> LoginAsync()
118 | {
119 | if (SignIn.SharedInstance.ClientId == null)
120 | {
121 | throw new GoogleClientNotInitializedErrorException(GoogleClientBaseException.ClientNotInitializedErrorMessage);
122 | }
123 |
124 |
125 | _loginTcs = new TaskCompletionSource>();
126 |
127 | UpdatePresentedViewController();
128 | if (CurrentUser == null)
129 | {
130 |
131 | SignIn.SharedInstance.SignInUser();
132 | }
133 | else
134 | {
135 | SignIn.SharedInstance.CurrentUser.Authentication.GetTokens(async (Authentication authentication, NSError error) =>
136 | {
137 | if (error == null)
138 | {
139 | _accessToken = authentication.AccessToken;
140 | _idToken = authentication.IdToken;
141 | System.Console.WriteLine($"Id Token: {_idToken}");
142 | System.Console.WriteLine($"Access Token: {_accessToken}");
143 | }
144 |
145 | });
146 |
147 |
148 | /* DateTime newDate = TimeZone.CurrentTimeZone.ToLocalTime(
149 | new DateTime(2001, 1, 1, 0, 0, 0));
150 | _tokenExpirationDate = newDate.AddSeconds(user.Authentication.AccessTokenExpirationDate.SecondsSinceReferenceDate);
151 | */
152 | var googleArgs = new GoogleClientResultEventArgs(
153 | CurrentUser,
154 | GoogleActionStatus.Completed,
155 | "the user is authenticated correctly"
156 | );
157 |
158 | // Log the result of the authentication
159 | Debug.WriteLine(Tag + ": Authentication " + GoogleActionStatus.Completed);
160 |
161 | // Send the result to the receivers
162 | _onLogin?.Invoke(this, googleArgs);
163 | _loginTcs.TrySetResult(new GoogleResponse(googleArgs));
164 | }
165 |
166 | return await _loginTcs.Task;
167 | }
168 |
169 | public async Task> SilentLoginAsync()
170 | {
171 | if (SignIn.SharedInstance.ClientId == null)
172 | {
173 | throw new GoogleClientNotInitializedErrorException(GoogleClientBaseException.ClientNotInitializedErrorMessage);
174 | }
175 |
176 | //SignIn.SharedInstance.CurrentUser.Authentication.ClientId != _clientId
177 | _loginTcs = new TaskCompletionSource>();
178 |
179 | if (SignIn.SharedInstance.HasPreviousSignIn)
180 | SignIn.SharedInstance.RestorePreviousSignIn();
181 |
182 | var currentUser = SignIn.SharedInstance.CurrentUser;
183 | var isSuccessful = currentUser != null;
184 |
185 | if(isSuccessful)
186 | {
187 | OnSignInSuccessful(currentUser);
188 | }
189 | else
190 | {
191 | var errorEventArgs = new GoogleClientErrorEventArgs();
192 | errorEventArgs.Error = GoogleClientErrorType.SignInDefaultError;
193 | errorEventArgs.Message = GoogleClientBaseException.SignInDefaultErrorMessage;
194 | _onError?.Invoke(this, errorEventArgs);
195 | _loginTcs.TrySetException(new GoogleClientBaseException());
196 | }
197 |
198 | return await _loginTcs.Task;
199 | }
200 |
201 | public static bool OnOpenUrl(UIApplication app, NSUrl url, NSDictionary options)
202 | {
203 | var openUrlOptions = new UIApplicationOpenUrlOptions(options);
204 | return SignIn.SharedInstance.HandleUrl(url);
205 | }
206 |
207 | protected virtual void OnLoginCompleted(GoogleClientResultEventArgs e)
208 | {
209 | _onLogin?.Invoke(this, e);
210 | }
211 |
212 | public void Logout()
213 | {
214 | if (SignIn.SharedInstance.ClientId == null)
215 | {
216 | throw new GoogleClientNotInitializedErrorException(GoogleClientBaseException.ClientNotInitializedErrorMessage);
217 | }
218 |
219 | if (IsLoggedIn)
220 | {
221 | _idToken = null;
222 | _accessToken = null;
223 | SignIn.SharedInstance.SignOutUser();
224 | // Send the logout result to the receivers
225 | OnLogoutCompleted(EventArgs.Empty);
226 | }
227 |
228 | }
229 |
230 | protected virtual void OnLogoutCompleted(EventArgs e)
231 | {
232 | _onLogout?.Invoke(this, e);
233 | }
234 |
235 | EventHandler _onError;
236 | public event EventHandler OnError
237 | {
238 | add => _onError += value;
239 | remove => _onError -= value;
240 | }
241 |
242 |
243 | public void DidSignIn(SignIn signIn, Google.SignIn.GoogleUser user, NSError error)
244 | {
245 | var isSuccessful = user != null && error == null;
246 |
247 | if (isSuccessful)
248 | {
249 | OnSignInSuccessful(user);
250 | return;
251 | }
252 |
253 | GoogleClientErrorEventArgs errorEventArgs = new GoogleClientErrorEventArgs();
254 | Exception exception = null;
255 | switch (error.Code)
256 | {
257 | case -1:
258 | errorEventArgs.Error = GoogleClientErrorType.SignInUnknownError;
259 | errorEventArgs.Message = GoogleClientBaseException.SignInUnknownErrorMessage;
260 | exception=new GoogleClientSignInUnknownErrorException();
261 | break;
262 | case -2:
263 | errorEventArgs.Error = GoogleClientErrorType.SignInKeychainError;
264 | errorEventArgs.Message = GoogleClientBaseException.SignInKeychainErrorMessage;
265 | exception = new GoogleClientSignInKeychainErrorException();
266 | break;
267 | case -3:
268 | errorEventArgs.Error = GoogleClientErrorType.NoSignInHandlersInstalledError;
269 | errorEventArgs.Message = GoogleClientBaseException.SignInNoSignInHandlersInstalledErrorMessage;
270 | exception = new GoogleClientSignInNoSignInHandlersInstalledErrorException();
271 | break;
272 | case -4:
273 | errorEventArgs.Error = GoogleClientErrorType.SignInHasNoAuthInKeychainError;
274 | errorEventArgs.Message = GoogleClientBaseException.SignInUnknownErrorMessage;
275 | exception = new GoogleClientSignInHasNoAuthInKeychainErrorException();
276 | break;
277 | case -5:
278 | errorEventArgs.Error = GoogleClientErrorType.SignInCanceledError;
279 | errorEventArgs.Message = GoogleClientBaseException.SignInCanceledErrorMessage;
280 | exception = new GoogleClientSignInCanceledErrorException();
281 | break;
282 | default:
283 | errorEventArgs.Error = GoogleClientErrorType.SignInDefaultError;
284 | errorEventArgs.Message = GoogleClientBaseException.SignInDefaultErrorMessage;
285 | exception = new GoogleClientBaseException();
286 | break;
287 | }
288 |
289 | _onError?.Invoke(this,errorEventArgs);
290 | _loginTcs.TrySetException(exception);
291 | }
292 |
293 | [Export("signIn:didDisconnectWithUser:withError:")]
294 | public void DidDisconnect(SignIn signIn, Google.SignIn.GoogleUser user, NSError error)
295 | {
296 | // Perform any operations when the user disconnects from app here.
297 | }
298 |
299 |
300 | void UpdatePresentedViewController()
301 | {
302 | var window = UIApplication.SharedApplication.KeyWindow;
303 | var viewController = window.RootViewController;
304 | while (viewController.PresentedViewController != null)
305 | {
306 | viewController = viewController.PresentedViewController;
307 | }
308 |
309 | SignIn.SharedInstance.PresentingViewController = viewController;
310 | }
311 |
312 |
313 | void OnSignInSuccessful(Google.SignIn.GoogleUser user)
314 | {
315 | GoogleUser googleUser = new GoogleUser
316 | {
317 | Id = user.UserId,
318 | Name = user.Profile.Name,
319 | GivenName = user.Profile.GivenName,
320 | FamilyName = user.Profile.FamilyName,
321 | Email = user.Profile.Email,
322 | Picture = user.Profile.HasImage
323 | ? new Uri(user.Profile.GetImageUrl(500).ToString())
324 | : new Uri(string.Empty)
325 | };
326 |
327 | user.Authentication.GetTokens(async (Authentication authentication, NSError error) =>
328 | {
329 | if(error ==null)
330 | {
331 | _accessToken = authentication.AccessToken;
332 | _idToken = authentication.IdToken;
333 | System.Console.WriteLine($"Id Token: {_idToken}");
334 | System.Console.WriteLine($"Access Token: {_accessToken}");
335 | }
336 |
337 | });
338 |
339 |
340 | /* DateTime newDate = TimeZone.CurrentTimeZone.ToLocalTime(
341 | new DateTime(2001, 1, 1, 0, 0, 0));
342 | _tokenExpirationDate = newDate.AddSeconds(user.Authentication.AccessTokenExpirationDate.SecondsSinceReferenceDate);
343 | */
344 | var googleArgs = new GoogleClientResultEventArgs(
345 | googleUser,
346 | GoogleActionStatus.Completed,
347 | "the user is authenticated correctly"
348 | );
349 |
350 | // Log the result of the authentication
351 | Debug.WriteLine(Tag + ": Authentication " + GoogleActionStatus.Completed);
352 |
353 | // Send the result to the receivers
354 | _onLogin?.Invoke(this, googleArgs);
355 | _loginTcs.TrySetResult(new GoogleResponse(googleArgs));
356 |
357 | }
358 | }
359 | }
360 |
--------------------------------------------------------------------------------
/src/Plugin.GoogleClient/GoogleUser.shared.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace Plugin.GoogleClient.Shared
6 | {
7 | public class GoogleUser
8 | {
9 | public string Id { get; set; }
10 | public string Name { get; set; }
11 | public string GivenName { get; set; }
12 | public string FamilyName { get; set; }
13 | public string Email { get; set; }
14 | public Uri Picture { get; set; }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/Plugin.GoogleClient/IGoogleClientManager.shared.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using System.Threading.Tasks;
5 | using Plugin.GoogleClient.Shared;
6 |
7 | namespace Plugin.GoogleClient
8 | {
9 | public enum GoogleClientErrorType {
10 | SignInUnknownError,
11 | SignInKeychainError,
12 | NoSignInHandlersInstalledError,
13 | SignInHasNoAuthInKeychainError,
14 | SignInCanceledError,
15 | SignInDefaultError,
16 | SignInApiNotConnectedError,
17 | SignInInvalidAccountError,
18 | SignInNetworkError,
19 | SignInInternalError,
20 | SignInRequiredError,
21 | SignInFailedError
22 | }
23 | public class GoogleClientErrorEventArgs : EventArgs
24 | {
25 | public GoogleClientErrorType Error { get; set; }
26 | public string Message { get; set; }
27 | }
28 |
29 | public enum GoogleActionStatus
30 | {
31 | Canceled,
32 | Unauthorized,
33 | Completed,
34 | Error
35 | }
36 |
37 | public class GoogleClientResultEventArgs : EventArgs
38 | {
39 | public T Data { get; set; }
40 | public GoogleActionStatus Status { get; set; }
41 | public string Message { get; set; }
42 |
43 | public GoogleClientResultEventArgs(T data, GoogleActionStatus status, string msg = "")
44 | {
45 | Data = data;
46 | Status = status;
47 | Message = msg;
48 | }
49 | }
50 |
51 | public class GoogleResponse
52 | {
53 | public T Data { get; set; }
54 | public GoogleActionStatus Status { get; set; }
55 | public string Message { get; set; }
56 |
57 | public GoogleResponse(GoogleClientResultEventArgs evtArgs)
58 | {
59 | Data = evtArgs.Data;
60 | Status = evtArgs.Status;
61 | Message = evtArgs.Message;
62 | }
63 |
64 | public GoogleResponse(T user, GoogleActionStatus status, string msg = "")
65 | {
66 | Data = user;
67 | Status = status;
68 | Message = msg;
69 | }
70 | }
71 |
72 | ///
73 | /// Interface for GoogleClientManager
74 | ///
75 | public interface IGoogleClientManager
76 | {
77 | event EventHandler> OnLogin;
78 | event EventHandler OnLogout;
79 | event EventHandler OnError;
80 | Task> LoginAsync();
81 | Task> SilentLoginAsync();
82 | void Logout();
83 | string IdToken { get; }
84 | string AccessToken { get; }
85 | GoogleUser CurrentUser { get; }
86 | bool IsLoggedIn { get; }
87 | //DateTime TokenExpirationDate { get; }
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/src/Plugin.GoogleClient/Plugin.GoogleClient.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0;MonoAndroid90;MonoAndroid10.0;Xamarin.iOS10;
5 | Plugin.GoogleClient
6 | Plugin.GoogleClient
7 | Plugin.GoogleClient
8 | $(AssemblyName) ($(TargetFramework))
9 | 2.0.0.0
10 | 2.0.0.0
11 | 2.0.0.0
12 | true
13 | en
14 | default
15 | $(DefineConstants);
16 | false
17 | false
18 |
19 | latest
20 | https://github.com/CrossGeeks/GoogleClientPlugin/blob/master/LICENSE
21 | https://github.com/CrossGeeks/GoogleClientPlugin
22 | https://github.com/CrossGeeks/GoogleClientPlugin
23 | https://github.com/CrossGeeks/GoogleClientPlugin/blob/master/art/icon.png?raw=true
24 | xamarin, ios, android, xamarin.forms, plugin, google client, authentication, google
25 |
26 | Google Client Plugin for Xamarin
27 | Google authentication handling across Xamarin.iOS and Xamarin.Android
28 | Google authentication handling across Xamarin.iOS and Xamarin.Android
29 | BREAKING CHANGE: Expose IdToken and AccessToken instead of ActiveToken. ActiveToken property was removed
30 | Luis Pujols
31 | pujolsluis,crossgeeks
32 | Copyright 2018
33 | true
34 |
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.GoogleClient.xml
53 | CrossGeeks
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 |
81 |
82 |
--------------------------------------------------------------------------------