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