diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..713040f
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,135 @@
+root = true
+
+[*]
+indent_style = space
+trim_trailing_whitespace = true
+
+##### .NET Framework/.NET Core Projects #####
+
+[*.sln]
+charset = utf-8-bom
+indent_style = tab
+insert_final_newline = true
+
+[*.{csproj,dcproj,vbproj}]
+charset = utf-8-bom
+indent_size = 2
+insert_final_newline = true
+
+[*.{cs,csx,vb,vbx}]
+charset = utf-8-bom
+indent_size = 4
+insert_final_newline = true
+max_line_length = 120
+
+dotnet_style_qualification_for_field = false:suggestion
+dotnet_style_qualification_for_property = false:suggestion
+dotnet_style_qualification_for_method = false:suggestion
+dotnet_style_qualification_for_event = false:suggestion
+dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
+dotnet_style_predefined_type_for_member_access = true:suggestion
+dotnet_style_require_accessibility_modifiers = always:warning
+dotnet_style_readonly_field = true:warning
+dotnet_style_object_initializer = true:suggestion
+dotnet_style_collection_initializer = true:suggestion
+dotnet_style_explicit_tuple_names = true:suggestion
+dotnet_style_prefer_inferred_tuple_names = true:suggestion
+dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
+dotnet_style_prefer_auto_properties = true:suggestion
+dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
+dotnet_style_coalesce_expression = true:suggestion
+dotnet_style_null_propagation = true:suggestion
+
+csharp_style_var_for_built_in_types = true:suggestion
+csharp_style_var_when_type_is_apparent = true:suggestion
+csharp_style_var_elsewhere = true:suggestion
+csharp_style_expression_bodied_methods = true:suggestion
+csharp_style_expression_bodied_constructors = true:suggestion
+csharp_style_expression_bodied_operators = true:suggestion
+csharp_style_expression_bodied_properties = true:suggestion
+csharp_style_expression_bodied_indexers = true:suggestion
+csharp_style_expression_bodied_accessors = true:suggestion
+csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
+csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
+csharp_style_inlined_variable_declaration = true:suggestion
+csharp_style_deconstructed_variable_declaration = true:suggestion
+csharp_style_pattern_local_over_anonymous_function = true:suggestion
+csharp_style_throw_expression = true:suggestion
+csharp_style_conditional_delegate_call = true:suggestion
+
+csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion
+csharp_prefer_simple_default_expression = true:suggestion
+csharp_prefer_braces = true:suggestion
+
+visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:suggestion
+
+dotnet_sort_system_directives_first = true
+
+csharp_new_line_before_open_brace = all
+csharp_new_line_before_else = true
+csharp_new_line_before_catch = true
+csharp_new_line_before_finally = true
+csharp_new_line_before_members_in_object_initializers = true
+csharp_new_line_before_members_in_anonymous_types = true
+csharp_new_line_between_query_expression_clauses = true
+
+csharp_indent_case_contents = true
+csharp_indent_switch_labels = true
+csharp_indent_labels = flush_left
+
+csharp_space_after_cast = false
+csharp_space_after_keywords_in_control_flow_statements = true
+csharp_space_between_method_declaration_parameter_list_parentheses = false
+csharp_space_between_method_call_parameter_list_parentheses = false
+csharp_space_between_parentheses = false
+csharp_space_before_colon_in_inheritance_clause = true
+csharp_space_after_colon_in_inheritance_clause = true
+csharp_space_around_binary_operators = before_and_after
+csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
+csharp_space_between_method_call_name_and_opening_parenthesis = false
+csharp_space_between_method_call_empty_parameter_list_parentheses = false
+
+csharp_preserve_single_line_statements = false
+csharp_preserve_single_line_blocks = true
+
+##### Documents #####
+
+[*.{json,json5,xml}]
+charset = utf-8
+indent_size = 2
+
+[*.md]
+charset = utf-8
+insert_final_newline = true
+
+[*.{yml}]
+charset = utf-8
+indent_size = 2
+insert_final_newline = true
+
+##### Shell Scripts #####
+
+[*.{bat,cmd}]
+charset = utf-8
+end_of_line = crlf
+indent_size = 2
+insert_final_newline = true
+
+[*.ps1]
+charset = utf-8-bom
+indent_size = 2
+insert_final_newline = true
+
+[*.sh]
+charset = utf-8
+end_of_line = lf
+indent_size = 2
+insert_final_newline = true
+
+##### Web Projects #####
+
+[*.{css,html,js,jsx,less,sass,scss,svg,ts,tsx}]
+charset = utf-8
+indent_size = 2
+insert_final_newline = true
+max_line_length = 120
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..26f8bc7
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,120 @@
+* text=auto
+*.7z binary
+*.ai binary
+*.bat text eol=crlf
+*.bmp binary
+*.class binary
+*.cmd text eol=crlf
+*.coffee text
+*.cs text diff=csharp
+*.csproj text
+*.css text diff=css
+*.csv text
+*.dll binary
+*.doc diff=astextplain
+*.dockerignore text
+*.docx diff=astextplain
+*.dot diff=astextplain
+*.env text
+*.eot binary
+*.eps binary
+*.exe binary
+*.gif binary
+*.gz binary
+*.htm text diff=html
+*.html text diff=html
+*.ico binary
+*.ini text
+*.jar binary
+*.java text diff=java
+*.jpg binary
+*.jpeg binary
+*.js text
+*.json text
+*.jsp text
+*.jsx text
+*.less text
+*.m4a binary
+*.m4v binary
+*.md text
+*.meta text
+*.mid binary
+*.midi binary
+*.mov binary
+*.mp3 binary
+*.mp4 binary
+*.mpeg binary
+*.mpg binary
+*.ogg binary
+*.otf binary
+*.pbxproj binary -merge=union
+*.pdf binary
+*.php text diff=php
+*.pl text diff=perl
+*.pm text diff=perl
+*.png binary
+*.psd binary
+*.ps1 text
+*.pxd text
+*.py text diff=python
+*.py3 text diff=python
+*.pyc binary
+*.pyd binary
+*.pyo binary
+*.pyw text diff=python
+*.pywz binary
+*.pyx text
+*.pyz binary
+*.rar binary
+*.rb text diff=ruby
+*.rtf diff=astextplain
+*.sass text
+*.scss text
+*.sh text eol=lf
+*.sln text
+*.so binary
+*.sql text
+*.styl text
+*.svg text
+*.svgz binary
+*.tar binary
+*.tif binary
+*.tiff binary
+*.ts text
+*.tsv text
+*.tsx text
+*.ttf binary
+*.txt text
+*.war binary
+*.wav binary
+*.wbmp binary
+*.webm binary
+*.webp binary
+*.woff binary
+*.woff2 binary
+*.xhtml text diff=html
+*.xml text
+*.xz binary
+*.yaml text
+*.yml text
+*.zip binary
+.editorconfig text
+.eslintrc text
+.gitattributes text
+.gitconfig text
+.gitignore text
+.htaccess text
+AUTHORS* text
+CHANGELOG* text
+CHANGES* text
+CONTRIBUTING* text
+COPYING* text
+COPYRIGHT* text
+Dockerfile text
+INSTALL* text
+LICENSE* text
+Makefile text
+makefile text
+NEWS* text
+README* text
+TODO* text
diff --git a/.gitignore b/.gitignore
index 3544fee..1de8bd6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,14 +1,102 @@
-/[Ll]ibrary/
-/[Tt]emp/
-/[Oo]bj/
-/[Bb]uild/
-/[Bb]uilds/
-/Assets/AssetStoreTools*
+## Linux.gitignore
+## https://github.com/github/gitignore
+*~
+
+# temporary files which can be created if a process still has a handle open of a deleted file
+.fuse_hidden*
+
+# KDE directory preferences
+.directory
+
+# Linux trash folder which might appear on any partition or disk
+.Trash-*
+
+# .nfs files are created when an open file is removed but is still being accessed
+.nfs*
+
+## macOS.gitignore
+## https://github.com/github/gitignore
+
+# General
.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+## Windows.gitignore
+## https://github.com/github/gitignore
+
+# Windows thumbnail cache files
+Thumbs.db
+ehthumbs.db
+ehthumbs_vista.db
+
+# Dump file
+*.stackdump
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+## MonoDevelop.gitignore
+## https://github.com/github/gitignore
+
+#User Specific
+*.userprefs
+*.usertasks
+
+#Mono Project Files
+*.pidb
+*.resources
+test-results/
+
+## Unity.gitignore
+## https://github.com/github/gitignore
-# Visual Studio 2015 cache directory
-/.vs/
+[Ll]ibrary/
+[Tt]emp/
+[Oo]bj/
+[Bb]uild/
+[Bb]uilds/
+Assets/AssetStoreTools*
+
+# Visual Studio cache directory
+.vs/
# Autogenerated VS/MD/Consulo solution and project files
ExportedObj/
@@ -24,9 +112,11 @@ ExportedObj/
*.booproj
*.svd
*.pdb
+*.opendb
# Unity3D generated meta files
*.pidb.meta
+*.pdb.meta
# Unity3D Generated File On Crash Reports
sysinfo.txt
@@ -35,20 +125,354 @@ sysinfo.txt
*.apk
*.unitypackage
-\.DS_Store
+## VisualStudio.gitignore
+## https://github.com/github/gitignore
+
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
-Carthage/
+# MSBuild Binary and Structured Log
+*.binlog
-\.vscode/
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
-unity\.log
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
-ICSharpCode\.SharpZipLib\.dll
+# Local History for Visual Studio
+.localhistory/
-UnityPacker\.exe
+## VisualStudioCode.gitignore
+## https://github.com/github/gitignore
-Assets/Zapic/Plugins/Android/ZapicManifest\.plugin/AndroidManifest\.xml
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
-Assets/Zapic/Plugins/Android/ZapicManifest\.plugin/AndroidManifest\.xml\.meta
+## Zapic-SDK-Unity
-Scripts/zapic-ios/
+# Keep Unity meta files
+!/Assets/**/*.meta
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000..4121d12
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,35 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "Unity Editor",
+ "type": "unity",
+ "request": "launch"
+ },
+ {
+ "name": "Windows Player",
+ "type": "unity",
+ "request": "launch"
+ },
+ {
+ "name": "OSX Player",
+ "type": "unity",
+ "request": "launch"
+ },
+ {
+ "name": "Linux Player",
+ "type": "unity",
+ "request": "launch"
+ },
+ {
+ "name": "iOS Player",
+ "type": "unity",
+ "request": "launch"
+ },
+ {
+ "name": "Android Player",
+ "type": "unity",
+ "request": "launch"
+ }
+ ]
+}
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..c169b2c
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,61 @@
+{
+ "editor.formatOnSave": true,
+ "editor.minimap.showSlider": "always",
+ "editor.renderWhitespace": "all",
+ "editor.rulers": [
+ 120
+ ],
+ "files.exclude": {
+ "**/.DS_Store": true,
+ "**/.git": true,
+ "**/.gitignore": true,
+ "**/.gitmodules": true,
+ "**/*.booproj": true,
+ "**/*.pidb": true,
+ "**/*.suo": true,
+ "**/*.user": true,
+ "**/*.userprefs": true,
+ "**/*.unityproj": true,
+ "**/*.dll": true,
+ "**/*.exe": true,
+ "**/*.pdf": true,
+ "**/*.mid": true,
+ "**/*.midi": true,
+ "**/*.wav": true,
+ "**/*.gif": true,
+ "**/*.ico": true,
+ "**/*.jpg": true,
+ "**/*.jpeg": true,
+ "**/*.png": true,
+ "**/*.psd": true,
+ "**/*.tga": true,
+ "**/*.tif": true,
+ "**/*.tiff": true,
+ "**/*.3ds": true,
+ "**/*.3DS": true,
+ "**/*.fbx": true,
+ "**/*.FBX": true,
+ "**/*.lxo": true,
+ "**/*.LXO": true,
+ "**/*.ma": true,
+ "**/*.MA": true,
+ "**/*.obj": true,
+ "**/*.OBJ": true,
+ "**/*.asset": true,
+ "**/*.cubemap": true,
+ "**/*.flare": true,
+ "**/*.mat": true,
+ "**/*.meta": true,
+ "**/*.prefab": true,
+ "**/*.unity": true,
+ "build/": true,
+ "Build/": true,
+ "Library/": true,
+ "library/": true,
+ "obj/": true,
+ "Obj/": true,
+ "ProjectSettings/": true,
+ "temp/": true,
+ "Temp/": true
+ }
+}
diff --git a/Assets/Plugins.meta b/Assets/Plugins.meta
index 6270fb9..efcfac5 100644
--- a/Assets/Plugins.meta
+++ b/Assets/Plugins.meta
@@ -1,9 +1,8 @@
fileFormatVersion: 2
guid: 606f231f0cbb54ab7853c818b6e345c3
folderAsset: yes
-timeCreated: 1499975660
-licenseType: Free
DefaultImporter:
+ externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
diff --git a/Assets/Plugins/iOS.meta b/Assets/Plugins/iOS.meta
index 93d7f73..a683810 100644
--- a/Assets/Plugins/iOS.meta
+++ b/Assets/Plugins/iOS.meta
@@ -1,9 +1,8 @@
fileFormatVersion: 2
guid: 506768d1943294e739a974caea2bd5f7
folderAsset: yes
-timeCreated: 1499975660
-licenseType: Free
DefaultImporter:
+ externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
diff --git a/Assets/Zapic.meta b/Assets/Zapic.meta
index 7e8fcf9..6643e29 100644
--- a/Assets/Zapic.meta
+++ b/Assets/Zapic.meta
@@ -1,9 +1,8 @@
fileFormatVersion: 2
guid: 57c97fd9ddf314f3e8a01daef17136f6
folderAsset: yes
-timeCreated: 1499959067
-licenseType: Free
DefaultImporter:
+ externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
diff --git a/Assets/Zapic/Android.meta b/Assets/Zapic/Android.meta
new file mode 100644
index 0000000..3782e12
--- /dev/null
+++ b/Assets/Zapic/Android.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 17900b8270f67eb4f94abb41faaa7b30
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Zapic/Android/ZapicAndroidAuthenticationHandler.cs b/Assets/Zapic/Android/ZapicAndroidAuthenticationHandler.cs
new file mode 100644
index 0000000..094e035
--- /dev/null
+++ b/Assets/Zapic/Android/ZapicAndroidAuthenticationHandler.cs
@@ -0,0 +1,135 @@
+#if !UNITY_EDITOR && UNITY_ANDROID
+
+using System;
+using UnityEngine;
+
+namespace ZapicSDK
+{
+ /// An implementation of the ZapicPlayerAuthenticationHandler Java interface.
+ internal sealed class ZapicAndroidAuthenticationHandler : AndroidJavaProxy
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ internal ZapicAndroidAuthenticationHandler()
+ : base("com/zapic/sdk/android/ZapicPlayerAuthenticationHandler")
+ {
+ }
+
+ ///
+ /// Gets or sets the callback invoked after the player has been logged in.
+ /// The player that has been logged in is passed to the callback.
+ ///
+ public Action OnLogin { get; set; }
+
+ ///
+ /// Gets or sets the callback invoked after the player has been logged out.
+ /// The player that has been logged out is passed to the callback.
+ ///
+ public Action OnLogout { get; set; }
+
+ /// Invoked after the player has logged in.
+ /// The current player.
+ public void onLogin(AndroidJavaObject playerObject)
+ {
+ try
+ {
+ var handler = OnLogin;
+ if (handler == null)
+ {
+ return;
+ }
+
+ ZapicPlayer player;
+ try
+ {
+ player = ZapicAndroidUtilities.ConvertPlayer(playerObject);
+ }
+ catch (Exception e)
+ {
+ Debug.LogError("Zapic: An error occurred converting the Java object to ZapicPlayer");
+ Debug.LogException(e);
+ return;
+ }
+ finally
+ {
+ if (playerObject != null)
+ {
+ playerObject.Dispose();
+ playerObject = null;
+ }
+ }
+
+ try
+ {
+ handler(player);
+ }
+ catch (Exception e)
+ {
+ Debug.LogError("Zapic: An error occurred invoking the application callback");
+ Debug.LogException(e);
+ }
+ }
+ finally
+ {
+ if (playerObject != null)
+ {
+ playerObject.Dispose();
+ }
+ }
+ }
+
+ /// Invoked after the player has logged out.
+ /// The previous player.
+ public void onLogout(AndroidJavaObject playerObject)
+ {
+ try
+ {
+ var handler = OnLogout;
+ if (handler == null)
+ {
+ return;
+ }
+
+ ZapicPlayer player;
+ try
+ {
+ player = ZapicAndroidUtilities.ConvertPlayer(playerObject);
+ }
+ catch (Exception e)
+ {
+ Debug.LogError("Zapic: An error occurred converting the Java object to ZapicPlayer");
+ Debug.LogException(e);
+ return;
+ }
+ finally
+ {
+ if (playerObject != null)
+ {
+ playerObject.Dispose();
+ playerObject = null;
+ }
+ }
+
+ try
+ {
+ handler(player);
+ }
+ catch (Exception e)
+ {
+ Debug.LogError("Zapic: An error occurred invoking the application callback");
+ Debug.LogException(e);
+ }
+ }
+ finally
+ {
+ if (playerObject != null)
+ {
+ playerObject.Dispose();
+ }
+ }
+ }
+ }
+}
+
+#endif
diff --git a/Assets/Zapic/ZapicPlayType.cs.meta b/Assets/Zapic/Android/ZapicAndroidAuthenticationHandler.cs.meta
similarity index 83%
rename from Assets/Zapic/ZapicPlayType.cs.meta
rename to Assets/Zapic/Android/ZapicAndroidAuthenticationHandler.cs.meta
index 10b25f3..c7da634 100644
--- a/Assets/Zapic/ZapicPlayType.cs.meta
+++ b/Assets/Zapic/Android/ZapicAndroidAuthenticationHandler.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: f8d8857a98f274eaf93fdb0af1d8b02e
+guid: 4899efc78318d0340894b81306029e86
MonoImporter:
externalObjects: {}
serializedVersion: 2
diff --git a/Assets/Zapic/Android/ZapicAndroidFunctionCallback{T}.cs b/Assets/Zapic/Android/ZapicAndroidFunctionCallback{T}.cs
new file mode 100644
index 0000000..0c6eb38
--- /dev/null
+++ b/Assets/Zapic/Android/ZapicAndroidFunctionCallback{T}.cs
@@ -0,0 +1,170 @@
+#if !UNITY_EDITOR && UNITY_ANDROID
+
+using System;
+using UnityEngine;
+
+namespace ZapicSDK
+{
+ /// A delegate-based implementation of the ZapicCallback Java interface.
+ /// The type of the result.
+ internal sealed class ZapicAndroidFunctionCallback : AndroidJavaProxy
+ where T : class
+ {
+ /// The callback invoked with the result of the asynchronous operation.
+ private readonly Action callback;
+
+ /// The callback invoked to convert the result of the asynchronous operation.
+ private readonly Func convertResult;
+
+ /// Initializes a new instance of the class.
+ /// The callback invoked with the result of the asynchronous operation.
+ ///
+ /// The callback invoked to convert the result of the asynchronous operation.
+ ///
+ ///
+ /// If or are null.
+ ///
+ internal ZapicAndroidFunctionCallback(
+ Action callback,
+ Func convertResult)
+ : base("com/zapic/sdk/android/ZapicCallback")
+ {
+ if (callback == null)
+ {
+ throw new ArgumentNullException("callback");
+ }
+
+ if (convertResult == null)
+ {
+ throw new ArgumentNullException("convertResult");
+ }
+
+ this.callback = callback;
+ this.convertResult = convertResult;
+ }
+
+ /// Called when the asynchronous operation is complete.
+ /// The result of the asynchronous operation.
+ ///
+ /// The error thrown by the asynchronous operation. This will be {@code null} if the asynchronous operation
+ /// completed normally.
+ ///
+ public void onComplete(AndroidJavaObject resultObject, AndroidJavaObject errorObject)
+ {
+ try
+ {
+ ZapicException error;
+ try
+ {
+ error = ZapicAndroidUtilities.ConvertError(errorObject);
+ }
+ catch (Exception e)
+ {
+ Debug.LogError("Zapic: An error occurred converting the Java object to ZapicException");
+ Debug.LogException(e);
+
+ error = e as ZapicException;
+ if (error == null)
+ {
+ error = new ZapicException(
+ ZapicErrorCode.INVALID_RESPONSE,
+ "An error occurred converting the Java object to ZapicException",
+ e);
+ }
+ }
+ finally
+ {
+ if (errorObject != null)
+ {
+ errorObject.Dispose();
+ errorObject = null;
+ }
+ }
+
+ if (error != null)
+ {
+ if (resultObject != null)
+ {
+ resultObject.Dispose();
+ resultObject = null;
+ }
+
+ try
+ {
+ callback(null, error);
+ }
+ catch (Exception e)
+ {
+ Debug.LogError("Zapic: An error occurred invoking the application callback");
+ Debug.LogException(e);
+ }
+
+ return;
+ }
+
+ T result;
+ try
+ {
+ result = convertResult(resultObject);
+ }
+ catch (Exception e)
+ {
+ Debug.LogError("Zapic: An error occurred converting the Java object to " + typeof(T).Name);
+ Debug.LogException(e);
+
+ error = e as ZapicException;
+ if (error == null)
+ {
+ error = new ZapicException(
+ ZapicErrorCode.INVALID_RESPONSE,
+ "An error occurred converting the Java object to " + typeof(T).Name,
+ e);
+ }
+
+ result = null;
+ }
+ finally
+ {
+ if (resultObject != null)
+ {
+ resultObject.Dispose();
+ resultObject = null;
+ }
+ }
+
+ try
+ {
+ if (error != null)
+ {
+ callback(null, error);
+ }
+ else
+ {
+ callback(result, null);
+ }
+ }
+ catch (Exception e)
+ {
+ Debug.LogError("Zapic: An error occurred invoking the application callback");
+ Debug.LogException(e);
+ }
+ }
+ finally
+ {
+ if (errorObject != null)
+ {
+ errorObject.Dispose();
+ }
+
+ if (resultObject != null)
+ {
+ resultObject.Dispose();
+ }
+
+ javaInterface.Dispose();
+ }
+ }
+ }
+}
+
+#endif
diff --git a/Assets/Zapic/Android/ZapicAndroidFunctionCallback{T}.cs.meta b/Assets/Zapic/Android/ZapicAndroidFunctionCallback{T}.cs.meta
new file mode 100644
index 0000000..263225d
--- /dev/null
+++ b/Assets/Zapic/Android/ZapicAndroidFunctionCallback{T}.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 267976c06cdf93248b806b05ce6bace3
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Zapic/Android/ZapicAndroidInterface.cs b/Assets/Zapic/Android/ZapicAndroidInterface.cs
new file mode 100644
index 0000000..e2fc6fd
--- /dev/null
+++ b/Assets/Zapic/Android/ZapicAndroidInterface.cs
@@ -0,0 +1,255 @@
+#if !UNITY_EDITOR && UNITY_ANDROID
+
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+#if NET_4_6 || NET_STANDARD_2_0
+using System.Threading;
+using System.Threading.Tasks;
+#endif
+
+namespace ZapicSDK
+{
+ /// An that communicates with the Android SDK.
+ internal sealed class ZapicAndroidInterface : IZapicInterface
+ {
+ /// The authentication handler registered with the Android SDK.
+ private readonly ZapicAndroidAuthenticationHandler authenticationHandler;
+
+ /// A value indicating whether the Android SDK has been initialized.
+ private bool initialized;
+
+ /// Initializes a new instance of the class.
+ internal ZapicAndroidInterface()
+ {
+ authenticationHandler = new ZapicAndroidAuthenticationHandler();
+ initialized = false;
+ }
+
+ public Action OnLogin { get; set; }
+
+ public Action OnLogout { get; set; }
+
+ public void GetChallenges(Action callback)
+ {
+ Get("getChallenges", callback, ZapicAndroidUtilities.ConvertChallenges);
+ }
+
+#if NET_4_6 || NET_STANDARD_2_0
+ public Task GetChallengesAsync(CancellationToken cancellationToken)
+ {
+ return GetAsync("getChallenges", ZapicAndroidUtilities.ConvertChallenges, cancellationToken);
+ }
+#endif
+
+ public void GetCompetitions(Action callback)
+ {
+ Get("getCompetitions", callback, ZapicAndroidUtilities.ConvertCompetitions);
+ }
+
+#if NET_4_6 || NET_STANDARD_2_0
+ public Task GetCompetitionsAsync(CancellationToken cancellationToken)
+ {
+ return GetAsync("getCompetitions", ZapicAndroidUtilities.ConvertCompetitions, cancellationToken);
+ }
+#endif
+
+ public void GetPlayer(Action callback)
+ {
+ Get("getPlayer", callback, ZapicAndroidUtilities.ConvertPlayer);
+ }
+
+#if NET_4_6 || NET_STANDARD_2_0
+ public Task GetPlayerAsync(CancellationToken cancellationToken)
+ {
+ return GetAsync("getPlayer", ZapicAndroidUtilities.ConvertPlayer, cancellationToken);
+ }
+#endif
+
+ public void GetStatistics(Action callback)
+ {
+ Get("getStatistics", callback, ZapicAndroidUtilities.ConvertStatistics);
+ }
+
+#if NET_4_6 || NET_STANDARD_2_0
+ public Task GetStatisticsAsync(CancellationToken cancellationToken)
+ {
+ return GetAsync("getStatistics", ZapicAndroidUtilities.ConvertStatistics, cancellationToken);
+ }
+#endif
+
+ public void HandleInteraction(Dictionary parameters)
+ {
+ var json = MiniJSON.Json.Serialize(parameters);
+
+ using (var parametersObject = new AndroidJavaObject("java/lang/String", json))
+ using (var zapicClass = new AndroidJavaClass("com/zapic/sdk/android/Zapic"))
+ {
+ zapicClass.CallStatic("handleInteraction", parametersObject);
+ }
+ }
+
+ [Obsolete]
+ public ZapicPlayer Player()
+ {
+ using (var zapicClass = new AndroidJavaClass("com/zapic/sdk/android/Zapic"))
+ using (var playerObject = zapicClass.CallStatic("getCurrentPlayer"))
+ {
+ try
+ {
+ var player = ZapicAndroidUtilities.ConvertPlayer(playerObject);
+ return player;
+ }
+ catch (Exception e)
+ {
+ Debug.LogError("Zapic: An error occurred converting the Java object to ZapicPlayer");
+ Debug.LogException(e);
+
+ if (e is ZapicException)
+ {
+ throw;
+ }
+
+ throw new ZapicException(
+ ZapicErrorCode.INVALID_RESPONSE,
+ "An error occurred converting the Java object to ZapicPlayer",
+ e);
+ }
+ }
+ }
+
+ public void ShowDefaultPage()
+ {
+ using (var unityPlayerClass = new AndroidJavaClass("com/unity3d/player/UnityPlayer"))
+ using (var activityObject = unityPlayerClass.GetStatic("currentActivity"))
+ using (var zapicClass = new AndroidJavaClass("com/zapic/sdk/android/Zapic"))
+ {
+ zapicClass.CallStatic("showDefaultPage", activityObject);
+ }
+ }
+
+ public void ShowPage(ZapicPage page)
+ {
+ using (var unityPlayerClass = new AndroidJavaClass("com/unity3d/player/UnityPlayer"))
+ using (var activityObject = unityPlayerClass.GetStatic("currentActivity"))
+ using (var zapicClass = new AndroidJavaClass("com/zapic/sdk/android/Zapic"))
+ using (var pageObject = new AndroidJavaObject("java/lang/String", page.ToString().ToLowerInvariant()))
+ {
+ zapicClass.CallStatic("showPage", activityObject, pageObject);
+ }
+ }
+
+ public void Start()
+ {
+ if (initialized)
+ {
+ return;
+ }
+
+ using (var unityPlayerClass = new AndroidJavaClass("com/unity3d/player/UnityPlayer"))
+ using (var activityObject = unityPlayerClass.GetStatic("currentActivity"))
+ {
+ activityObject.Call("runOnUiThread", new AndroidJavaRunnable(StartOnUI));
+ }
+ }
+
+ public void SubmitEvent(Dictionary parameters)
+ {
+ var json = MiniJSON.Json.Serialize(parameters);
+
+ using (var parametersObject = new AndroidJavaObject("java/lang/String", json))
+ using (var zapicClass = new AndroidJavaClass("com/zapic/sdk/android/Zapic"))
+ {
+ zapicClass.CallStatic("submitEvent", parametersObject);
+ }
+ }
+
+ private void Get(
+ string methodName,
+ Action callback,
+ Func convertResult)
+ where T : class
+ {
+ var callbackWrapper = new ZapicAndroidFunctionCallback(callback, convertResult);
+
+ using (var zapicClass = new AndroidJavaClass("com/zapic/sdk/android/Zapic"))
+ {
+ var future = zapicClass.CallStatic(methodName, callbackWrapper);
+ if (future != null)
+ {
+ future.Dispose();
+ }
+ }
+ }
+
+#if NET_4_6 || NET_STANDARD_2_0
+ private Task GetAsync(
+ string methodName,
+ Func convertResult,
+ CancellationToken cancellationToken)
+ where T : class
+ {
+ var taskCompletionSource = new TaskCompletionSource();
+ var callbackWrapper = new ZapicAndroidTaskCallback(taskCompletionSource, convertResult);
+
+ using (var zapicClass = new AndroidJavaClass("com/zapic/sdk/android/Zapic"))
+ {
+ var future = zapicClass.CallStatic(methodName, callbackWrapper);
+ if (future != null)
+ {
+ if (cancellationToken.CanBeCanceled)
+ {
+ var registration = cancellationToken.Register(() =>
+ {
+ if (taskCompletionSource.TrySetCanceled(cancellationToken))
+ {
+ future.Call("cancel", true);
+ }
+ });
+
+ return taskCompletionSource.Task.ContinueWith(
+ parentTask =>
+ {
+ registration.Dispose();
+ future.Dispose();
+ return parentTask;
+ },
+ TaskContinuationOptions.ExecuteSynchronously).Unwrap();
+ }
+ else
+ {
+ future.Dispose();
+ }
+ }
+
+ return taskCompletionSource.Task;
+ }
+ }
+#endif
+
+ private void StartOnUI()
+ {
+ if (initialized)
+ {
+ return;
+ }
+
+ // Ensure initialization only runs once.
+ initialized = true;
+
+ using (var zapicClass = new AndroidJavaClass("com/zapic/sdk/android/Zapic"))
+ {
+ zapicClass.CallStatic("setPlayerAuthenticationHandler", authenticationHandler);
+
+ using (var unityPlayerClass = new AndroidJavaClass("com/unity3d/player/UnityPlayer"))
+ using (var activityObject = unityPlayerClass.GetStatic("currentActivity"))
+ {
+ zapicClass.CallStatic("attachFragment", activityObject);
+ }
+ }
+ }
+ }
+}
+
+#endif
diff --git a/Assets/Zapic/ZapicAndroidInterface.cs.meta b/Assets/Zapic/Android/ZapicAndroidInterface.cs.meta
similarity index 85%
rename from Assets/Zapic/ZapicAndroidInterface.cs.meta
rename to Assets/Zapic/Android/ZapicAndroidInterface.cs.meta
index 6822706..830f9be 100644
--- a/Assets/Zapic/ZapicAndroidInterface.cs.meta
+++ b/Assets/Zapic/Android/ZapicAndroidInterface.cs.meta
@@ -1,7 +1,5 @@
fileFormatVersion: 2
guid: 4b530f454ec88a34b9cde3857fd23e1a
-timeCreated: 1518560456
-licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
diff --git a/Assets/Zapic/Android/ZapicAndroidLog.cs b/Assets/Zapic/Android/ZapicAndroidLog.cs
new file mode 100644
index 0000000..83ed39e
--- /dev/null
+++ b/Assets/Zapic/Android/ZapicAndroidLog.cs
@@ -0,0 +1,30 @@
+#if !UNITY_EDITOR && UNITY_ANDROID
+
+using UnityEngine;
+
+namespace ZapicSDK
+{
+ /// Provides static methods to enable or disable verbose SDK logging.
+ internal static class ZapicAndroidLog
+ {
+ /// Disables verbose SDK logging.
+ internal static void Disable()
+ {
+ using (var zapicLogClass = new AndroidJavaClass("com/zapic/sdk/android/ZapicLog"))
+ {
+ zapicLogClass.CallStatic("setLogLevel", 7);
+ }
+ }
+
+ /// Enables verbose SDK logging.
+ internal static void Enable()
+ {
+ using (var zapicLogClass = new AndroidJavaClass("com/zapic/sdk/android/ZapicLog"))
+ {
+ zapicLogClass.CallStatic("setLogLevel", 2);
+ }
+ }
+ }
+}
+
+#endif
diff --git a/Assets/Zapic/Android/ZapicAndroidLog.cs.meta b/Assets/Zapic/Android/ZapicAndroidLog.cs.meta
new file mode 100644
index 0000000..ee7e543
--- /dev/null
+++ b/Assets/Zapic/Android/ZapicAndroidLog.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 9082889e8c4e5a541a142e2f88d00906
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Zapic/Android/ZapicAndroidTaskCallback{T}.cs b/Assets/Zapic/Android/ZapicAndroidTaskCallback{T}.cs
new file mode 100644
index 0000000..66b7001
--- /dev/null
+++ b/Assets/Zapic/Android/ZapicAndroidTaskCallback{T}.cs
@@ -0,0 +1,154 @@
+#if !UNITY_EDITOR && UNITY_ANDROID && (NET_4_6 || NET_STANDARD_2_0)
+
+using System;
+using System.Threading.Tasks;
+using UnityEngine;
+
+namespace ZapicSDK
+{
+ /// A -based implementation of the ZapicCallback Java interface.
+ /// The type of the result.
+ internal sealed class ZapicAndroidTaskCallback : AndroidJavaProxy
+ where T : class
+ {
+ /// The callback invoked to convert the result of the asynchronous operation.
+ private readonly Func convertResult;
+
+ /// The task completion source to receive the result of the asynchronous operation.
+ private readonly TaskCompletionSource task;
+
+ /// Initializes a new instance of the class.
+ ///
+ /// The task completion source to receive the result of the asynchronous operation.
+ ///
+ ///
+ /// The callback invoked to convert the result of the asynchronous operation.
+ ///
+ ///
+ /// If or are null.
+ ///
+ internal ZapicAndroidTaskCallback(TaskCompletionSource task, Func convertResult)
+ : base("com/zapic/sdk/android/ZapicCallback")
+ {
+ if (task == null)
+ {
+ throw new ArgumentNullException("task");
+ }
+
+ if (convertResult == null)
+ {
+ throw new ArgumentNullException("convertResult");
+ }
+
+ this.convertResult = convertResult;
+ this.task = task;
+ }
+
+ /// Called when the asynchronous operation is complete.
+ /// The result of the asynchronous operation.
+ ///
+ /// The error thrown by the asynchronous operation. This will be {@code null} if the asynchronous operation
+ /// completed normally.
+ ///
+ public void onComplete(AndroidJavaObject resultObject, AndroidJavaObject errorObject)
+ {
+ try
+ {
+ ZapicException error;
+ try
+ {
+ error = ZapicAndroidUtilities.ConvertError(errorObject);
+ }
+ catch (Exception e)
+ {
+ Debug.LogError("Zapic: An error occurred converting the Java object to ZapicException");
+ Debug.LogException(e);
+
+ error = e as ZapicException;
+ if (error == null)
+ {
+ error = new ZapicException(
+ ZapicErrorCode.INVALID_RESPONSE,
+ "An error occurred converting the Java object to ZapicException",
+ e);
+ }
+ }
+ finally
+ {
+ if (errorObject != null)
+ {
+ errorObject.Dispose();
+ errorObject = null;
+ }
+ }
+
+ if (error != null)
+ {
+ if (resultObject != null)
+ {
+ resultObject.Dispose();
+ resultObject = null;
+ }
+
+ task.TrySetException(error);
+ return;
+ }
+
+ T result;
+ try
+ {
+ result = convertResult(resultObject);
+ }
+ catch (Exception e)
+ {
+ Debug.LogError("Zapic: An error occurred converting the Java object to " + typeof(T).Name);
+ Debug.LogException(e);
+
+ error = e as ZapicException;
+ if (error == null)
+ {
+ error = new ZapicException(
+ ZapicErrorCode.INVALID_RESPONSE,
+ "An error occurred converting the Java object to " + typeof(T).Name,
+ e);
+ }
+
+ result = null;
+ }
+ finally
+ {
+ if (resultObject != null)
+ {
+ resultObject.Dispose();
+ resultObject = null;
+ }
+ }
+
+ if (error != null)
+ {
+ task.TrySetException(error);
+ }
+ else
+ {
+ task.TrySetResult(result);
+ }
+ }
+ finally
+ {
+ if (errorObject != null)
+ {
+ errorObject.Dispose();
+ }
+
+ if (resultObject != null)
+ {
+ resultObject.Dispose();
+ }
+
+ javaInterface.Dispose();
+ }
+ }
+ }
+}
+
+#endif
diff --git a/Assets/Zapic/Android/ZapicAndroidTaskCallback{T}.cs.meta b/Assets/Zapic/Android/ZapicAndroidTaskCallback{T}.cs.meta
new file mode 100644
index 0000000..72c4b25
--- /dev/null
+++ b/Assets/Zapic/Android/ZapicAndroidTaskCallback{T}.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 1e0dff69044788248bac2400bdee3985
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Zapic/Android/ZapicAndroidUtilities.cs b/Assets/Zapic/Android/ZapicAndroidUtilities.cs
new file mode 100644
index 0000000..2cd38f9
--- /dev/null
+++ b/Assets/Zapic/Android/ZapicAndroidUtilities.cs
@@ -0,0 +1,562 @@
+#if !UNITY_EDITOR && UNITY_ANDROID
+
+using System;
+using UnityEngine;
+
+namespace ZapicSDK
+{
+ /// Provides utility methods to convert the Java class instances to C# class instances.
+ internal static class ZapicAndroidUtilities
+ {
+ ///
+ /// Converts a ZapicChallenge Java class instance to a instance.
+ ///
+ /// The ZapicChallenge Java class instance.
+ /// The converted instance or null.
+ /// If an error occurs converting the Java class instance.
+ internal static ZapicChallenge ConvertChallenge(AndroidJavaObject challengeObject)
+ {
+ try
+ {
+ if (challengeObject == null || challengeObject.GetRawObject() == IntPtr.Zero)
+ {
+ return null;
+ }
+
+ // active
+ var active = challengeObject.Get("active");
+
+ // description
+ var description = challengeObject.Get("description");
+
+ // end.getTime()
+ DateTime end;
+ using (var endObject = challengeObject.Get("end"))
+ {
+ if (endObject == null || endObject.GetRawObject() == IntPtr.Zero)
+ {
+ throw new ZapicException(
+ ZapicErrorCode.INVALID_RESPONSE,
+ "The end date and time must not be null");
+ }
+
+#if NET_4_6 || NET_STANDARD_2_0
+ end = DateTimeOffset.FromUnixTimeMilliseconds(endObject.Call("getTime")).UtcDateTime;
+#else
+ end = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc) +
+ TimeSpan.FromMilliseconds(endObject.Call("getTime"));
+#endif
+ }
+
+ // formattedScore
+ var formattedScore = challengeObject.Get("formattedScore");
+
+ // id
+ var id = challengeObject.Get("id");
+
+ // metadata
+ var metadata = challengeObject.Get("metadata");
+
+ // rank.longValue()
+ long? rank;
+ using (var rankObject = challengeObject.Get("rank"))
+ {
+ rank = rankObject == null || rankObject.GetRawObject() == IntPtr.Zero
+ ? (long?)null
+ : rankObject.Call("longValue");
+ }
+
+ // score.doubleValue()
+ double? score;
+ using (var scoreObject = challengeObject.Get("score"))
+ {
+ score = scoreObject == null || scoreObject.GetRawObject() == IntPtr.Zero
+ ? (double?)null
+ : scoreObject.Call("doubleValue");
+ }
+
+ // start.getTime()
+ DateTime start;
+ using (var startObject = challengeObject.Get("start"))
+ {
+ if (startObject == null || startObject.GetRawObject() == IntPtr.Zero)
+ {
+ throw new ZapicException(
+ ZapicErrorCode.INVALID_RESPONSE,
+ "The start date and time must not be null");
+ }
+
+#if NET_4_6 || NET_STANDARD_2_0
+ start = DateTimeOffset.FromUnixTimeMilliseconds(startObject.Call("getTime")).UtcDateTime;
+#else
+ start = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc) +
+ TimeSpan.FromMilliseconds(startObject.Call("getTime"));
+#endif
+ }
+
+ // status
+ var status = (ZapicChallengeStatus)challengeObject.Get("status");
+
+ // title
+ var title = challengeObject.Get("title");
+
+ // totalUsers
+ var totalUsers = challengeObject.Get("totalUsers");
+
+ return new ZapicChallenge(
+ id,
+ title,
+ description,
+ metadata,
+ active,
+ start,
+ end,
+ totalUsers,
+ status,
+ score,
+ formattedScore,
+ rank);
+ }
+ catch (Exception e)
+ {
+ throw new ZapicException(
+ ZapicErrorCode.INVALID_RESPONSE,
+ "An error occurred converting the challenge",
+ e);
+ }
+ }
+
+ ///
+ /// Converts an array of ZapicChallenge Java class instances to an array of
+ /// instances.
+ ///
+ /// The array of ZapicChallenge Java class instances.
+ /// The converted array of instances or null.
+ /// If an error occurs converting the Java class instances.
+ internal static ZapicChallenge[] ConvertChallenges(AndroidJavaObject arrayObject)
+ {
+ if (arrayObject == null)
+ {
+ return null;
+ }
+
+ AndroidJavaObject[] itemObjects;
+ try
+ {
+ var arrayPointer = arrayObject.GetRawObject();
+ itemObjects = arrayPointer == IntPtr.Zero
+ ? null
+ : AndroidJNIHelper.ConvertFromJNIArray(arrayPointer);
+ if (itemObjects == null)
+ {
+ return null;
+ }
+ }
+ catch (Exception e)
+ {
+ throw new ZapicException(
+ ZapicErrorCode.INVALID_RESPONSE,
+ "An error occurred converting the array of challenges",
+ e);
+ }
+
+ var challenges = new ZapicChallenge[itemObjects.Length];
+ for (var i = 0; i < itemObjects.Length; i++)
+ {
+ try
+ {
+ var itemObject = itemObjects[i];
+ challenges[i] = ConvertChallenge(itemObject);
+ itemObject.Dispose();
+ }
+ catch
+ {
+ for (var j = i; j < itemObjects.Length; j++)
+ {
+ itemObjects[j].Dispose();
+ }
+
+ throw;
+ }
+ }
+
+ return challenges;
+ }
+
+ ///
+ /// Converts a ZapicCompetition Java class instance to a instance.
+ ///
+ /// The ZapicCompetition Java class instance.
+ /// The converted instance or null.
+ /// If an error occurs converting the Java class instance.
+ internal static ZapicCompetition ConvertCompetition(AndroidJavaObject competitionObject)
+ {
+ try
+ {
+ if (competitionObject == null || competitionObject.GetRawObject() == IntPtr.Zero)
+ {
+ return null;
+ }
+
+ // active
+ var active = competitionObject.Get("active");
+
+ // description
+ var description = competitionObject.Get("description");
+
+ // end.getTime()
+ DateTime end;
+ using (var endObject = competitionObject.Get("end"))
+ {
+ if (endObject == null || endObject.GetRawObject() == IntPtr.Zero)
+ {
+ throw new ZapicException(
+ ZapicErrorCode.INVALID_RESPONSE,
+ "The end date and time must not be null");
+ }
+
+#if NET_4_6 || NET_STANDARD_2_0
+ end = DateTimeOffset.FromUnixTimeMilliseconds(endObject.Call("getTime")).UtcDateTime;
+#else
+ end = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc) +
+ TimeSpan.FromMilliseconds(endObject.Call("getTime"));
+#endif
+ }
+
+ // formattedScore
+ var formattedScore = competitionObject.Get("formattedScore");
+
+ // id
+ var id = competitionObject.Get("id");
+
+ // leaderboardRank.longValue()
+ long? leaderboardRank;
+ using (var leaderboardRankObject = competitionObject.Get("leaderboardRank"))
+ {
+ leaderboardRank = leaderboardRankObject == null || leaderboardRankObject.GetRawObject() == IntPtr.Zero
+ ? (long?)null
+ : leaderboardRankObject.Call("longValue");
+ }
+
+ // leagueRank.longValue()
+ long? leagueRank;
+ using (var leagueRankObject = competitionObject.Get("leagueRank"))
+ {
+ leagueRank = leagueRankObject == null || leagueRankObject.GetRawObject() == IntPtr.Zero
+ ? (long?)null
+ : leagueRankObject.Call("longValue");
+ }
+
+ // metadata
+ var metadata = competitionObject.Get("metadata");
+
+ // score.doubleValue()
+ double? score;
+ using (var scoreObject = competitionObject.Get("score"))
+ {
+ score = scoreObject == null || scoreObject.GetRawObject() == IntPtr.Zero
+ ? (double?)null
+ : scoreObject.Call("doubleValue");
+ }
+
+ // start.getTime()
+ DateTime start;
+ using (var startObject = competitionObject.Get("start"))
+ {
+ if (startObject == null || startObject.GetRawObject() == IntPtr.Zero)
+ {
+ throw new ZapicException(
+ ZapicErrorCode.INVALID_RESPONSE,
+ "The start date and time must not be null");
+ }
+
+#if NET_4_6 || NET_STANDARD_2_0
+ start = DateTimeOffset.FromUnixTimeMilliseconds(startObject.Call("getTime")).UtcDateTime;
+#else
+ start = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc) +
+ TimeSpan.FromMilliseconds(startObject.Call("getTime"));
+#endif
+ }
+
+ // status
+ var status = (ZapicCompetitionStatus)competitionObject.Get("status");
+
+ // title
+ var title = competitionObject.Get("title");
+
+ // totalUsers
+ var totalUsers = competitionObject.Get("totalUsers");
+
+ return new ZapicCompetition(
+ id,
+ title,
+ description,
+ metadata,
+ active,
+ start,
+ end,
+ totalUsers,
+ status,
+ score,
+ formattedScore,
+ leaderboardRank,
+ leagueRank);
+ }
+ catch (Exception e)
+ {
+ throw new ZapicException(
+ ZapicErrorCode.INVALID_RESPONSE,
+ "An error occurred converting the competition",
+ e);
+ }
+ }
+
+ ///
+ /// Converts an array of ZapicCompetition Java class instances to an array of
+ /// instances.
+ ///
+ /// The array of ZapicCompetition Java class instances.
+ /// The converted array of instances or null.
+ /// If an error occurs converting the Java class instances.
+ internal static ZapicCompetition[] ConvertCompetitions(AndroidJavaObject arrayObject)
+ {
+ if (arrayObject == null)
+ {
+ return null;
+ }
+
+ AndroidJavaObject[] itemObjects;
+ try
+ {
+ var arrayPointer = arrayObject.GetRawObject();
+ itemObjects = arrayPointer == IntPtr.Zero
+ ? null
+ : AndroidJNIHelper.ConvertFromJNIArray(arrayPointer);
+ if (itemObjects == null)
+ {
+ return null;
+ }
+ }
+ catch (Exception e)
+ {
+ throw new ZapicException(
+ ZapicErrorCode.INVALID_RESPONSE,
+ "An error occurred converting the array of competitions",
+ e);
+ }
+
+ var competitions = new ZapicCompetition[itemObjects.Length];
+ for (var i = 0; i < itemObjects.Length; i++)
+ {
+ try
+ {
+ var itemObject = itemObjects[i];
+ competitions[i] = ConvertCompetition(itemObject);
+ itemObject.Dispose();
+ }
+ catch
+ {
+ for (var j = i; j < itemObjects.Length; j++)
+ {
+ itemObjects[j].Dispose();
+ }
+
+ throw;
+ }
+ }
+
+ return competitions;
+ }
+
+ ///
+ /// Converts a ZapicException Java class instance to a instance.
+ ///
+ /// The ZapicException Java class instance.
+ /// The converted instance or null.
+ /// If an error occurs converting the Java class instance.
+ internal static ZapicException ConvertError(AndroidJavaObject errorObject)
+ {
+ try
+ {
+ if (errorObject == null || errorObject.GetRawObject() == IntPtr.Zero)
+ {
+ return null;
+ }
+
+ // code
+ var code = errorObject.Get("code");
+
+ // getMessage()
+ var message = errorObject.Call("getMessage");
+
+ return new ZapicException(code, message);
+ }
+ catch (Exception e)
+ {
+ throw new ZapicException(
+ ZapicErrorCode.INVALID_RESPONSE,
+ "An error occurred converting the exception",
+ e);
+ }
+ }
+
+ ///
+ /// Converts a ZapicPlayer Java class instance to a instance.
+ ///
+ /// The ZapicPlayer Java class instance.
+ /// The converted instance or null.
+ /// If an error occurs converting the Java class instance.
+ internal static ZapicPlayer ConvertPlayer(AndroidJavaObject playerObject)
+ {
+ try
+ {
+ if (playerObject == null || playerObject.GetRawObject() == IntPtr.Zero)
+ {
+ return null;
+ }
+
+ // iconUrl.toString()
+ Uri iconUrl;
+ using (var iconUrlObject = playerObject.Get("iconUrl"))
+ {
+ if (iconUrlObject == null || iconUrlObject.GetRawObject() == IntPtr.Zero)
+ {
+ throw new ZapicException(ZapicErrorCode.INVALID_RESPONSE, "The icon URL must not be null");
+ }
+
+ iconUrl = new Uri(iconUrlObject.Call("toString"));
+ }
+
+ // id
+ var id = playerObject.Get("id");
+
+ // name
+ var name = playerObject.Get("name");
+
+ // notificationToken
+ var notificationToken = playerObject.Get("notificationToken");
+
+ return new ZapicPlayer(id, name, iconUrl, notificationToken);
+ }
+ catch (Exception e)
+ {
+ throw new ZapicException(ZapicErrorCode.INVALID_RESPONSE, "An error occurred converting the player", e);
+ }
+ }
+
+ ///
+ /// Converts a ZapicStatistic Java class instance to a instance.
+ ///
+ /// The ZapicStatistic Java class instance.
+ /// The converted instance or null.
+ /// If an error occurs converting the Java class instance.
+ internal static ZapicStatistic ConvertStatistic(AndroidJavaObject statisticObject)
+ {
+ try
+ {
+ if (statisticObject == null || statisticObject.GetRawObject() == IntPtr.Zero)
+ {
+ return null;
+ }
+
+ // formattedScore
+ var formattedScore = statisticObject.Get("formattedScore");
+
+ // id
+ var id = statisticObject.Get("id");
+
+ // metadata
+ var metadata = statisticObject.Get("metadata");
+
+ // percentile.intValue()
+ int? percentile;
+ using (var percentileObject = statisticObject.Get("percentile"))
+ {
+ percentile = percentileObject == null || percentileObject.GetRawObject() == IntPtr.Zero
+ ? (int?)null
+ : percentileObject.Call("intValue");
+ }
+
+ // score.doubleValue()
+ double? score;
+ using (var scoreObject = statisticObject.Get("score"))
+ {
+ score = scoreObject == null || scoreObject.GetRawObject() == IntPtr.Zero
+ ? (double?)null
+ : scoreObject.Call("doubleValue");
+ }
+
+ // title
+ var title = statisticObject.Get("title");
+
+ return new ZapicStatistic(id, title, metadata, score, formattedScore, percentile);
+ }
+ catch (Exception e)
+ {
+ throw new ZapicException(
+ ZapicErrorCode.INVALID_RESPONSE,
+ "An error occurred converting the statistic",
+ e);
+ }
+ }
+
+ ///
+ /// Converts an array of ZapicStatistic Java class instances to an array of
+ /// instances.
+ ///
+ /// The array of ZapicStatistic Java class instances.
+ /// The converted array of instances or null.
+ /// If an error occurs converting the Java class instances.
+ internal static ZapicStatistic[] ConvertStatistics(AndroidJavaObject arrayObject)
+ {
+ if (arrayObject == null)
+ {
+ return null;
+ }
+
+ AndroidJavaObject[] itemObjects;
+ try
+ {
+ var arrayPointer = arrayObject.GetRawObject();
+ itemObjects = arrayPointer == IntPtr.Zero
+ ? null
+ : AndroidJNIHelper.ConvertFromJNIArray(arrayPointer);
+ if (itemObjects == null)
+ {
+ return null;
+ }
+ }
+ catch (Exception e)
+ {
+ throw new ZapicException(
+ ZapicErrorCode.INVALID_RESPONSE,
+ "An error occurred converting the array of statistics",
+ e);
+ }
+
+ var statistics = new ZapicStatistic[itemObjects.Length];
+ for (var i = 0; i < itemObjects.Length; i++)
+ {
+ try
+ {
+ var itemObject = itemObjects[i];
+ statistics[i] = ConvertStatistic(itemObject);
+ itemObject.Dispose();
+ }
+ catch
+ {
+ for (var j = i; j < itemObjects.Length; j++)
+ {
+ itemObjects[j].Dispose();
+ }
+
+ throw;
+ }
+ }
+
+ return statistics;
+ }
+ }
+}
+
+#endif
diff --git a/Assets/Zapic/Android/ZapicAndroidUtilities.cs.meta b/Assets/Zapic/Android/ZapicAndroidUtilities.cs.meta
new file mode 100644
index 0000000..d9e58d6
--- /dev/null
+++ b/Assets/Zapic/Android/ZapicAndroidUtilities.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 9a81ad279fe91f44bbb5d38e2ad9bb72
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Zapic/Editor.meta b/Assets/Zapic/Editor.meta
index 3f7434e..a8d825f 100644
--- a/Assets/Zapic/Editor.meta
+++ b/Assets/Zapic/Editor.meta
@@ -1,9 +1,8 @@
fileFormatVersion: 2
guid: 47d1333ed4d37440183abb0ce4e27708
folderAsset: yes
-timeCreated: 1508167056
-licenseType: Free
DefaultImporter:
+ externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
diff --git a/Assets/Zapic/Editor/ZapicDependencies.xml b/Assets/Zapic/Editor/ZapicDependencies.xml
index da2e7a0..f680dee 100644
--- a/Assets/Zapic/Editor/ZapicDependencies.xml
+++ b/Assets/Zapic/Editor/ZapicDependencies.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/Assets/Zapic/Editor/ZapicDependencies.xml.meta b/Assets/Zapic/Editor/ZapicDependencies.xml.meta
index 77b547c..da83c4f 100644
--- a/Assets/Zapic/Editor/ZapicDependencies.xml.meta
+++ b/Assets/Zapic/Editor/ZapicDependencies.xml.meta
@@ -1,7 +1,5 @@
fileFormatVersion: 2
guid: bbf413162b31d6245a03de79bdca5453
-timeCreated: 1521932374
-licenseType: Free
TextScriptImporter:
externalObjects: {}
userData:
diff --git a/Assets/Zapic/Editor/ZapicPostProcessBuild.cs.meta b/Assets/Zapic/Editor/ZapicPostProcessBuild.cs.meta
index 210a08e..ad24fa1 100644
--- a/Assets/Zapic/Editor/ZapicPostProcessBuild.cs.meta
+++ b/Assets/Zapic/Editor/ZapicPostProcessBuild.cs.meta
@@ -1,8 +1,7 @@
fileFormatVersion: 2
guid: 05ed7c0e6b34f45eda08039368ae8c87
-timeCreated: 1508167068
-licenseType: Free
MonoImporter:
+ externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
diff --git a/Assets/Zapic/Examples.meta b/Assets/Zapic/Examples.meta
index 8cb8a85..e38f40c 100644
--- a/Assets/Zapic/Examples.meta
+++ b/Assets/Zapic/Examples.meta
@@ -1,9 +1,8 @@
fileFormatVersion: 2
guid: aa7f4e0a1166b48ca862f6c40eef7894
folderAsset: yes
-timeCreated: 1497548828
-licenseType: Free
DefaultImporter:
+ externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
diff --git a/Assets/Zapic/Examples/MenuDemo.unity.meta b/Assets/Zapic/Examples/MenuDemo.unity.meta
index e56279f..537d0b6 100644
--- a/Assets/Zapic/Examples/MenuDemo.unity.meta
+++ b/Assets/Zapic/Examples/MenuDemo.unity.meta
@@ -1,8 +1,7 @@
fileFormatVersion: 2
guid: f3ced3faf0ca343d08cc238f50cdf410
-timeCreated: 1497552965
-licenseType: Free
DefaultImporter:
+ externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
diff --git a/Assets/Zapic/Examples/ZapicButton.cs b/Assets/Zapic/Examples/ZapicButton.cs
index facaa3a..0d899e0 100644
--- a/Assets/Zapic/Examples/ZapicButton.cs
+++ b/Assets/Zapic/Examples/ZapicButton.cs
@@ -1,14 +1,11 @@
-using System.Collections;
-using System.Collections.Generic;
-using UnityEngine;
+using UnityEngine;
using UnityEngine.UI;
public class ZapicButton : MonoBehaviour
{
private void Awake()
{
- var button = this.GetComponent