| @@ -0,0 +1,109 @@ | |||||
| <?xml version="1.0" encoding="UTF-8"?> | |||||
| <JUCERPROJECT id="Z3D0EG" name="AnalyticsCollection" displaySplashScreen="0" | |||||
| reportAppUsage="0" splashScreenColour="Dark" projectType="guiapp" | |||||
| version="1.0.0" bundleIdentifier="com.yourcompany.AnalyticsCollection" | |||||
| includeBinaryInAppConfig="1" cppLanguageStandard="11" companyCopyright="" | |||||
| jucerVersion="5.1.2"> | |||||
| <MAINGROUP id="aOi9Tf" name="AnalyticsCollection"> | |||||
| <GROUP id="{527B2E17-B1B1-B919-CBEA-231058E23D74}" name="Source"> | |||||
| <FILE id="qTLkDX" name="GoogleAnalyticsDestination.h" compile="0" resource="0" | |||||
| file="Source/GoogleAnalyticsDestination.h"/> | |||||
| <FILE id="DHs1bY" name="MainComponent.h" compile="0" resource="0" file="Source/MainComponent.h"/> | |||||
| <FILE id="dsUiEq" name="Main.cpp" compile="1" resource="0" file="Source/Main.cpp"/> | |||||
| </GROUP> | |||||
| </MAINGROUP> | |||||
| <EXPORTFORMATS> | |||||
| <XCODE_MAC targetFolder="Builds/MacOSX"> | |||||
| <CONFIGURATIONS> | |||||
| <CONFIGURATION name="Debug" isDebug="1" optimisation="1" targetName="AnalyticsCollection" | |||||
| enablePluginBinaryCopyStep="1"/> | |||||
| <CONFIGURATION name="Release" isDebug="0" optimisation="3" targetName="AnalyticsCollection" | |||||
| enablePluginBinaryCopyStep="1"/> | |||||
| </CONFIGURATIONS> | |||||
| <MODULEPATHS> | |||||
| <MODULEPATH id="juce_core" path="../../modules"/> | |||||
| <MODULEPATH id="juce_events" path="../../modules"/> | |||||
| <MODULEPATH id="juce_graphics" path="../../modules"/> | |||||
| <MODULEPATH id="juce_data_structures" path="../../modules"/> | |||||
| <MODULEPATH id="juce_gui_basics" path="../../modules"/> | |||||
| <MODULEPATH id="juce_analytics" path="../../modules"/> | |||||
| </MODULEPATHS> | |||||
| </XCODE_MAC> | |||||
| <XCODE_IPHONE targetFolder="Builds/iOS" iosScreenOrientation="portraitlandscape" | |||||
| iosDeviceFamily="1,2" iPadScreenOrientation="portraitlandscape"> | |||||
| <CONFIGURATIONS> | |||||
| <CONFIGURATION name="Debug" isDebug="1" optimisation="1" targetName="AnalyticsCollection" | |||||
| enablePluginBinaryCopyStep="1"/> | |||||
| <CONFIGURATION name="Release" isDebug="0" optimisation="3" targetName="AnalyticsCollection" | |||||
| enablePluginBinaryCopyStep="1"/> | |||||
| </CONFIGURATIONS> | |||||
| <MODULEPATHS> | |||||
| <MODULEPATH id="juce_core" path="../../modules"/> | |||||
| <MODULEPATH id="juce_events" path="../../modules"/> | |||||
| <MODULEPATH id="juce_graphics" path="../../modules"/> | |||||
| <MODULEPATH id="juce_data_structures" path="../../modules"/> | |||||
| <MODULEPATH id="juce_gui_basics" path="../../modules"/> | |||||
| <MODULEPATH id="juce_analytics" path="../../modules"/> | |||||
| </MODULEPATHS> | |||||
| </XCODE_IPHONE> | |||||
| <VS2017 targetFolder="Builds/VisualStudio2017"> | |||||
| <CONFIGURATIONS> | |||||
| <CONFIGURATION name="Debug" winWarningLevel="4" generateManifest="1" winArchitecture="x64" | |||||
| isDebug="1" optimisation="1" targetName="AnalyticsCollection" | |||||
| debugInformationFormat="ProgramDatabase" enablePluginBinaryCopyStep="0"/> | |||||
| <CONFIGURATION name="Release" winWarningLevel="4" generateManifest="1" winArchitecture="x64" | |||||
| isDebug="0" optimisation="3" targetName="AnalyticsCollection" | |||||
| debugInformationFormat="None" enablePluginBinaryCopyStep="0" | |||||
| linkTimeOptimisation="1"/> | |||||
| </CONFIGURATIONS> | |||||
| <MODULEPATHS> | |||||
| <MODULEPATH id="juce_core" path="../../modules"/> | |||||
| <MODULEPATH id="juce_events" path="../../modules"/> | |||||
| <MODULEPATH id="juce_graphics" path="../../modules"/> | |||||
| <MODULEPATH id="juce_data_structures" path="../../modules"/> | |||||
| <MODULEPATH id="juce_gui_basics" path="../../modules"/> | |||||
| <MODULEPATH id="juce_analytics" path="../../modules"/> | |||||
| </MODULEPATHS> | |||||
| </VS2017> | |||||
| <LINUX_MAKE targetFolder="Builds/LinuxMakefile" extraDefs="JUCE_USE_CURL=1"> | |||||
| <CONFIGURATIONS> | |||||
| <CONFIGURATION name="Debug" isDebug="1" optimisation="1" targetName="AnalyticsCollection"/> | |||||
| <CONFIGURATION name="Release" isDebug="0" optimisation="3" targetName="AnalyticsCollection"/> | |||||
| </CONFIGURATIONS> | |||||
| <MODULEPATHS> | |||||
| <MODULEPATH id="juce_core" path="../../modules"/> | |||||
| <MODULEPATH id="juce_events" path="../../modules"/> | |||||
| <MODULEPATH id="juce_graphics" path="../../modules"/> | |||||
| <MODULEPATH id="juce_data_structures" path="../../modules"/> | |||||
| <MODULEPATH id="juce_gui_basics" path="../../modules"/> | |||||
| <MODULEPATH id="juce_analytics" path="../../modules"/> | |||||
| </MODULEPATHS> | |||||
| </LINUX_MAKE> | |||||
| <ANDROIDSTUDIO targetFolder="Builds/Android"> | |||||
| <CONFIGURATIONS> | |||||
| <CONFIGURATION name="Debug" androidArchitectures="armeabi x86" isDebug="1" optimisation="1" | |||||
| targetName="AnalyticsCollection"/> | |||||
| <CONFIGURATION name="Release" androidArchitectures="" isDebug="0" optimisation="3" | |||||
| targetName="AnalyticsCollection"/> | |||||
| </CONFIGURATIONS> | |||||
| <MODULEPATHS> | |||||
| <MODULEPATH id="juce_core" path="../../modules"/> | |||||
| <MODULEPATH id="juce_events" path="../../modules"/> | |||||
| <MODULEPATH id="juce_graphics" path="../../modules"/> | |||||
| <MODULEPATH id="juce_data_structures" path="../../modules"/> | |||||
| <MODULEPATH id="juce_gui_basics" path="../../modules"/> | |||||
| <MODULEPATH id="juce_analytics" path="../../modules"/> | |||||
| </MODULEPATHS> | |||||
| </ANDROIDSTUDIO> | |||||
| </EXPORTFORMATS> | |||||
| <MODULES> | |||||
| <MODULE id="juce_analytics" showAllCode="1" useLocalCopy="0" useGlobalPath="0"/> | |||||
| <MODULE id="juce_core" showAllCode="1" useLocalCopy="0" useGlobalPath="0"/> | |||||
| <MODULE id="juce_data_structures" showAllCode="1" useLocalCopy="0" useGlobalPath="0"/> | |||||
| <MODULE id="juce_events" showAllCode="1" useLocalCopy="0" useGlobalPath="0"/> | |||||
| <MODULE id="juce_graphics" showAllCode="1" useLocalCopy="0" useGlobalPath="0"/> | |||||
| <MODULE id="juce_gui_basics" showAllCode="1" useLocalCopy="0" useGlobalPath="0"/> | |||||
| </MODULES> | |||||
| <JUCEOPTIONS/> | |||||
| </JUCERPROJECT> | |||||
| @@ -0,0 +1,89 @@ | |||||
| apply plugin: 'com.android.application' | |||||
| android { | |||||
| compileSdkVersion 10 | |||||
| buildToolsVersion "26.0.0" | |||||
| externalNativeBuild { | |||||
| cmake { | |||||
| path "CMakeLists.txt" | |||||
| } | |||||
| } | |||||
| signingConfigs { | |||||
| juceSigning { | |||||
| storeFile file("${System.properties['user.home']}${File.separator}.android${File.separator}debug.keystore") | |||||
| storePassword "android" | |||||
| keyAlias "androiddebugkey" | |||||
| keyPassword "android" | |||||
| storeType "jks" | |||||
| } | |||||
| } | |||||
| defaultConfig { | |||||
| applicationId "com.yourcompany.analyticscollection" | |||||
| minSdkVersion 10 | |||||
| targetSdkVersion 10 | |||||
| externalNativeBuild { | |||||
| cmake { | |||||
| arguments "-DANDROID_TOOLCHAIN=clang", "-DANDROID_PLATFORM=android-10", "-DANDROID_STL=c++_static", "-DANDROID_CPP_FEATURES=exceptions rtti", "-DANDROID_ARM_MODE=arm", "-DANDROID_ARM_NEON=TRUE" | |||||
| cFlags "-fsigned-char" | |||||
| cppFlags "-fsigned-char", "-std=c++11" | |||||
| } | |||||
| } | |||||
| } | |||||
| buildTypes { | |||||
| debug { | |||||
| initWith debug | |||||
| debuggable true | |||||
| jniDebuggable true | |||||
| signingConfig signingConfigs.juceSigning | |||||
| } | |||||
| release { | |||||
| initWith release | |||||
| debuggable false | |||||
| jniDebuggable false | |||||
| signingConfig signingConfigs.juceSigning | |||||
| } | |||||
| } | |||||
| productFlavors { | |||||
| debug_ { | |||||
| ndk { | |||||
| abiFilters "armeabi", "x86" | |||||
| } | |||||
| externalNativeBuild { | |||||
| cmake { | |||||
| arguments "-DJUCE_BUILD_CONFIGFURATION=DEBUG", "-DCMAKE_CXX_FLAGS_DEBUG=-O0", "-DCMAKE_C_FLAGS_DEBUG=-O0" | |||||
| } | |||||
| } | |||||
| } | |||||
| release_ { | |||||
| externalNativeBuild { | |||||
| cmake { | |||||
| arguments "-DJUCE_BUILD_CONFIGFURATION=RELEASE", "-DCMAKE_CXX_FLAGS_RELEASE=-O3", "-DCMAKE_C_FLAGS_RELEASE=-O3" | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| variantFilter { variant -> | |||||
| def names = variant.flavors*.name | |||||
| if (names.contains ("debug_") | |||||
| && variant.buildType.name != "debug") { | |||||
| setIgnore(true) | |||||
| } | |||||
| if (names.contains ("release_") | |||||
| && variant.buildType.name != "release") { | |||||
| setIgnore(true) | |||||
| } | |||||
| } | |||||
| repositories { | |||||
| } | |||||
| dependencies { | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,5 @@ | |||||
| <?xml version="1.0" encoding="utf-8"?> | |||||
| <resources> | |||||
| <string name="app_name">AnalyticsCollection</string> | |||||
| </resources> | |||||
| @@ -0,0 +1,22 @@ | |||||
| <?xml version="1.0" encoding="utf-8"?> | |||||
| <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0.0" | |||||
| package="com.yourcompany.analyticscollection"> | |||||
| <supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:anyDensity="true"/> | |||||
| <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="10"/> | |||||
| <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> | |||||
| <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> | |||||
| <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> | |||||
| <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> | |||||
| <uses-permission android:name="android.permission.BLUETOOTH"/> | |||||
| <uses-permission android:name="android.permission.INTERNET"/> | |||||
| <application android:label="@string/app_name"> | |||||
| <activity android:name="AnalyticsCollection" android:label="@string/app_name" android:configChanges="keyboardHidden|orientation" | |||||
| android:screenOrientation="unspecified" android:launchMode="singleTask"> | |||||
| <intent-filter> | |||||
| <action android:name="android.intent.action.MAIN"/> | |||||
| <category android:name="android.intent.category.LAUNCHER"/> | |||||
| </intent-filter> | |||||
| </activity> | |||||
| </application> | |||||
| </manifest> | |||||
| @@ -0,0 +1,971 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library. | |||||
| Copyright (c) 2017 - ROLI Ltd. | |||||
| JUCE is an open source library subject to commercial or open-source | |||||
| licensing. | |||||
| The code included in this file is provided under the terms of the ISC license | |||||
| http://www.isc.org/downloads/software-support-policy/isc-license. Permission | |||||
| To use, copy, modify, and/or distribute this software for any purpose with or | |||||
| without fee is hereby granted provided that the above copyright notice and | |||||
| this permission notice appear in all copies. | |||||
| JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | |||||
| EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | |||||
| DISCLAIMED. | |||||
| ============================================================================== | |||||
| */ | |||||
| package com.android.vending.billing; | |||||
| /** | |||||
| * InAppBillingService is the service that provides in-app billing version 3 and beyond. | |||||
| * This service provides the following features: | |||||
| * 1. Provides a new API to get details of in-app items published for the app including | |||||
| * price, type, title and description. | |||||
| * 2. The purchase flow is synchronous and purchase information is available immediately | |||||
| * after it completes. | |||||
| * 3. Purchase information of in-app purchases is maintained within the Google Play system | |||||
| * till the purchase is consumed. | |||||
| * 4. An API to consume a purchase of an inapp item. All purchases of one-time | |||||
| * in-app items are consumable and thereafter can be purchased again. | |||||
| * 5. An API to get current purchases of the user immediately. This will not contain any | |||||
| * consumed purchases. | |||||
| * | |||||
| * All calls will give a response code with the following possible values | |||||
| * RESULT_OK = 0 - success | |||||
| * RESULT_USER_CANCELED = 1 - User pressed back or canceled a dialog | |||||
| * RESULT_SERVICE_UNAVAILABLE = 2 - The network connection is down | |||||
| * RESULT_BILLING_UNAVAILABLE = 3 - This billing API version is not supported for the type requested | |||||
| * RESULT_ITEM_UNAVAILABLE = 4 - Requested SKU is not available for purchase | |||||
| * RESULT_DEVELOPER_ERROR = 5 - Invalid arguments provided to the API | |||||
| * RESULT_ERROR = 6 - Fatal error during the API action | |||||
| * RESULT_ITEM_ALREADY_OWNED = 7 - Failure to purchase since item is already owned | |||||
| * RESULT_ITEM_NOT_OWNED = 8 - Failure to consume since item is not owned | |||||
| */ | |||||
| public interface IInAppBillingService extends android.os.IInterface | |||||
| { | |||||
| /** Local-side IPC implementation stub class. */ | |||||
| public static abstract class Stub extends android.os.Binder implements com.android.vending.billing.IInAppBillingService | |||||
| { | |||||
| private static final java.lang.String DESCRIPTOR = "com.android.vending.billing.IInAppBillingService"; | |||||
| /** Construct the stub at attach it to the interface. */ | |||||
| public Stub() | |||||
| { | |||||
| this.attachInterface(this, DESCRIPTOR); | |||||
| } | |||||
| /** | |||||
| * Cast an IBinder object into an com.android.vending.billing.IInAppBillingService interface, | |||||
| * generating a proxy if needed. | |||||
| */ | |||||
| public static com.android.vending.billing.IInAppBillingService asInterface(android.os.IBinder obj) | |||||
| { | |||||
| if ((obj==null)) { | |||||
| return null; | |||||
| } | |||||
| android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); | |||||
| if (((iin!=null)&&(iin instanceof com.android.vending.billing.IInAppBillingService))) { | |||||
| return ((com.android.vending.billing.IInAppBillingService)iin); | |||||
| } | |||||
| return new com.android.vending.billing.IInAppBillingService.Stub.Proxy(obj); | |||||
| } | |||||
| @Override public android.os.IBinder asBinder() | |||||
| { | |||||
| return this; | |||||
| } | |||||
| @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException | |||||
| { | |||||
| switch (code) | |||||
| { | |||||
| case INTERFACE_TRANSACTION: | |||||
| { | |||||
| reply.writeString(DESCRIPTOR); | |||||
| return true; | |||||
| } | |||||
| case TRANSACTION_isBillingSupported: | |||||
| { | |||||
| data.enforceInterface(DESCRIPTOR); | |||||
| int _arg0; | |||||
| _arg0 = data.readInt(); | |||||
| java.lang.String _arg1; | |||||
| _arg1 = data.readString(); | |||||
| java.lang.String _arg2; | |||||
| _arg2 = data.readString(); | |||||
| int _result = this.isBillingSupported(_arg0, _arg1, _arg2); | |||||
| reply.writeNoException(); | |||||
| reply.writeInt(_result); | |||||
| return true; | |||||
| } | |||||
| case TRANSACTION_getSkuDetails: | |||||
| { | |||||
| data.enforceInterface(DESCRIPTOR); | |||||
| int _arg0; | |||||
| _arg0 = data.readInt(); | |||||
| java.lang.String _arg1; | |||||
| _arg1 = data.readString(); | |||||
| java.lang.String _arg2; | |||||
| _arg2 = data.readString(); | |||||
| android.os.Bundle _arg3; | |||||
| if ((0!=data.readInt())) { | |||||
| _arg3 = android.os.Bundle.CREATOR.createFromParcel(data); | |||||
| } | |||||
| else { | |||||
| _arg3 = null; | |||||
| } | |||||
| android.os.Bundle _result = this.getSkuDetails(_arg0, _arg1, _arg2, _arg3); | |||||
| reply.writeNoException(); | |||||
| if ((_result!=null)) { | |||||
| reply.writeInt(1); | |||||
| _result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE); | |||||
| } | |||||
| else { | |||||
| reply.writeInt(0); | |||||
| } | |||||
| return true; | |||||
| } | |||||
| case TRANSACTION_getBuyIntent: | |||||
| { | |||||
| data.enforceInterface(DESCRIPTOR); | |||||
| int _arg0; | |||||
| _arg0 = data.readInt(); | |||||
| java.lang.String _arg1; | |||||
| _arg1 = data.readString(); | |||||
| java.lang.String _arg2; | |||||
| _arg2 = data.readString(); | |||||
| java.lang.String _arg3; | |||||
| _arg3 = data.readString(); | |||||
| java.lang.String _arg4; | |||||
| _arg4 = data.readString(); | |||||
| android.os.Bundle _result = this.getBuyIntent(_arg0, _arg1, _arg2, _arg3, _arg4); | |||||
| reply.writeNoException(); | |||||
| if ((_result!=null)) { | |||||
| reply.writeInt(1); | |||||
| _result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE); | |||||
| } | |||||
| else { | |||||
| reply.writeInt(0); | |||||
| } | |||||
| return true; | |||||
| } | |||||
| case TRANSACTION_getPurchases: | |||||
| { | |||||
| data.enforceInterface(DESCRIPTOR); | |||||
| int _arg0; | |||||
| _arg0 = data.readInt(); | |||||
| java.lang.String _arg1; | |||||
| _arg1 = data.readString(); | |||||
| java.lang.String _arg2; | |||||
| _arg2 = data.readString(); | |||||
| java.lang.String _arg3; | |||||
| _arg3 = data.readString(); | |||||
| android.os.Bundle _result = this.getPurchases(_arg0, _arg1, _arg2, _arg3); | |||||
| reply.writeNoException(); | |||||
| if ((_result!=null)) { | |||||
| reply.writeInt(1); | |||||
| _result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE); | |||||
| } | |||||
| else { | |||||
| reply.writeInt(0); | |||||
| } | |||||
| return true; | |||||
| } | |||||
| case TRANSACTION_consumePurchase: | |||||
| { | |||||
| data.enforceInterface(DESCRIPTOR); | |||||
| int _arg0; | |||||
| _arg0 = data.readInt(); | |||||
| java.lang.String _arg1; | |||||
| _arg1 = data.readString(); | |||||
| java.lang.String _arg2; | |||||
| _arg2 = data.readString(); | |||||
| int _result = this.consumePurchase(_arg0, _arg1, _arg2); | |||||
| reply.writeNoException(); | |||||
| reply.writeInt(_result); | |||||
| return true; | |||||
| } | |||||
| case TRANSACTION_stub: | |||||
| { | |||||
| data.enforceInterface(DESCRIPTOR); | |||||
| int _arg0; | |||||
| _arg0 = data.readInt(); | |||||
| java.lang.String _arg1; | |||||
| _arg1 = data.readString(); | |||||
| java.lang.String _arg2; | |||||
| _arg2 = data.readString(); | |||||
| int _result = this.stub(_arg0, _arg1, _arg2); | |||||
| reply.writeNoException(); | |||||
| reply.writeInt(_result); | |||||
| return true; | |||||
| } | |||||
| case TRANSACTION_getBuyIntentToReplaceSkus: | |||||
| { | |||||
| data.enforceInterface(DESCRIPTOR); | |||||
| int _arg0; | |||||
| _arg0 = data.readInt(); | |||||
| java.lang.String _arg1; | |||||
| _arg1 = data.readString(); | |||||
| java.util.List<java.lang.String> _arg2; | |||||
| _arg2 = data.createStringArrayList(); | |||||
| java.lang.String _arg3; | |||||
| _arg3 = data.readString(); | |||||
| java.lang.String _arg4; | |||||
| _arg4 = data.readString(); | |||||
| java.lang.String _arg5; | |||||
| _arg5 = data.readString(); | |||||
| android.os.Bundle _result = this.getBuyIntentToReplaceSkus(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5); | |||||
| reply.writeNoException(); | |||||
| if ((_result!=null)) { | |||||
| reply.writeInt(1); | |||||
| _result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE); | |||||
| } | |||||
| else { | |||||
| reply.writeInt(0); | |||||
| } | |||||
| return true; | |||||
| } | |||||
| case TRANSACTION_getBuyIntentExtraParams: | |||||
| { | |||||
| data.enforceInterface(DESCRIPTOR); | |||||
| int _arg0; | |||||
| _arg0 = data.readInt(); | |||||
| java.lang.String _arg1; | |||||
| _arg1 = data.readString(); | |||||
| java.lang.String _arg2; | |||||
| _arg2 = data.readString(); | |||||
| java.lang.String _arg3; | |||||
| _arg3 = data.readString(); | |||||
| java.lang.String _arg4; | |||||
| _arg4 = data.readString(); | |||||
| android.os.Bundle _arg5; | |||||
| if ((0!=data.readInt())) { | |||||
| _arg5 = android.os.Bundle.CREATOR.createFromParcel(data); | |||||
| } | |||||
| else { | |||||
| _arg5 = null; | |||||
| } | |||||
| android.os.Bundle _result = this.getBuyIntentExtraParams(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5); | |||||
| reply.writeNoException(); | |||||
| if ((_result!=null)) { | |||||
| reply.writeInt(1); | |||||
| _result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE); | |||||
| } | |||||
| else { | |||||
| reply.writeInt(0); | |||||
| } | |||||
| return true; | |||||
| } | |||||
| case TRANSACTION_getPurchaseHistory: | |||||
| { | |||||
| data.enforceInterface(DESCRIPTOR); | |||||
| int _arg0; | |||||
| _arg0 = data.readInt(); | |||||
| java.lang.String _arg1; | |||||
| _arg1 = data.readString(); | |||||
| java.lang.String _arg2; | |||||
| _arg2 = data.readString(); | |||||
| java.lang.String _arg3; | |||||
| _arg3 = data.readString(); | |||||
| android.os.Bundle _arg4; | |||||
| if ((0!=data.readInt())) { | |||||
| _arg4 = android.os.Bundle.CREATOR.createFromParcel(data); | |||||
| } | |||||
| else { | |||||
| _arg4 = null; | |||||
| } | |||||
| android.os.Bundle _result = this.getPurchaseHistory(_arg0, _arg1, _arg2, _arg3, _arg4); | |||||
| reply.writeNoException(); | |||||
| if ((_result!=null)) { | |||||
| reply.writeInt(1); | |||||
| _result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE); | |||||
| } | |||||
| else { | |||||
| reply.writeInt(0); | |||||
| } | |||||
| return true; | |||||
| } | |||||
| case TRANSACTION_isBillingSupportedExtraParams: | |||||
| { | |||||
| data.enforceInterface(DESCRIPTOR); | |||||
| int _arg0; | |||||
| _arg0 = data.readInt(); | |||||
| java.lang.String _arg1; | |||||
| _arg1 = data.readString(); | |||||
| java.lang.String _arg2; | |||||
| _arg2 = data.readString(); | |||||
| android.os.Bundle _arg3; | |||||
| if ((0!=data.readInt())) { | |||||
| _arg3 = android.os.Bundle.CREATOR.createFromParcel(data); | |||||
| } | |||||
| else { | |||||
| _arg3 = null; | |||||
| } | |||||
| int _result = this.isBillingSupportedExtraParams(_arg0, _arg1, _arg2, _arg3); | |||||
| reply.writeNoException(); | |||||
| reply.writeInt(_result); | |||||
| return true; | |||||
| } | |||||
| } | |||||
| return super.onTransact(code, data, reply, flags); | |||||
| } | |||||
| private static class Proxy implements com.android.vending.billing.IInAppBillingService | |||||
| { | |||||
| private android.os.IBinder mRemote; | |||||
| Proxy(android.os.IBinder remote) | |||||
| { | |||||
| mRemote = remote; | |||||
| } | |||||
| @Override public android.os.IBinder asBinder() | |||||
| { | |||||
| return mRemote; | |||||
| } | |||||
| public java.lang.String getInterfaceDescriptor() | |||||
| { | |||||
| return DESCRIPTOR; | |||||
| } | |||||
| @Override public int isBillingSupported(int apiVersion, java.lang.String packageName, java.lang.String type) throws android.os.RemoteException | |||||
| { | |||||
| android.os.Parcel _data = android.os.Parcel.obtain(); | |||||
| android.os.Parcel _reply = android.os.Parcel.obtain(); | |||||
| int _result; | |||||
| try { | |||||
| _data.writeInterfaceToken(DESCRIPTOR); | |||||
| _data.writeInt(apiVersion); | |||||
| _data.writeString(packageName); | |||||
| _data.writeString(type); | |||||
| mRemote.transact(Stub.TRANSACTION_isBillingSupported, _data, _reply, 0); | |||||
| _reply.readException(); | |||||
| _result = _reply.readInt(); | |||||
| } | |||||
| finally { | |||||
| _reply.recycle(); | |||||
| _data.recycle(); | |||||
| } | |||||
| return _result; | |||||
| } | |||||
| /** | |||||
| * Provides details of a list of SKUs | |||||
| * Given a list of SKUs of a valid type in the skusBundle, this returns a bundle | |||||
| * with a list JSON strings containing the productId, price, title and description. | |||||
| * This API can be called with a maximum of 20 SKUs. | |||||
| * @param apiVersion billing API version that the app is using | |||||
| * @param packageName the package name of the calling app | |||||
| * @param type of the in-app items ("inapp" for one-time purchases | |||||
| * and "subs" for subscriptions) | |||||
| * @param skusBundle bundle containing a StringArrayList of SKUs with key "ITEM_ID_LIST" | |||||
| * @return Bundle containing the following key-value pairs | |||||
| * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, appropriate response codes | |||||
| * on failures. | |||||
| * "DETAILS_LIST" with a StringArrayList containing purchase information | |||||
| * in JSON format similar to: | |||||
| * '{ "productId" : "exampleSku", | |||||
| * "type" : "inapp", | |||||
| * "price" : "$5.00", | |||||
| * "price_currency": "USD", | |||||
| * "price_amount_micros": 5000000, | |||||
| * "title : "Example Title", | |||||
| * "description" : "This is an example description" }' | |||||
| */ | |||||
| @Override public android.os.Bundle getSkuDetails(int apiVersion, java.lang.String packageName, java.lang.String type, android.os.Bundle skusBundle) throws android.os.RemoteException | |||||
| { | |||||
| android.os.Parcel _data = android.os.Parcel.obtain(); | |||||
| android.os.Parcel _reply = android.os.Parcel.obtain(); | |||||
| android.os.Bundle _result; | |||||
| try { | |||||
| _data.writeInterfaceToken(DESCRIPTOR); | |||||
| _data.writeInt(apiVersion); | |||||
| _data.writeString(packageName); | |||||
| _data.writeString(type); | |||||
| if ((skusBundle!=null)) { | |||||
| _data.writeInt(1); | |||||
| skusBundle.writeToParcel(_data, 0); | |||||
| } | |||||
| else { | |||||
| _data.writeInt(0); | |||||
| } | |||||
| mRemote.transact(Stub.TRANSACTION_getSkuDetails, _data, _reply, 0); | |||||
| _reply.readException(); | |||||
| if ((0!=_reply.readInt())) { | |||||
| _result = android.os.Bundle.CREATOR.createFromParcel(_reply); | |||||
| } | |||||
| else { | |||||
| _result = null; | |||||
| } | |||||
| } | |||||
| finally { | |||||
| _reply.recycle(); | |||||
| _data.recycle(); | |||||
| } | |||||
| return _result; | |||||
| } | |||||
| /** | |||||
| * Returns a pending intent to launch the purchase flow for an in-app item by providing a SKU, | |||||
| * the type, a unique purchase token and an optional developer payload. | |||||
| * @param apiVersion billing API version that the app is using | |||||
| * @param packageName package name of the calling app | |||||
| * @param sku the SKU of the in-app item as published in the developer console | |||||
| * @param type of the in-app item being purchased ("inapp" for one-time purchases | |||||
| * and "subs" for subscriptions) | |||||
| * @param developerPayload optional argument to be sent back with the purchase information | |||||
| * @return Bundle containing the following key-value pairs | |||||
| * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, appropriate response codes | |||||
| * on failures. | |||||
| * "BUY_INTENT" - PendingIntent to start the purchase flow | |||||
| * | |||||
| * The Pending intent should be launched with startIntentSenderForResult. When purchase flow | |||||
| * has completed, the onActivityResult() will give a resultCode of OK or CANCELED. | |||||
| * If the purchase is successful, the result data will contain the following key-value pairs | |||||
| * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, appropriate response | |||||
| * codes on failures. | |||||
| * "INAPP_PURCHASE_DATA" - String in JSON format similar to | |||||
| * '{"orderId":"12999763169054705758.1371079406387615", | |||||
| * "packageName":"com.example.app", | |||||
| * "productId":"exampleSku", | |||||
| * "purchaseTime":1345678900000, | |||||
| * "purchaseToken" : "122333444455555", | |||||
| * "developerPayload":"example developer payload" }' | |||||
| * "INAPP_DATA_SIGNATURE" - String containing the signature of the purchase data that | |||||
| * was signed with the private key of the developer | |||||
| */ | |||||
| @Override public android.os.Bundle getBuyIntent(int apiVersion, java.lang.String packageName, java.lang.String sku, java.lang.String type, java.lang.String developerPayload) throws android.os.RemoteException | |||||
| { | |||||
| android.os.Parcel _data = android.os.Parcel.obtain(); | |||||
| android.os.Parcel _reply = android.os.Parcel.obtain(); | |||||
| android.os.Bundle _result; | |||||
| try { | |||||
| _data.writeInterfaceToken(DESCRIPTOR); | |||||
| _data.writeInt(apiVersion); | |||||
| _data.writeString(packageName); | |||||
| _data.writeString(sku); | |||||
| _data.writeString(type); | |||||
| _data.writeString(developerPayload); | |||||
| mRemote.transact(Stub.TRANSACTION_getBuyIntent, _data, _reply, 0); | |||||
| _reply.readException(); | |||||
| if ((0!=_reply.readInt())) { | |||||
| _result = android.os.Bundle.CREATOR.createFromParcel(_reply); | |||||
| } | |||||
| else { | |||||
| _result = null; | |||||
| } | |||||
| } | |||||
| finally { | |||||
| _reply.recycle(); | |||||
| _data.recycle(); | |||||
| } | |||||
| return _result; | |||||
| } | |||||
| /** | |||||
| * Returns the current SKUs owned by the user of the type and package name specified along with | |||||
| * purchase information and a signature of the data to be validated. | |||||
| * This will return all SKUs that have been purchased in V3 and managed items purchased using | |||||
| * V1 and V2 that have not been consumed. | |||||
| * @param apiVersion billing API version that the app is using | |||||
| * @param packageName package name of the calling app | |||||
| * @param type of the in-app items being requested ("inapp" for one-time purchases | |||||
| * and "subs" for subscriptions) | |||||
| * @param continuationToken to be set as null for the first call, if the number of owned | |||||
| * skus are too many, a continuationToken is returned in the response bundle. | |||||
| * This method can be called again with the continuation token to get the next set of | |||||
| * owned skus. | |||||
| * @return Bundle containing the following key-value pairs | |||||
| * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, appropriate response codes | |||||
| on failures. | |||||
| * "INAPP_PURCHASE_ITEM_LIST" - StringArrayList containing the list of SKUs | |||||
| * "INAPP_PURCHASE_DATA_LIST" - StringArrayList containing the purchase information | |||||
| * "INAPP_DATA_SIGNATURE_LIST"- StringArrayList containing the signatures | |||||
| * of the purchase information | |||||
| * "INAPP_CONTINUATION_TOKEN" - String containing a continuation token for the | |||||
| * next set of in-app purchases. Only set if the | |||||
| * user has more owned skus than the current list. | |||||
| */ | |||||
| @Override public android.os.Bundle getPurchases(int apiVersion, java.lang.String packageName, java.lang.String type, java.lang.String continuationToken) throws android.os.RemoteException | |||||
| { | |||||
| android.os.Parcel _data = android.os.Parcel.obtain(); | |||||
| android.os.Parcel _reply = android.os.Parcel.obtain(); | |||||
| android.os.Bundle _result; | |||||
| try { | |||||
| _data.writeInterfaceToken(DESCRIPTOR); | |||||
| _data.writeInt(apiVersion); | |||||
| _data.writeString(packageName); | |||||
| _data.writeString(type); | |||||
| _data.writeString(continuationToken); | |||||
| mRemote.transact(Stub.TRANSACTION_getPurchases, _data, _reply, 0); | |||||
| _reply.readException(); | |||||
| if ((0!=_reply.readInt())) { | |||||
| _result = android.os.Bundle.CREATOR.createFromParcel(_reply); | |||||
| } | |||||
| else { | |||||
| _result = null; | |||||
| } | |||||
| } | |||||
| finally { | |||||
| _reply.recycle(); | |||||
| _data.recycle(); | |||||
| } | |||||
| return _result; | |||||
| } | |||||
| @Override public int consumePurchase(int apiVersion, java.lang.String packageName, java.lang.String purchaseToken) throws android.os.RemoteException | |||||
| { | |||||
| android.os.Parcel _data = android.os.Parcel.obtain(); | |||||
| android.os.Parcel _reply = android.os.Parcel.obtain(); | |||||
| int _result; | |||||
| try { | |||||
| _data.writeInterfaceToken(DESCRIPTOR); | |||||
| _data.writeInt(apiVersion); | |||||
| _data.writeString(packageName); | |||||
| _data.writeString(purchaseToken); | |||||
| mRemote.transact(Stub.TRANSACTION_consumePurchase, _data, _reply, 0); | |||||
| _reply.readException(); | |||||
| _result = _reply.readInt(); | |||||
| } | |||||
| finally { | |||||
| _reply.recycle(); | |||||
| _data.recycle(); | |||||
| } | |||||
| return _result; | |||||
| } | |||||
| @Override public int stub(int apiVersion, java.lang.String packageName, java.lang.String type) throws android.os.RemoteException | |||||
| { | |||||
| android.os.Parcel _data = android.os.Parcel.obtain(); | |||||
| android.os.Parcel _reply = android.os.Parcel.obtain(); | |||||
| int _result; | |||||
| try { | |||||
| _data.writeInterfaceToken(DESCRIPTOR); | |||||
| _data.writeInt(apiVersion); | |||||
| _data.writeString(packageName); | |||||
| _data.writeString(type); | |||||
| mRemote.transact(Stub.TRANSACTION_stub, _data, _reply, 0); | |||||
| _reply.readException(); | |||||
| _result = _reply.readInt(); | |||||
| } | |||||
| finally { | |||||
| _reply.recycle(); | |||||
| _data.recycle(); | |||||
| } | |||||
| return _result; | |||||
| } | |||||
| /** | |||||
| * Returns a pending intent to launch the purchase flow for upgrading or downgrading a | |||||
| * subscription. The existing owned SKU(s) should be provided along with the new SKU that | |||||
| * the user is upgrading or downgrading to. | |||||
| * @param apiVersion billing API version that the app is using, must be 5 or later | |||||
| * @param packageName package name of the calling app | |||||
| * @param oldSkus the SKU(s) that the user is upgrading or downgrading from, | |||||
| * if null or empty this method will behave like {@link #getBuyIntent} | |||||
| * @param newSku the SKU that the user is upgrading or downgrading to | |||||
| * @param type of the item being purchased, currently must be "subs" | |||||
| * @param developerPayload optional argument to be sent back with the purchase information | |||||
| * @return Bundle containing the following key-value pairs | |||||
| * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, appropriate response codes | |||||
| * on failures. | |||||
| * "BUY_INTENT" - PendingIntent to start the purchase flow | |||||
| * | |||||
| * The Pending intent should be launched with startIntentSenderForResult. When purchase flow | |||||
| * has completed, the onActivityResult() will give a resultCode of OK or CANCELED. | |||||
| * If the purchase is successful, the result data will contain the following key-value pairs | |||||
| * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, appropriate response | |||||
| * codes on failures. | |||||
| * "INAPP_PURCHASE_DATA" - String in JSON format similar to | |||||
| * '{"orderId":"12999763169054705758.1371079406387615", | |||||
| * "packageName":"com.example.app", | |||||
| * "productId":"exampleSku", | |||||
| * "purchaseTime":1345678900000, | |||||
| * "purchaseToken" : "122333444455555", | |||||
| * "developerPayload":"example developer payload" }' | |||||
| * "INAPP_DATA_SIGNATURE" - String containing the signature of the purchase data that | |||||
| * was signed with the private key of the developer | |||||
| */ | |||||
| @Override public android.os.Bundle getBuyIntentToReplaceSkus(int apiVersion, java.lang.String packageName, java.util.List<java.lang.String> oldSkus, java.lang.String newSku, java.lang.String type, java.lang.String developerPayload) throws android.os.RemoteException | |||||
| { | |||||
| android.os.Parcel _data = android.os.Parcel.obtain(); | |||||
| android.os.Parcel _reply = android.os.Parcel.obtain(); | |||||
| android.os.Bundle _result; | |||||
| try { | |||||
| _data.writeInterfaceToken(DESCRIPTOR); | |||||
| _data.writeInt(apiVersion); | |||||
| _data.writeString(packageName); | |||||
| _data.writeStringList(oldSkus); | |||||
| _data.writeString(newSku); | |||||
| _data.writeString(type); | |||||
| _data.writeString(developerPayload); | |||||
| mRemote.transact(Stub.TRANSACTION_getBuyIntentToReplaceSkus, _data, _reply, 0); | |||||
| _reply.readException(); | |||||
| if ((0!=_reply.readInt())) { | |||||
| _result = android.os.Bundle.CREATOR.createFromParcel(_reply); | |||||
| } | |||||
| else { | |||||
| _result = null; | |||||
| } | |||||
| } | |||||
| finally { | |||||
| _reply.recycle(); | |||||
| _data.recycle(); | |||||
| } | |||||
| return _result; | |||||
| } | |||||
| /** | |||||
| * Returns a pending intent to launch the purchase flow for an in-app item. This method is | |||||
| * a variant of the {@link #getBuyIntent} method and takes an additional {@code extraParams} | |||||
| * parameter. This parameter is a Bundle of optional keys and values that affect the | |||||
| * operation of the method. | |||||
| * @param apiVersion billing API version that the app is using, must be 6 or later | |||||
| * @param packageName package name of the calling app | |||||
| * @param sku the SKU of the in-app item as published in the developer console | |||||
| * @param type of the in-app item being purchased ("inapp" for one-time purchases | |||||
| * and "subs" for subscriptions) | |||||
| * @param developerPayload optional argument to be sent back with the purchase information | |||||
| * @extraParams a Bundle with the following optional keys: | |||||
| * "skusToReplace" - List<String> - an optional list of SKUs that the user is | |||||
| * upgrading or downgrading from. | |||||
| * Pass this field if the purchase is upgrading or downgrading | |||||
| * existing subscriptions. | |||||
| * The specified SKUs are replaced with the SKUs that the user is | |||||
| * purchasing. Google Play replaces the specified SKUs at the start of | |||||
| * the next billing cycle. | |||||
| * "replaceSkusProration" - Boolean - whether the user should be credited for any unused | |||||
| * subscription time on the SKUs they are upgrading or downgrading. | |||||
| * If you set this field to true, Google Play swaps out the old SKUs | |||||
| * and credits the user with the unused value of their subscription | |||||
| * time on a pro-rated basis. | |||||
| * Google Play applies this credit to the new subscription, and does | |||||
| * not begin billing the user for the new subscription until after | |||||
| * the credit is used up. | |||||
| * If you set this field to false, the user does not receive credit for | |||||
| * any unused subscription time and the recurrence date does not | |||||
| * change. | |||||
| * Default value is true. Ignored if you do not pass skusToReplace. | |||||
| * "accountId" - String - an optional obfuscated string that is uniquely | |||||
| * associated with the user's account in your app. | |||||
| * If you pass this value, Google Play can use it to detect irregular | |||||
| * activity, such as many devices making purchases on the same | |||||
| * account in a short period of time. | |||||
| * Do not use the developer ID or the user's Google ID for this field. | |||||
| * In addition, this field should not contain the user's ID in | |||||
| * cleartext. | |||||
| * We recommend that you use a one-way hash to generate a string from | |||||
| * the user's ID, and store the hashed string in this field. | |||||
| * "vr" - Boolean - an optional flag indicating whether the returned intent | |||||
| * should start a VR purchase flow. The apiVersion must also be 7 or | |||||
| * later to use this flag. | |||||
| */ | |||||
| @Override public android.os.Bundle getBuyIntentExtraParams(int apiVersion, java.lang.String packageName, java.lang.String sku, java.lang.String type, java.lang.String developerPayload, android.os.Bundle extraParams) throws android.os.RemoteException | |||||
| { | |||||
| android.os.Parcel _data = android.os.Parcel.obtain(); | |||||
| android.os.Parcel _reply = android.os.Parcel.obtain(); | |||||
| android.os.Bundle _result; | |||||
| try { | |||||
| _data.writeInterfaceToken(DESCRIPTOR); | |||||
| _data.writeInt(apiVersion); | |||||
| _data.writeString(packageName); | |||||
| _data.writeString(sku); | |||||
| _data.writeString(type); | |||||
| _data.writeString(developerPayload); | |||||
| if ((extraParams!=null)) { | |||||
| _data.writeInt(1); | |||||
| extraParams.writeToParcel(_data, 0); | |||||
| } | |||||
| else { | |||||
| _data.writeInt(0); | |||||
| } | |||||
| mRemote.transact(Stub.TRANSACTION_getBuyIntentExtraParams, _data, _reply, 0); | |||||
| _reply.readException(); | |||||
| if ((0!=_reply.readInt())) { | |||||
| _result = android.os.Bundle.CREATOR.createFromParcel(_reply); | |||||
| } | |||||
| else { | |||||
| _result = null; | |||||
| } | |||||
| } | |||||
| finally { | |||||
| _reply.recycle(); | |||||
| _data.recycle(); | |||||
| } | |||||
| return _result; | |||||
| } | |||||
| /** | |||||
| * Returns the most recent purchase made by the user for each SKU, even if that purchase is | |||||
| * expired, canceled, or consumed. | |||||
| * @param apiVersion billing API version that the app is using, must be 6 or later | |||||
| * @param packageName package name of the calling app | |||||
| * @param type of the in-app items being requested ("inapp" for one-time purchases | |||||
| * and "subs" for subscriptions) | |||||
| * @param continuationToken to be set as null for the first call, if the number of owned | |||||
| * skus is too large, a continuationToken is returned in the response bundle. | |||||
| * This method can be called again with the continuation token to get the next set of | |||||
| * owned skus. | |||||
| * @param extraParams a Bundle with extra params that would be appended into http request | |||||
| * query string. Not used at this moment. Reserved for future functionality. | |||||
| * @return Bundle containing the following key-value pairs | |||||
| * "RESPONSE_CODE" with int value: RESULT_OK(0) if success, | |||||
| * {@link IabHelper#BILLING_RESPONSE_RESULT_*} response codes on failures. | |||||
| * | |||||
| * "INAPP_PURCHASE_ITEM_LIST" - ArrayList<String> containing the list of SKUs | |||||
| * "INAPP_PURCHASE_DATA_LIST" - ArrayList<String> containing the purchase information | |||||
| * "INAPP_DATA_SIGNATURE_LIST"- ArrayList<String> containing the signatures | |||||
| * of the purchase information | |||||
| * "INAPP_CONTINUATION_TOKEN" - String containing a continuation token for the | |||||
| * next set of in-app purchases. Only set if the | |||||
| * user has more owned skus than the current list. | |||||
| */ | |||||
| @Override public android.os.Bundle getPurchaseHistory(int apiVersion, java.lang.String packageName, java.lang.String type, java.lang.String continuationToken, android.os.Bundle extraParams) throws android.os.RemoteException | |||||
| { | |||||
| android.os.Parcel _data = android.os.Parcel.obtain(); | |||||
| android.os.Parcel _reply = android.os.Parcel.obtain(); | |||||
| android.os.Bundle _result; | |||||
| try { | |||||
| _data.writeInterfaceToken(DESCRIPTOR); | |||||
| _data.writeInt(apiVersion); | |||||
| _data.writeString(packageName); | |||||
| _data.writeString(type); | |||||
| _data.writeString(continuationToken); | |||||
| if ((extraParams!=null)) { | |||||
| _data.writeInt(1); | |||||
| extraParams.writeToParcel(_data, 0); | |||||
| } | |||||
| else { | |||||
| _data.writeInt(0); | |||||
| } | |||||
| mRemote.transact(Stub.TRANSACTION_getPurchaseHistory, _data, _reply, 0); | |||||
| _reply.readException(); | |||||
| if ((0!=_reply.readInt())) { | |||||
| _result = android.os.Bundle.CREATOR.createFromParcel(_reply); | |||||
| } | |||||
| else { | |||||
| _result = null; | |||||
| } | |||||
| } | |||||
| finally { | |||||
| _reply.recycle(); | |||||
| _data.recycle(); | |||||
| } | |||||
| return _result; | |||||
| } | |||||
| @Override public int isBillingSupportedExtraParams(int apiVersion, java.lang.String packageName, java.lang.String type, android.os.Bundle extraParams) throws android.os.RemoteException | |||||
| { | |||||
| android.os.Parcel _data = android.os.Parcel.obtain(); | |||||
| android.os.Parcel _reply = android.os.Parcel.obtain(); | |||||
| int _result; | |||||
| try { | |||||
| _data.writeInterfaceToken(DESCRIPTOR); | |||||
| _data.writeInt(apiVersion); | |||||
| _data.writeString(packageName); | |||||
| _data.writeString(type); | |||||
| if ((extraParams!=null)) { | |||||
| _data.writeInt(1); | |||||
| extraParams.writeToParcel(_data, 0); | |||||
| } | |||||
| else { | |||||
| _data.writeInt(0); | |||||
| } | |||||
| mRemote.transact(Stub.TRANSACTION_isBillingSupportedExtraParams, _data, _reply, 0); | |||||
| _reply.readException(); | |||||
| _result = _reply.readInt(); | |||||
| } | |||||
| finally { | |||||
| _reply.recycle(); | |||||
| _data.recycle(); | |||||
| } | |||||
| return _result; | |||||
| } | |||||
| } | |||||
| static final int TRANSACTION_isBillingSupported = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); | |||||
| static final int TRANSACTION_getSkuDetails = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1); | |||||
| static final int TRANSACTION_getBuyIntent = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2); | |||||
| static final int TRANSACTION_getPurchases = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3); | |||||
| static final int TRANSACTION_consumePurchase = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4); | |||||
| static final int TRANSACTION_stub = (android.os.IBinder.FIRST_CALL_TRANSACTION + 5); | |||||
| static final int TRANSACTION_getBuyIntentToReplaceSkus = (android.os.IBinder.FIRST_CALL_TRANSACTION + 6); | |||||
| static final int TRANSACTION_getBuyIntentExtraParams = (android.os.IBinder.FIRST_CALL_TRANSACTION + 7); | |||||
| static final int TRANSACTION_getPurchaseHistory = (android.os.IBinder.FIRST_CALL_TRANSACTION + 8); | |||||
| static final int TRANSACTION_isBillingSupportedExtraParams = (android.os.IBinder.FIRST_CALL_TRANSACTION + 9); | |||||
| } | |||||
| public int isBillingSupported(int apiVersion, java.lang.String packageName, java.lang.String type) throws android.os.RemoteException; | |||||
| /** | |||||
| * Provides details of a list of SKUs | |||||
| * Given a list of SKUs of a valid type in the skusBundle, this returns a bundle | |||||
| * with a list JSON strings containing the productId, price, title and description. | |||||
| * This API can be called with a maximum of 20 SKUs. | |||||
| * @param apiVersion billing API version that the app is using | |||||
| * @param packageName the package name of the calling app | |||||
| * @param type of the in-app items ("inapp" for one-time purchases | |||||
| * and "subs" for subscriptions) | |||||
| * @param skusBundle bundle containing a StringArrayList of SKUs with key "ITEM_ID_LIST" | |||||
| * @return Bundle containing the following key-value pairs | |||||
| * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, appropriate response codes | |||||
| * on failures. | |||||
| * "DETAILS_LIST" with a StringArrayList containing purchase information | |||||
| * in JSON format similar to: | |||||
| * '{ "productId" : "exampleSku", | |||||
| * "type" : "inapp", | |||||
| * "price" : "$5.00", | |||||
| * "price_currency": "USD", | |||||
| * "price_amount_micros": 5000000, | |||||
| * "title : "Example Title", | |||||
| * "description" : "This is an example description" }' | |||||
| */ | |||||
| public android.os.Bundle getSkuDetails(int apiVersion, java.lang.String packageName, java.lang.String type, android.os.Bundle skusBundle) throws android.os.RemoteException; | |||||
| /** | |||||
| * Returns a pending intent to launch the purchase flow for an in-app item by providing a SKU, | |||||
| * the type, a unique purchase token and an optional developer payload. | |||||
| * @param apiVersion billing API version that the app is using | |||||
| * @param packageName package name of the calling app | |||||
| * @param sku the SKU of the in-app item as published in the developer console | |||||
| * @param type of the in-app item being purchased ("inapp" for one-time purchases | |||||
| * and "subs" for subscriptions) | |||||
| * @param developerPayload optional argument to be sent back with the purchase information | |||||
| * @return Bundle containing the following key-value pairs | |||||
| * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, appropriate response codes | |||||
| * on failures. | |||||
| * "BUY_INTENT" - PendingIntent to start the purchase flow | |||||
| * | |||||
| * The Pending intent should be launched with startIntentSenderForResult. When purchase flow | |||||
| * has completed, the onActivityResult() will give a resultCode of OK or CANCELED. | |||||
| * If the purchase is successful, the result data will contain the following key-value pairs | |||||
| * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, appropriate response | |||||
| * codes on failures. | |||||
| * "INAPP_PURCHASE_DATA" - String in JSON format similar to | |||||
| * '{"orderId":"12999763169054705758.1371079406387615", | |||||
| * "packageName":"com.example.app", | |||||
| * "productId":"exampleSku", | |||||
| * "purchaseTime":1345678900000, | |||||
| * "purchaseToken" : "122333444455555", | |||||
| * "developerPayload":"example developer payload" }' | |||||
| * "INAPP_DATA_SIGNATURE" - String containing the signature of the purchase data that | |||||
| * was signed with the private key of the developer | |||||
| */ | |||||
| public android.os.Bundle getBuyIntent(int apiVersion, java.lang.String packageName, java.lang.String sku, java.lang.String type, java.lang.String developerPayload) throws android.os.RemoteException; | |||||
| /** | |||||
| * Returns the current SKUs owned by the user of the type and package name specified along with | |||||
| * purchase information and a signature of the data to be validated. | |||||
| * This will return all SKUs that have been purchased in V3 and managed items purchased using | |||||
| * V1 and V2 that have not been consumed. | |||||
| * @param apiVersion billing API version that the app is using | |||||
| * @param packageName package name of the calling app | |||||
| * @param type of the in-app items being requested ("inapp" for one-time purchases | |||||
| * and "subs" for subscriptions) | |||||
| * @param continuationToken to be set as null for the first call, if the number of owned | |||||
| * skus are too many, a continuationToken is returned in the response bundle. | |||||
| * This method can be called again with the continuation token to get the next set of | |||||
| * owned skus. | |||||
| * @return Bundle containing the following key-value pairs | |||||
| * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, appropriate response codes | |||||
| on failures. | |||||
| * "INAPP_PURCHASE_ITEM_LIST" - StringArrayList containing the list of SKUs | |||||
| * "INAPP_PURCHASE_DATA_LIST" - StringArrayList containing the purchase information | |||||
| * "INAPP_DATA_SIGNATURE_LIST"- StringArrayList containing the signatures | |||||
| * of the purchase information | |||||
| * "INAPP_CONTINUATION_TOKEN" - String containing a continuation token for the | |||||
| * next set of in-app purchases. Only set if the | |||||
| * user has more owned skus than the current list. | |||||
| */ | |||||
| public android.os.Bundle getPurchases(int apiVersion, java.lang.String packageName, java.lang.String type, java.lang.String continuationToken) throws android.os.RemoteException; | |||||
| public int consumePurchase(int apiVersion, java.lang.String packageName, java.lang.String purchaseToken) throws android.os.RemoteException; | |||||
| public int stub(int apiVersion, java.lang.String packageName, java.lang.String type) throws android.os.RemoteException; | |||||
| /** | |||||
| * Returns a pending intent to launch the purchase flow for upgrading or downgrading a | |||||
| * subscription. The existing owned SKU(s) should be provided along with the new SKU that | |||||
| * the user is upgrading or downgrading to. | |||||
| * @param apiVersion billing API version that the app is using, must be 5 or later | |||||
| * @param packageName package name of the calling app | |||||
| * @param oldSkus the SKU(s) that the user is upgrading or downgrading from, | |||||
| * if null or empty this method will behave like {@link #getBuyIntent} | |||||
| * @param newSku the SKU that the user is upgrading or downgrading to | |||||
| * @param type of the item being purchased, currently must be "subs" | |||||
| * @param developerPayload optional argument to be sent back with the purchase information | |||||
| * @return Bundle containing the following key-value pairs | |||||
| * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, appropriate response codes | |||||
| * on failures. | |||||
| * "BUY_INTENT" - PendingIntent to start the purchase flow | |||||
| * | |||||
| * The Pending intent should be launched with startIntentSenderForResult. When purchase flow | |||||
| * has completed, the onActivityResult() will give a resultCode of OK or CANCELED. | |||||
| * If the purchase is successful, the result data will contain the following key-value pairs | |||||
| * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, appropriate response | |||||
| * codes on failures. | |||||
| * "INAPP_PURCHASE_DATA" - String in JSON format similar to | |||||
| * '{"orderId":"12999763169054705758.1371079406387615", | |||||
| * "packageName":"com.example.app", | |||||
| * "productId":"exampleSku", | |||||
| * "purchaseTime":1345678900000, | |||||
| * "purchaseToken" : "122333444455555", | |||||
| * "developerPayload":"example developer payload" }' | |||||
| * "INAPP_DATA_SIGNATURE" - String containing the signature of the purchase data that | |||||
| * was signed with the private key of the developer | |||||
| */ | |||||
| public android.os.Bundle getBuyIntentToReplaceSkus(int apiVersion, java.lang.String packageName, java.util.List<java.lang.String> oldSkus, java.lang.String newSku, java.lang.String type, java.lang.String developerPayload) throws android.os.RemoteException; | |||||
| /** | |||||
| * Returns a pending intent to launch the purchase flow for an in-app item. This method is | |||||
| * a variant of the {@link #getBuyIntent} method and takes an additional {@code extraParams} | |||||
| * parameter. This parameter is a Bundle of optional keys and values that affect the | |||||
| * operation of the method. | |||||
| * @param apiVersion billing API version that the app is using, must be 6 or later | |||||
| * @param packageName package name of the calling app | |||||
| * @param sku the SKU of the in-app item as published in the developer console | |||||
| * @param type of the in-app item being purchased ("inapp" for one-time purchases | |||||
| * and "subs" for subscriptions) | |||||
| * @param developerPayload optional argument to be sent back with the purchase information | |||||
| * @extraParams a Bundle with the following optional keys: | |||||
| * "skusToReplace" - List<String> - an optional list of SKUs that the user is | |||||
| * upgrading or downgrading from. | |||||
| * Pass this field if the purchase is upgrading or downgrading | |||||
| * existing subscriptions. | |||||
| * The specified SKUs are replaced with the SKUs that the user is | |||||
| * purchasing. Google Play replaces the specified SKUs at the start of | |||||
| * the next billing cycle. | |||||
| * "replaceSkusProration" - Boolean - whether the user should be credited for any unused | |||||
| * subscription time on the SKUs they are upgrading or downgrading. | |||||
| * If you set this field to true, Google Play swaps out the old SKUs | |||||
| * and credits the user with the unused value of their subscription | |||||
| * time on a pro-rated basis. | |||||
| * Google Play applies this credit to the new subscription, and does | |||||
| * not begin billing the user for the new subscription until after | |||||
| * the credit is used up. | |||||
| * If you set this field to false, the user does not receive credit for | |||||
| * any unused subscription time and the recurrence date does not | |||||
| * change. | |||||
| * Default value is true. Ignored if you do not pass skusToReplace. | |||||
| * "accountId" - String - an optional obfuscated string that is uniquely | |||||
| * associated with the user's account in your app. | |||||
| * If you pass this value, Google Play can use it to detect irregular | |||||
| * activity, such as many devices making purchases on the same | |||||
| * account in a short period of time. | |||||
| * Do not use the developer ID or the user's Google ID for this field. | |||||
| * In addition, this field should not contain the user's ID in | |||||
| * cleartext. | |||||
| * We recommend that you use a one-way hash to generate a string from | |||||
| * the user's ID, and store the hashed string in this field. | |||||
| * "vr" - Boolean - an optional flag indicating whether the returned intent | |||||
| * should start a VR purchase flow. The apiVersion must also be 7 or | |||||
| * later to use this flag. | |||||
| */ | |||||
| public android.os.Bundle getBuyIntentExtraParams(int apiVersion, java.lang.String packageName, java.lang.String sku, java.lang.String type, java.lang.String developerPayload, android.os.Bundle extraParams) throws android.os.RemoteException; | |||||
| /** | |||||
| * Returns the most recent purchase made by the user for each SKU, even if that purchase is | |||||
| * expired, canceled, or consumed. | |||||
| * @param apiVersion billing API version that the app is using, must be 6 or later | |||||
| * @param packageName package name of the calling app | |||||
| * @param type of the in-app items being requested ("inapp" for one-time purchases | |||||
| * and "subs" for subscriptions) | |||||
| * @param continuationToken to be set as null for the first call, if the number of owned | |||||
| * skus is too large, a continuationToken is returned in the response bundle. | |||||
| * This method can be called again with the continuation token to get the next set of | |||||
| * owned skus. | |||||
| * @param extraParams a Bundle with extra params that would be appended into http request | |||||
| * query string. Not used at this moment. Reserved for future functionality. | |||||
| * @return Bundle containing the following key-value pairs | |||||
| * "RESPONSE_CODE" with int value: RESULT_OK(0) if success, | |||||
| * {@link IabHelper#BILLING_RESPONSE_RESULT_*} response codes on failures. | |||||
| * | |||||
| * "INAPP_PURCHASE_ITEM_LIST" - ArrayList<String> containing the list of SKUs | |||||
| * "INAPP_PURCHASE_DATA_LIST" - ArrayList<String> containing the purchase information | |||||
| * "INAPP_DATA_SIGNATURE_LIST"- ArrayList<String> containing the signatures | |||||
| * of the purchase information | |||||
| * "INAPP_CONTINUATION_TOKEN" - String containing a continuation token for the | |||||
| * next set of in-app purchases. Only set if the | |||||
| * user has more owned skus than the current list. | |||||
| */ | |||||
| public android.os.Bundle getPurchaseHistory(int apiVersion, java.lang.String packageName, java.lang.String type, java.lang.String continuationToken, android.os.Bundle extraParams) throws android.os.RemoteException; | |||||
| public int isBillingSupportedExtraParams(int apiVersion, java.lang.String packageName, java.lang.String type, android.os.Bundle extraParams) throws android.os.RemoteException; | |||||
| } | |||||
| @@ -0,0 +1,5 @@ | |||||
| <?xml version="1.0" encoding="utf-8"?> | |||||
| <resources> | |||||
| <string name="app_name">AnalyticsCollection</string> | |||||
| </resources> | |||||
| @@ -0,0 +1,14 @@ | |||||
| buildscript { | |||||
| repositories { | |||||
| jcenter() | |||||
| } | |||||
| dependencies { | |||||
| classpath 'com.android.tools.build:gradle:2.3.3' | |||||
| } | |||||
| } | |||||
| allprojects { | |||||
| repositories { | |||||
| jcenter() | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,202 @@ | |||||
| Apache License | |||||
| Version 2.0, January 2004 | |||||
| http://www.apache.org/licenses/ | |||||
| TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | |||||
| 1. Definitions. | |||||
| "License" shall mean the terms and conditions for use, reproduction, | |||||
| and distribution as defined by Sections 1 through 9 of this document. | |||||
| "Licensor" shall mean the copyright owner or entity authorized by | |||||
| the copyright owner that is granting the License. | |||||
| "Legal Entity" shall mean the union of the acting entity and all | |||||
| other entities that control, are controlled by, or are under common | |||||
| control with that entity. For the purposes of this definition, | |||||
| "control" means (i) the power, direct or indirect, to cause the | |||||
| direction or management of such entity, whether by contract or | |||||
| otherwise, or (ii) ownership of fifty percent (50%) or more of the | |||||
| outstanding shares, or (iii) beneficial ownership of such entity. | |||||
| "You" (or "Your") shall mean an individual or Legal Entity | |||||
| exercising permissions granted by this License. | |||||
| "Source" form shall mean the preferred form for making modifications, | |||||
| including but not limited to software source code, documentation | |||||
| source, and configuration files. | |||||
| "Object" form shall mean any form resulting from mechanical | |||||
| transformation or translation of a Source form, including but | |||||
| not limited to compiled object code, generated documentation, | |||||
| and conversions to other media types. | |||||
| "Work" shall mean the work of authorship, whether in Source or | |||||
| Object form, made available under the License, as indicated by a | |||||
| copyright notice that is included in or attached to the work | |||||
| (an example is provided in the Appendix below). | |||||
| "Derivative Works" shall mean any work, whether in Source or Object | |||||
| form, that is based on (or derived from) the Work and for which the | |||||
| editorial revisions, annotations, elaborations, or other modifications | |||||
| represent, as a whole, an original work of authorship. For the purposes | |||||
| of this License, Derivative Works shall not include works that remain | |||||
| separable from, or merely link (or bind by name) to the interfaces of, | |||||
| the Work and Derivative Works thereof. | |||||
| "Contribution" shall mean any work of authorship, including | |||||
| the original version of the Work and any modifications or additions | |||||
| to that Work or Derivative Works thereof, that is intentionally | |||||
| submitted to Licensor for inclusion in the Work by the copyright owner | |||||
| or by an individual or Legal Entity authorized to submit on behalf of | |||||
| the copyright owner. For the purposes of this definition, "submitted" | |||||
| means any form of electronic, verbal, or written communication sent | |||||
| to the Licensor or its representatives, including but not limited to | |||||
| communication on electronic mailing lists, source code control systems, | |||||
| and issue tracking systems that are managed by, or on behalf of, the | |||||
| Licensor for the purpose of discussing and improving the Work, but | |||||
| excluding communication that is conspicuously marked or otherwise | |||||
| designated in writing by the copyright owner as "Not a Contribution." | |||||
| "Contributor" shall mean Licensor and any individual or Legal Entity | |||||
| on behalf of whom a Contribution has been received by Licensor and | |||||
| subsequently incorporated within the Work. | |||||
| 2. Grant of Copyright License. Subject to the terms and conditions of | |||||
| this License, each Contributor hereby grants to You a perpetual, | |||||
| worldwide, non-exclusive, no-charge, royalty-free, irrevocable | |||||
| copyright license to reproduce, prepare Derivative Works of, | |||||
| publicly display, publicly perform, sublicense, and distribute the | |||||
| Work and such Derivative Works in Source or Object form. | |||||
| 3. Grant of Patent License. Subject to the terms and conditions of | |||||
| this License, each Contributor hereby grants to You a perpetual, | |||||
| worldwide, non-exclusive, no-charge, royalty-free, irrevocable | |||||
| (except as stated in this section) patent license to make, have made, | |||||
| use, offer to sell, sell, import, and otherwise transfer the Work, | |||||
| where such license applies only to those patent claims licensable | |||||
| by such Contributor that are necessarily infringed by their | |||||
| Contribution(s) alone or by combination of their Contribution(s) | |||||
| with the Work to which such Contribution(s) was submitted. If You | |||||
| institute patent litigation against any entity (including a | |||||
| cross-claim or counterclaim in a lawsuit) alleging that the Work | |||||
| or a Contribution incorporated within the Work constitutes direct | |||||
| or contributory patent infringement, then any patent licenses | |||||
| granted to You under this License for that Work shall terminate | |||||
| as of the date such litigation is filed. | |||||
| 4. Redistribution. You may reproduce and distribute copies of the | |||||
| Work or Derivative Works thereof in any medium, with or without | |||||
| modifications, and in Source or Object form, provided that You | |||||
| meet the following conditions: | |||||
| (a) You must give any other recipients of the Work or | |||||
| Derivative Works a copy of this License; and | |||||
| (b) You must cause any modified files to carry prominent notices | |||||
| stating that You changed the files; and | |||||
| (c) You must retain, in the Source form of any Derivative Works | |||||
| that You distribute, all copyright, patent, trademark, and | |||||
| attribution notices from the Source form of the Work, | |||||
| excluding those notices that do not pertain to any part of | |||||
| the Derivative Works; and | |||||
| (d) If the Work includes a "NOTICE" text file as part of its | |||||
| distribution, then any Derivative Works that You distribute must | |||||
| include a readable copy of the attribution notices contained | |||||
| within such NOTICE file, excluding those notices that do not | |||||
| pertain to any part of the Derivative Works, in at least one | |||||
| of the following places: within a NOTICE text file distributed | |||||
| as part of the Derivative Works; within the Source form or | |||||
| documentation, if provided along with the Derivative Works; or, | |||||
| within a display generated by the Derivative Works, if and | |||||
| wherever such third-party notices normally appear. The contents | |||||
| of the NOTICE file are for informational purposes only and | |||||
| do not modify the License. You may add Your own attribution | |||||
| notices within Derivative Works that You distribute, alongside | |||||
| or as an addendum to the NOTICE text from the Work, provided | |||||
| that such additional attribution notices cannot be construed | |||||
| as modifying the License. | |||||
| You may add Your own copyright statement to Your modifications and | |||||
| may provide additional or different license terms and conditions | |||||
| for use, reproduction, or distribution of Your modifications, or | |||||
| for any such Derivative Works as a whole, provided Your use, | |||||
| reproduction, and distribution of the Work otherwise complies with | |||||
| the conditions stated in this License. | |||||
| 5. Submission of Contributions. Unless You explicitly state otherwise, | |||||
| any Contribution intentionally submitted for inclusion in the Work | |||||
| by You to the Licensor shall be under the terms and conditions of | |||||
| this License, without any additional terms or conditions. | |||||
| Notwithstanding the above, nothing herein shall supersede or modify | |||||
| the terms of any separate license agreement you may have executed | |||||
| with Licensor regarding such Contributions. | |||||
| 6. Trademarks. This License does not grant permission to use the trade | |||||
| names, trademarks, service marks, or product names of the Licensor, | |||||
| except as required for reasonable and customary use in describing the | |||||
| origin of the Work and reproducing the content of the NOTICE file. | |||||
| 7. Disclaimer of Warranty. Unless required by applicable law or | |||||
| agreed to in writing, Licensor provides the Work (and each | |||||
| Contributor provides its Contributions) on an "AS IS" BASIS, | |||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | |||||
| implied, including, without limitation, any warranties or conditions | |||||
| of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A | |||||
| PARTICULAR PURPOSE. You are solely responsible for determining the | |||||
| appropriateness of using or redistributing the Work and assume any | |||||
| risks associated with Your exercise of permissions under this License. | |||||
| 8. Limitation of Liability. In no event and under no legal theory, | |||||
| whether in tort (including negligence), contract, or otherwise, | |||||
| unless required by applicable law (such as deliberate and grossly | |||||
| negligent acts) or agreed to in writing, shall any Contributor be | |||||
| liable to You for damages, including any direct, indirect, special, | |||||
| incidental, or consequential damages of any character arising as a | |||||
| result of this License or out of the use or inability to use the | |||||
| Work (including but not limited to damages for loss of goodwill, | |||||
| work stoppage, computer failure or malfunction, or any and all | |||||
| other commercial damages or losses), even if such Contributor | |||||
| has been advised of the possibility of such damages. | |||||
| 9. Accepting Warranty or Additional Liability. While redistributing | |||||
| the Work or Derivative Works thereof, You may choose to offer, | |||||
| and charge a fee for, acceptance of support, warranty, indemnity, | |||||
| or other liability obligations and/or rights consistent with this | |||||
| License. However, in accepting such obligations, You may act only | |||||
| on Your own behalf and on Your sole responsibility, not on behalf | |||||
| of any other Contributor, and only if You agree to indemnify, | |||||
| defend, and hold each Contributor harmless for any liability | |||||
| incurred by, or claims asserted against, such Contributor by reason | |||||
| of your accepting any such warranty or additional liability. | |||||
| END OF TERMS AND CONDITIONS | |||||
| APPENDIX: How to apply the Apache License to your work. | |||||
| To apply the Apache License to your work, attach the following | |||||
| boilerplate notice, with the fields enclosed by brackets "{}" | |||||
| replaced with your own identifying information. (Don't include | |||||
| the brackets!) The text should be enclosed in the appropriate | |||||
| comment syntax for the file format. We also recommend that a | |||||
| file or class name and description of purpose be included on the | |||||
| same "printed page" as the copyright notice for easier | |||||
| identification within third-party archives. | |||||
| Copyright {yyyy} {name of copyright owner} | |||||
| Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| you may not use this file except in compliance with the License. | |||||
| You may obtain a copy of the License at | |||||
| http://www.apache.org/licenses/LICENSE-2.0 | |||||
| Unless required by applicable law or agreed to in writing, software | |||||
| distributed under the License is distributed on an "AS IS" BASIS, | |||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| See the License for the specific language governing permissions and | |||||
| limitations under the License. | |||||
| @@ -0,0 +1 @@ | |||||
| distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip | |||||
| @@ -0,0 +1,160 @@ | |||||
| #!/usr/bin/env bash | |||||
| ############################################################################## | |||||
| ## | |||||
| ## Gradle start up script for UN*X | |||||
| ## | |||||
| ############################################################################## | |||||
| # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. | |||||
| DEFAULT_JVM_OPTS="" | |||||
| APP_NAME="Gradle" | |||||
| APP_BASE_NAME=`basename "$0"` | |||||
| # Use the maximum available, or set MAX_FD != -1 to use that value. | |||||
| MAX_FD="maximum" | |||||
| warn ( ) { | |||||
| echo "$*" | |||||
| } | |||||
| die ( ) { | |||||
| echo | |||||
| echo "$*" | |||||
| echo | |||||
| exit 1 | |||||
| } | |||||
| # OS specific support (must be 'true' or 'false'). | |||||
| cygwin=false | |||||
| msys=false | |||||
| darwin=false | |||||
| case "`uname`" in | |||||
| CYGWIN* ) | |||||
| cygwin=true | |||||
| ;; | |||||
| Darwin* ) | |||||
| darwin=true | |||||
| ;; | |||||
| MINGW* ) | |||||
| msys=true | |||||
| ;; | |||||
| esac | |||||
| # Attempt to set APP_HOME | |||||
| # Resolve links: $0 may be a link | |||||
| PRG="$0" | |||||
| # Need this for relative symlinks. | |||||
| while [ -h "$PRG" ] ; do | |||||
| ls=`ls -ld "$PRG"` | |||||
| link=`expr "$ls" : '.*-> \(.*\)$'` | |||||
| if expr "$link" : '/.*' > /dev/null; then | |||||
| PRG="$link" | |||||
| else | |||||
| PRG=`dirname "$PRG"`"/$link" | |||||
| fi | |||||
| done | |||||
| SAVED="`pwd`" | |||||
| cd "`dirname \"$PRG\"`/" >/dev/null | |||||
| APP_HOME="`pwd -P`" | |||||
| cd "$SAVED" >/dev/null | |||||
| CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar | |||||
| # Determine the Java command to use to start the JVM. | |||||
| if [ -n "$JAVA_HOME" ] ; then | |||||
| if [ -x "$JAVA_HOME/jre/sh/java" ] ; then | |||||
| # IBM's JDK on AIX uses strange locations for the executables | |||||
| JAVACMD="$JAVA_HOME/jre/sh/java" | |||||
| else | |||||
| JAVACMD="$JAVA_HOME/bin/java" | |||||
| fi | |||||
| if [ ! -x "$JAVACMD" ] ; then | |||||
| die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME | |||||
| Please set the JAVA_HOME variable in your environment to match the | |||||
| location of your Java installation." | |||||
| fi | |||||
| else | |||||
| JAVACMD="java" | |||||
| which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. | |||||
| Please set the JAVA_HOME variable in your environment to match the | |||||
| location of your Java installation." | |||||
| fi | |||||
| # Increase the maximum file descriptors if we can. | |||||
| if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then | |||||
| MAX_FD_LIMIT=`ulimit -H -n` | |||||
| if [ $? -eq 0 ] ; then | |||||
| if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then | |||||
| MAX_FD="$MAX_FD_LIMIT" | |||||
| fi | |||||
| ulimit -n $MAX_FD | |||||
| if [ $? -ne 0 ] ; then | |||||
| warn "Could not set maximum file descriptor limit: $MAX_FD" | |||||
| fi | |||||
| else | |||||
| warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" | |||||
| fi | |||||
| fi | |||||
| # For Darwin, add options to specify how the application appears in the dock | |||||
| if $darwin; then | |||||
| GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" | |||||
| fi | |||||
| # For Cygwin, switch paths to Windows format before running java | |||||
| if $cygwin ; then | |||||
| APP_HOME=`cygpath --path --mixed "$APP_HOME"` | |||||
| CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` | |||||
| JAVACMD=`cygpath --unix "$JAVACMD"` | |||||
| # We build the pattern for arguments to be converted via cygpath | |||||
| ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` | |||||
| SEP="" | |||||
| for dir in $ROOTDIRSRAW ; do | |||||
| ROOTDIRS="$ROOTDIRS$SEP$dir" | |||||
| SEP="|" | |||||
| done | |||||
| OURCYGPATTERN="(^($ROOTDIRS))" | |||||
| # Add a user-defined pattern to the cygpath arguments | |||||
| if [ "$GRADLE_CYGPATTERN" != "" ] ; then | |||||
| OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" | |||||
| fi | |||||
| # Now convert the arguments - kludge to limit ourselves to /bin/sh | |||||
| i=0 | |||||
| for arg in "$@" ; do | |||||
| CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` | |||||
| CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option | |||||
| if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition | |||||
| eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` | |||||
| else | |||||
| eval `echo args$i`="\"$arg\"" | |||||
| fi | |||||
| i=$((i+1)) | |||||
| done | |||||
| case $i in | |||||
| (0) set -- ;; | |||||
| (1) set -- "$args0" ;; | |||||
| (2) set -- "$args0" "$args1" ;; | |||||
| (3) set -- "$args0" "$args1" "$args2" ;; | |||||
| (4) set -- "$args0" "$args1" "$args2" "$args3" ;; | |||||
| (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; | |||||
| (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; | |||||
| (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; | |||||
| (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; | |||||
| (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; | |||||
| esac | |||||
| fi | |||||
| # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules | |||||
| function splitJvmOpts() { | |||||
| JVM_OPTS=("$@") | |||||
| } | |||||
| eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS | |||||
| JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" | |||||
| exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" | |||||
| @@ -0,0 +1,90 @@ | |||||
| @if "%DEBUG%" == "" @echo off | |||||
| @rem ########################################################################## | |||||
| @rem | |||||
| @rem Gradle startup script for Windows | |||||
| @rem | |||||
| @rem ########################################################################## | |||||
| @rem Set local scope for the variables with windows NT shell | |||||
| if "%OS%"=="Windows_NT" setlocal | |||||
| @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. | |||||
| set DEFAULT_JVM_OPTS= | |||||
| set DIRNAME=%~dp0 | |||||
| if "%DIRNAME%" == "" set DIRNAME=. | |||||
| set APP_BASE_NAME=%~n0 | |||||
| set APP_HOME=%DIRNAME% | |||||
| @rem Find java.exe | |||||
| if defined JAVA_HOME goto findJavaFromJavaHome | |||||
| set JAVA_EXE=java.exe | |||||
| %JAVA_EXE% -version >NUL 2>&1 | |||||
| if "%ERRORLEVEL%" == "0" goto init | |||||
| echo. | |||||
| echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. | |||||
| echo. | |||||
| echo Please set the JAVA_HOME variable in your environment to match the | |||||
| echo location of your Java installation. | |||||
| goto fail | |||||
| :findJavaFromJavaHome | |||||
| set JAVA_HOME=%JAVA_HOME:"=% | |||||
| set JAVA_EXE=%JAVA_HOME%/bin/java.exe | |||||
| if exist "%JAVA_EXE%" goto init | |||||
| echo. | |||||
| echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% | |||||
| echo. | |||||
| echo Please set the JAVA_HOME variable in your environment to match the | |||||
| echo location of your Java installation. | |||||
| goto fail | |||||
| :init | |||||
| @rem Get command-line arguments, handling Windowz variants | |||||
| if not "%OS%" == "Windows_NT" goto win9xME_args | |||||
| if "%@eval[2+2]" == "4" goto 4NT_args | |||||
| :win9xME_args | |||||
| @rem Slurp the command line arguments. | |||||
| set CMD_LINE_ARGS= | |||||
| set _SKIP=2 | |||||
| :win9xME_args_slurp | |||||
| if "x%~1" == "x" goto execute | |||||
| set CMD_LINE_ARGS=%* | |||||
| goto execute | |||||
| :4NT_args | |||||
| @rem Get arguments from the 4NT Shell from JP Software | |||||
| set CMD_LINE_ARGS=%$ | |||||
| :execute | |||||
| @rem Setup the command line | |||||
| set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar | |||||
| @rem Execute Gradle | |||||
| "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% | |||||
| :end | |||||
| @rem End local scope for the variables with windows NT shell | |||||
| if "%ERRORLEVEL%"=="0" goto mainEnd | |||||
| :fail | |||||
| rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of | |||||
| rem the _cmd.exe /c_ return code! | |||||
| if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 | |||||
| exit /b 1 | |||||
| :mainEnd | |||||
| if "%OS%"=="Windows_NT" endlocal | |||||
| :omega | |||||
| @@ -0,0 +1 @@ | |||||
| include ':app' | |||||
| @@ -0,0 +1,135 @@ | |||||
| # Automatically generated makefile, created by the Projucer | |||||
| # Don't edit this file! Your changes will be overwritten when you re-save the Projucer project! | |||||
| # build with "V=1" for verbose builds | |||||
| ifeq ($(V), 1) | |||||
| V_AT = | |||||
| else | |||||
| V_AT = @ | |||||
| endif | |||||
| # (this disables dependency generation if multiple architectures are set) | |||||
| DEPFLAGS := $(if $(word 2, $(TARGET_ARCH)), , -MMD) | |||||
| ifndef STRIP | |||||
| STRIP=strip | |||||
| endif | |||||
| ifndef AR | |||||
| AR=ar | |||||
| endif | |||||
| ifndef CONFIG | |||||
| CONFIG=Debug | |||||
| endif | |||||
| ifeq ($(CONFIG),Debug) | |||||
| JUCE_BINDIR := build | |||||
| JUCE_LIBDIR := build | |||||
| JUCE_OBJDIR := build/intermediate/Debug | |||||
| JUCE_OUTDIR := build | |||||
| ifeq ($(TARGET_ARCH),) | |||||
| TARGET_ARCH := -march=native | |||||
| endif | |||||
| JUCE_CPPFLAGS := $(DEPFLAGS) -DLINUX=1 -DDEBUG=1 -D_DEBUG=1 -DJUCE_USE_CURL=1 -DJUCER_LINUX_MAKE_6D53C8B4=1 -DJUCE_APP_VERSION=1.0.0 -DJUCE_APP_VERSION_HEX=0x10000 $(shell pkg-config --cflags freetype2 libcurl x11 xext xinerama) -pthread -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS) | |||||
| JUCE_CPPFLAGS_APP := -DJucePlugin_Build_VST=0 -DJucePlugin_Build_VST3=0 -DJucePlugin_Build_AU=0 -DJucePlugin_Build_AUv3=0 -DJucePlugin_Build_RTAS=0 -DJucePlugin_Build_AAX=0 -DJucePlugin_Build_Standalone=0 | |||||
| JUCE_TARGET_APP := AnalyticsCollection | |||||
| JUCE_CFLAGS += $(JUCE_CPPFLAGS) $(TARGET_ARCH) -g -ggdb -O0 $(CFLAGS) | |||||
| JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++11 $(CXXFLAGS) | |||||
| JUCE_LDFLAGS += $(TARGET_ARCH) -L$(JUCE_BINDIR) -L$(JUCE_LIBDIR) $(shell pkg-config --libs freetype2 libcurl x11 xext xinerama) -ldl -lpthread -lrt $(LDFLAGS) | |||||
| CLEANCMD = rm -rf $(JUCE_OUTDIR)/$(TARGET) $(JUCE_OBJDIR) | |||||
| endif | |||||
| ifeq ($(CONFIG),Release) | |||||
| JUCE_BINDIR := build | |||||
| JUCE_LIBDIR := build | |||||
| JUCE_OBJDIR := build/intermediate/Release | |||||
| JUCE_OUTDIR := build | |||||
| ifeq ($(TARGET_ARCH),) | |||||
| TARGET_ARCH := -march=native | |||||
| endif | |||||
| JUCE_CPPFLAGS := $(DEPFLAGS) -DLINUX=1 -DNDEBUG=1 -DJUCE_USE_CURL=1 -DJUCER_LINUX_MAKE_6D53C8B4=1 -DJUCE_APP_VERSION=1.0.0 -DJUCE_APP_VERSION_HEX=0x10000 $(shell pkg-config --cflags freetype2 libcurl x11 xext xinerama) -pthread -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS) | |||||
| JUCE_CPPFLAGS_APP := -DJucePlugin_Build_VST=0 -DJucePlugin_Build_VST3=0 -DJucePlugin_Build_AU=0 -DJucePlugin_Build_AUv3=0 -DJucePlugin_Build_RTAS=0 -DJucePlugin_Build_AAX=0 -DJucePlugin_Build_Standalone=0 | |||||
| JUCE_TARGET_APP := AnalyticsCollection | |||||
| JUCE_CFLAGS += $(JUCE_CPPFLAGS) $(TARGET_ARCH) -O3 $(CFLAGS) | |||||
| JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++11 $(CXXFLAGS) | |||||
| JUCE_LDFLAGS += $(TARGET_ARCH) -L$(JUCE_BINDIR) -L$(JUCE_LIBDIR) $(shell pkg-config --libs freetype2 libcurl x11 xext xinerama) -fvisibility=hidden -ldl -lpthread -lrt $(LDFLAGS) | |||||
| CLEANCMD = rm -rf $(JUCE_OUTDIR)/$(TARGET) $(JUCE_OBJDIR) | |||||
| endif | |||||
| OBJECTS_APP := \ | |||||
| $(JUCE_OBJDIR)/Main_90ebc5c2.o \ | |||||
| $(JUCE_OBJDIR)/include_juce_analytics_f8e9fa94.o \ | |||||
| $(JUCE_OBJDIR)/include_juce_core_f26d17db.o \ | |||||
| $(JUCE_OBJDIR)/include_juce_data_structures_7471b1e3.o \ | |||||
| $(JUCE_OBJDIR)/include_juce_events_fd7d695.o \ | |||||
| $(JUCE_OBJDIR)/include_juce_graphics_f817e147.o \ | |||||
| $(JUCE_OBJDIR)/include_juce_gui_basics_e3f79785.o \ | |||||
| .PHONY: clean all | |||||
| all : $(JUCE_OUTDIR)/$(JUCE_TARGET_APP) | |||||
| $(JUCE_OUTDIR)/$(JUCE_TARGET_APP) : check-pkg-config $(OBJECTS_APP) $(RESOURCES) | |||||
| @echo Linking "AnalyticsCollection - App" | |||||
| -$(V_AT)mkdir -p $(JUCE_BINDIR) | |||||
| -$(V_AT)mkdir -p $(JUCE_LIBDIR) | |||||
| -$(V_AT)mkdir -p $(JUCE_OUTDIR) | |||||
| $(V_AT)$(CXX) -o $(JUCE_OUTDIR)/$(JUCE_TARGET_APP) $(OBJECTS_APP) $(JUCE_LDFLAGS) $(RESOURCES) $(TARGET_ARCH) | |||||
| $(JUCE_OBJDIR)/Main_90ebc5c2.o: ../../Source/Main.cpp | |||||
| -$(V_AT)mkdir -p $(JUCE_OBJDIR) | |||||
| @echo "Compiling Main.cpp" | |||||
| $(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<" | |||||
| $(JUCE_OBJDIR)/include_juce_analytics_f8e9fa94.o: ../../JuceLibraryCode/include_juce_analytics.cpp | |||||
| -$(V_AT)mkdir -p $(JUCE_OBJDIR) | |||||
| @echo "Compiling include_juce_analytics.cpp" | |||||
| $(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<" | |||||
| $(JUCE_OBJDIR)/include_juce_core_f26d17db.o: ../../JuceLibraryCode/include_juce_core.cpp | |||||
| -$(V_AT)mkdir -p $(JUCE_OBJDIR) | |||||
| @echo "Compiling include_juce_core.cpp" | |||||
| $(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<" | |||||
| $(JUCE_OBJDIR)/include_juce_data_structures_7471b1e3.o: ../../JuceLibraryCode/include_juce_data_structures.cpp | |||||
| -$(V_AT)mkdir -p $(JUCE_OBJDIR) | |||||
| @echo "Compiling include_juce_data_structures.cpp" | |||||
| $(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<" | |||||
| $(JUCE_OBJDIR)/include_juce_events_fd7d695.o: ../../JuceLibraryCode/include_juce_events.cpp | |||||
| -$(V_AT)mkdir -p $(JUCE_OBJDIR) | |||||
| @echo "Compiling include_juce_events.cpp" | |||||
| $(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<" | |||||
| $(JUCE_OBJDIR)/include_juce_graphics_f817e147.o: ../../JuceLibraryCode/include_juce_graphics.cpp | |||||
| -$(V_AT)mkdir -p $(JUCE_OBJDIR) | |||||
| @echo "Compiling include_juce_graphics.cpp" | |||||
| $(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<" | |||||
| $(JUCE_OBJDIR)/include_juce_gui_basics_e3f79785.o: ../../JuceLibraryCode/include_juce_gui_basics.cpp | |||||
| -$(V_AT)mkdir -p $(JUCE_OBJDIR) | |||||
| @echo "Compiling include_juce_gui_basics.cpp" | |||||
| $(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<" | |||||
| check-pkg-config: | |||||
| @command -v pkg-config >/dev/null 2>&1 || { echo >&2 "pkg-config not installed. Please, install it."; exit 1; } | |||||
| @pkg-config --print-errors freetype2 libcurl x11 xext xinerama | |||||
| clean: | |||||
| @echo Cleaning AnalyticsCollection | |||||
| $(V_AT)$(CLEANCMD) | |||||
| strip: | |||||
| @echo Stripping AnalyticsCollection | |||||
| -$(V_AT)$(STRIP) --strip-unneeded $(JUCE_OUTDIR)/$(TARGET) | |||||
| -include $(OBJECTS_APP:%.o=%.d) | |||||
| @@ -0,0 +1,251 @@ | |||||
| // !$*UTF8*$! | |||||
| { | |||||
| archiveVersion = 1; | |||||
| classes = { | |||||
| }; | |||||
| objectVersion = 46; | |||||
| objects = { | |||||
| 95AA57DF380DDDCD099D4000 = {isa = PBXBuildFile; fileRef = 707149C59A1AF9752E428B97; }; | |||||
| B45E888BC48139CA81112E4A = {isa = PBXBuildFile; fileRef = 570EA8E9B2BD490DAA35F86E; }; | |||||
| 375013DDDA026F2709E4FDAD = {isa = PBXBuildFile; fileRef = C858CF44E96D416E4B6B9266; }; | |||||
| 877F68400FB5A15B39719C61 = {isa = PBXBuildFile; fileRef = 08EEB00E1779867598046EB6; }; | |||||
| 38EE4929FFB8B83FB37B6E73 = {isa = PBXBuildFile; fileRef = FBCE051A0BA6C9FA3E64B47B; }; | |||||
| A0DA914E3E16F49D60A5A47F = {isa = PBXBuildFile; fileRef = 3D44D3C7CC1020729BBF62BB; }; | |||||
| D293FC19C031441D146F2410 = {isa = PBXBuildFile; fileRef = 6A86C9751E9DCFA62D4562DB; }; | |||||
| 962036B1BB2EDB0F9D53E125 = {isa = PBXBuildFile; fileRef = 33B9806EFA95DA05ACD9344E; }; | |||||
| 6297B7A712B1E5A74311F162 = {isa = PBXBuildFile; fileRef = 5DC0FF6BC4AE24FABC41F20E; }; | |||||
| 132F9FBC9EB36AF2E755325D = {isa = PBXBuildFile; fileRef = AD2CFF58DA5E1C6EDF9CC399; }; | |||||
| 805CDCC5840B0D713C286826 = {isa = PBXBuildFile; fileRef = A0DDFB3559C431E96EC59392; }; | |||||
| C09B5A3CD0643CF37C9CF851 = {isa = PBXBuildFile; fileRef = 61FADB63565026F559F43F3B; }; | |||||
| A1DF340E80EC501B1DBE75A0 = {isa = PBXBuildFile; fileRef = 65311EED96DCA9B62EBFEA04; }; | |||||
| 02589D465A73E0112B97BD3A = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_core"; path = "../../../../modules/juce_core"; sourceTree = "SOURCE_ROOT"; }; | |||||
| 08EEB00E1779867598046EB6 = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; }; | |||||
| 1AA9DA887BE127DCED5228BB = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_events"; path = "../../../../modules/juce_events"; sourceTree = "SOURCE_ROOT"; }; | |||||
| 33B9806EFA95DA05ACD9344E = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "include_juce_analytics.cpp"; path = "../../JuceLibraryCode/include_juce_analytics.cpp"; sourceTree = "SOURCE_ROOT"; }; | |||||
| 3D44D3C7CC1020729BBF62BB = {isa = PBXFileReference; lastKnownFileType = file.nib; name = RecentFilesMenuTemplate.nib; path = RecentFilesMenuTemplate.nib; sourceTree = "SOURCE_ROOT"; }; | |||||
| 5219A3D3BECB8C7135C90377 = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_gui_basics"; path = "../../../../modules/juce_gui_basics"; sourceTree = "SOURCE_ROOT"; }; | |||||
| 570EA8E9B2BD490DAA35F86E = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; }; | |||||
| 5DC0FF6BC4AE24FABC41F20E = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "include_juce_core.mm"; path = "../../JuceLibraryCode/include_juce_core.mm"; sourceTree = "SOURCE_ROOT"; }; | |||||
| 61FADB63565026F559F43F3B = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "include_juce_graphics.mm"; path = "../../JuceLibraryCode/include_juce_graphics.mm"; sourceTree = "SOURCE_ROOT"; }; | |||||
| 65311EED96DCA9B62EBFEA04 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "include_juce_gui_basics.mm"; path = "../../JuceLibraryCode/include_juce_gui_basics.mm"; sourceTree = "SOURCE_ROOT"; }; | |||||
| 6A86C9751E9DCFA62D4562DB = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Main.cpp; path = ../../Source/Main.cpp; sourceTree = "SOURCE_ROOT"; }; | |||||
| 707149C59A1AF9752E428B97 = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AnalyticsCollection.app; sourceTree = "BUILT_PRODUCTS_DIR"; }; | |||||
| 7A9FA859A2C2AE9FDDC99AD9 = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "Info-App.plist"; path = "Info-App.plist"; sourceTree = "SOURCE_ROOT"; }; | |||||
| 886AEA380A40C905503764EB = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_graphics"; path = "../../../../modules/juce_graphics"; sourceTree = "SOURCE_ROOT"; }; | |||||
| 8A74F3F7422C89A897D93397 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AppConfig.h; path = ../../JuceLibraryCode/AppConfig.h; sourceTree = "SOURCE_ROOT"; }; | |||||
| 8B927F72BA8726A064560942 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = GoogleAnalyticsDestination.h; path = ../../Source/GoogleAnalyticsDestination.h; sourceTree = "SOURCE_ROOT"; }; | |||||
| 91208A06115D573563996967 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = JuceHeader.h; path = ../../JuceLibraryCode/JuceHeader.h; sourceTree = "SOURCE_ROOT"; }; | |||||
| 996BEF5ADCE2EC85EB9F637F = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_data_structures"; path = "../../../../modules/juce_data_structures"; sourceTree = "SOURCE_ROOT"; }; | |||||
| A0DDFB3559C431E96EC59392 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "include_juce_events.mm"; path = "../../JuceLibraryCode/include_juce_events.mm"; sourceTree = "SOURCE_ROOT"; }; | |||||
| AD2CFF58DA5E1C6EDF9CC399 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "include_juce_data_structures.mm"; path = "../../JuceLibraryCode/include_juce_data_structures.mm"; sourceTree = "SOURCE_ROOT"; }; | |||||
| C858CF44E96D416E4B6B9266 = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; | |||||
| D352CDB4CA7E8B21FAA83B8C = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MainComponent.h; path = ../../Source/MainComponent.h; sourceTree = "SOURCE_ROOT"; }; | |||||
| F2CF007AA4C90AC7A5AD1604 = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_analytics"; path = "../../../../modules/juce_analytics"; sourceTree = "SOURCE_ROOT"; }; | |||||
| FBCE051A0BA6C9FA3E64B47B = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; | |||||
| D269FA28B5D6012AEFE0BF20 = {isa = PBXGroup; children = ( | |||||
| 8B927F72BA8726A064560942, | |||||
| D352CDB4CA7E8B21FAA83B8C, | |||||
| 6A86C9751E9DCFA62D4562DB, ); name = Source; sourceTree = "<group>"; }; | |||||
| 2B971235E85DF9D98B6FC8AF = {isa = PBXGroup; children = ( | |||||
| D269FA28B5D6012AEFE0BF20, ); name = AnalyticsCollection; sourceTree = "<group>"; }; | |||||
| 0B35DCE65DF34DECBF1D8118 = {isa = PBXGroup; children = ( | |||||
| F2CF007AA4C90AC7A5AD1604, | |||||
| 02589D465A73E0112B97BD3A, | |||||
| 996BEF5ADCE2EC85EB9F637F, | |||||
| 1AA9DA887BE127DCED5228BB, | |||||
| 886AEA380A40C905503764EB, | |||||
| 5219A3D3BECB8C7135C90377, ); name = "Juce Modules"; sourceTree = "<group>"; }; | |||||
| B24D9AE60E0CE5D1A75693B5 = {isa = PBXGroup; children = ( | |||||
| 8A74F3F7422C89A897D93397, | |||||
| 33B9806EFA95DA05ACD9344E, | |||||
| 5DC0FF6BC4AE24FABC41F20E, | |||||
| AD2CFF58DA5E1C6EDF9CC399, | |||||
| A0DDFB3559C431E96EC59392, | |||||
| 61FADB63565026F559F43F3B, | |||||
| 65311EED96DCA9B62EBFEA04, | |||||
| 91208A06115D573563996967, ); name = "Juce Library Code"; sourceTree = "<group>"; }; | |||||
| 782C3BD0C802236A266FDEDD = {isa = PBXGroup; children = ( | |||||
| 7A9FA859A2C2AE9FDDC99AD9, | |||||
| 3D44D3C7CC1020729BBF62BB, ); name = Resources; sourceTree = "<group>"; }; | |||||
| F70B9CB615E26A697D2CBEB4 = {isa = PBXGroup; children = ( | |||||
| 570EA8E9B2BD490DAA35F86E, | |||||
| C858CF44E96D416E4B6B9266, | |||||
| 08EEB00E1779867598046EB6, | |||||
| FBCE051A0BA6C9FA3E64B47B, ); name = Frameworks; sourceTree = "<group>"; }; | |||||
| 40E8A594A7EAFA1EF5707952 = {isa = PBXGroup; children = ( | |||||
| 707149C59A1AF9752E428B97, ); name = Products; sourceTree = "<group>"; }; | |||||
| 5CB45B3816ED17D0620DDEBF = {isa = PBXGroup; children = ( | |||||
| 2B971235E85DF9D98B6FC8AF, | |||||
| 0B35DCE65DF34DECBF1D8118, | |||||
| B24D9AE60E0CE5D1A75693B5, | |||||
| 782C3BD0C802236A266FDEDD, | |||||
| F70B9CB615E26A697D2CBEB4, | |||||
| 40E8A594A7EAFA1EF5707952, ); name = Source; sourceTree = "<group>"; }; | |||||
| 6FF8E864589AD3C2C06BF546 = {isa = XCBuildConfiguration; buildSettings = { | |||||
| CLANG_CXX_LANGUAGE_STANDARD = "c++11"; | |||||
| CLANG_LINK_OBJC_RUNTIME = NO; | |||||
| COMBINE_HIDPI_IMAGES = YES; | |||||
| CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)"; | |||||
| COPY_PHASE_STRIP = NO; | |||||
| GCC_DYNAMIC_NO_PIC = NO; | |||||
| GCC_OPTIMIZATION_LEVEL = 0; | |||||
| GCC_PREPROCESSOR_DEFINITIONS = ( | |||||
| "_DEBUG=1", | |||||
| "DEBUG=1", | |||||
| "JUCER_XCODE_MAC_F6D2F4CF=1", | |||||
| "JUCE_APP_VERSION=1.0.0", | |||||
| "JUCE_APP_VERSION_HEX=0x10000", | |||||
| "JucePlugin_Build_VST=0", | |||||
| "JucePlugin_Build_VST3=0", | |||||
| "JucePlugin_Build_AU=0", | |||||
| "JucePlugin_Build_AUv3=0", | |||||
| "JucePlugin_Build_RTAS=0", | |||||
| "JucePlugin_Build_AAX=0", | |||||
| "JucePlugin_Build_Standalone=0", ); | |||||
| GCC_VERSION = com.apple.compilers.llvm.clang.1_0; | |||||
| HEADER_SEARCH_PATHS = ("../../JuceLibraryCode", "../../../../modules", "$(inherited)"); | |||||
| INFOPLIST_FILE = Info-App.plist; | |||||
| INFOPLIST_PREPROCESS = NO; | |||||
| INSTALL_PATH = "$(HOME)/Applications"; | |||||
| MACOSX_DEPLOYMENT_TARGET = 10.11; | |||||
| MACOSX_DEPLOYMENT_TARGET_ppc = 10.4; | |||||
| PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.AnalyticsCollection; | |||||
| SDKROOT_ppc = macosx10.5; | |||||
| USE_HEADERMAP = NO; }; name = Debug; }; | |||||
| 8575FCD908F2B0E4E641C1A0 = {isa = XCBuildConfiguration; buildSettings = { | |||||
| CLANG_CXX_LANGUAGE_STANDARD = "c++11"; | |||||
| CLANG_LINK_OBJC_RUNTIME = NO; | |||||
| COMBINE_HIDPI_IMAGES = YES; | |||||
| CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)"; | |||||
| DEAD_CODE_STRIPPING = YES; | |||||
| GCC_GENERATE_DEBUGGING_SYMBOLS = NO; | |||||
| GCC_OPTIMIZATION_LEVEL = 3; | |||||
| GCC_PREPROCESSOR_DEFINITIONS = ( | |||||
| "_NDEBUG=1", | |||||
| "NDEBUG=1", | |||||
| "JUCER_XCODE_MAC_F6D2F4CF=1", | |||||
| "JUCE_APP_VERSION=1.0.0", | |||||
| "JUCE_APP_VERSION_HEX=0x10000", | |||||
| "JucePlugin_Build_VST=0", | |||||
| "JucePlugin_Build_VST3=0", | |||||
| "JucePlugin_Build_AU=0", | |||||
| "JucePlugin_Build_AUv3=0", | |||||
| "JucePlugin_Build_RTAS=0", | |||||
| "JucePlugin_Build_AAX=0", | |||||
| "JucePlugin_Build_Standalone=0", ); | |||||
| GCC_SYMBOLS_PRIVATE_EXTERN = YES; | |||||
| GCC_VERSION = com.apple.compilers.llvm.clang.1_0; | |||||
| HEADER_SEARCH_PATHS = ("../../JuceLibraryCode", "../../../../modules", "$(inherited)"); | |||||
| INFOPLIST_FILE = Info-App.plist; | |||||
| INFOPLIST_PREPROCESS = NO; | |||||
| INSTALL_PATH = "$(HOME)/Applications"; | |||||
| MACOSX_DEPLOYMENT_TARGET = 10.11; | |||||
| MACOSX_DEPLOYMENT_TARGET_ppc = 10.4; | |||||
| PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.AnalyticsCollection; | |||||
| SDKROOT_ppc = macosx10.5; | |||||
| USE_HEADERMAP = NO; }; name = Release; }; | |||||
| 0399310F2F5034CFCB14437B = {isa = XCBuildConfiguration; buildSettings = { | |||||
| ALWAYS_SEARCH_USER_PATHS = NO; | |||||
| CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; | |||||
| CLANG_WARN_BOOL_CONVERSION = YES; | |||||
| CLANG_WARN_COMMA = YES; | |||||
| CLANG_WARN_CONSTANT_CONVERSION = YES; | |||||
| CLANG_WARN_EMPTY_BODY = YES; | |||||
| CLANG_WARN_ENUM_CONVERSION = YES; | |||||
| CLANG_WARN_INFINITE_RECURSION = YES; | |||||
| CLANG_WARN_INT_CONVERSION = YES; | |||||
| CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; | |||||
| CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; | |||||
| CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; | |||||
| CLANG_WARN_STRICT_PROTOTYPES = YES; | |||||
| CLANG_WARN_SUSPICIOUS_MOVE = YES; | |||||
| CLANG_WARN_UNREACHABLE_CODE = YES; | |||||
| CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; | |||||
| DEBUG_INFORMATION_FORMAT = "dwarf"; | |||||
| ENABLE_STRICT_OBJC_MSGSEND = YES; | |||||
| ENABLE_TESTABILITY = YES; | |||||
| GCC_C_LANGUAGE_STANDARD = c11; | |||||
| GCC_INLINES_ARE_PRIVATE_EXTERN = YES; | |||||
| GCC_MODEL_TUNING = G5; | |||||
| GCC_NO_COMMON_BLOCKS = YES; | |||||
| GCC_WARN_64_TO_32_BIT_CONVERSION = YES; | |||||
| GCC_WARN_ABOUT_RETURN_TYPE = YES; | |||||
| GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; | |||||
| GCC_WARN_MISSING_PARENTHESES = YES; | |||||
| GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; | |||||
| GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES; | |||||
| GCC_WARN_UNDECLARED_SELECTOR = YES; | |||||
| GCC_WARN_UNINITIALIZED_AUTOS = YES; | |||||
| GCC_WARN_UNUSED_FUNCTION = YES; | |||||
| GCC_WARN_UNUSED_VARIABLE = YES; | |||||
| ONLY_ACTIVE_ARCH = YES; | |||||
| PRODUCT_NAME = "AnalyticsCollection"; | |||||
| WARNING_CFLAGS = -Wreorder; | |||||
| ZERO_LINK = NO; }; name = Debug; }; | |||||
| D9987A1AC287063A4E090185 = {isa = XCBuildConfiguration; buildSettings = { | |||||
| ALWAYS_SEARCH_USER_PATHS = NO; | |||||
| CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; | |||||
| CLANG_WARN_BOOL_CONVERSION = YES; | |||||
| CLANG_WARN_COMMA = YES; | |||||
| CLANG_WARN_CONSTANT_CONVERSION = YES; | |||||
| CLANG_WARN_EMPTY_BODY = YES; | |||||
| CLANG_WARN_ENUM_CONVERSION = YES; | |||||
| CLANG_WARN_INFINITE_RECURSION = YES; | |||||
| CLANG_WARN_INT_CONVERSION = YES; | |||||
| CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; | |||||
| CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; | |||||
| CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; | |||||
| CLANG_WARN_STRICT_PROTOTYPES = YES; | |||||
| CLANG_WARN_SUSPICIOUS_MOVE = YES; | |||||
| CLANG_WARN_UNREACHABLE_CODE = YES; | |||||
| CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; | |||||
| DEBUG_INFORMATION_FORMAT = "dwarf"; | |||||
| ENABLE_STRICT_OBJC_MSGSEND = YES; | |||||
| GCC_C_LANGUAGE_STANDARD = c11; | |||||
| GCC_INLINES_ARE_PRIVATE_EXTERN = YES; | |||||
| GCC_MODEL_TUNING = G5; | |||||
| GCC_NO_COMMON_BLOCKS = YES; | |||||
| GCC_WARN_64_TO_32_BIT_CONVERSION = YES; | |||||
| GCC_WARN_ABOUT_RETURN_TYPE = YES; | |||||
| GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; | |||||
| GCC_WARN_MISSING_PARENTHESES = YES; | |||||
| GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; | |||||
| GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES; | |||||
| GCC_WARN_UNDECLARED_SELECTOR = YES; | |||||
| GCC_WARN_UNINITIALIZED_AUTOS = YES; | |||||
| GCC_WARN_UNUSED_FUNCTION = YES; | |||||
| GCC_WARN_UNUSED_VARIABLE = YES; | |||||
| PRODUCT_NAME = "AnalyticsCollection"; | |||||
| WARNING_CFLAGS = -Wreorder; | |||||
| ZERO_LINK = NO; }; name = Release; }; | |||||
| E1B8C9CDDA25A31AA3C9C1BC = {isa = PBXTargetDependency; target = 3195ADB3A101AAE977C998D2; }; | |||||
| 65535D1056F6B2C9C545923E = {isa = XCConfigurationList; buildConfigurations = ( | |||||
| 0399310F2F5034CFCB14437B, | |||||
| D9987A1AC287063A4E090185, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; | |||||
| 850BB95DDE68E87344778037 = {isa = XCConfigurationList; buildConfigurations = ( | |||||
| 6FF8E864589AD3C2C06BF546, | |||||
| 8575FCD908F2B0E4E641C1A0, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; | |||||
| 9DE971716CBA79E89467EFD0 = {isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( | |||||
| A0DA914E3E16F49D60A5A47F, ); runOnlyForDeploymentPostprocessing = 0; }; | |||||
| A01C1A7AFBB72E638096E0BA = {isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( | |||||
| D293FC19C031441D146F2410, | |||||
| 962036B1BB2EDB0F9D53E125, | |||||
| 6297B7A712B1E5A74311F162, | |||||
| 132F9FBC9EB36AF2E755325D, | |||||
| 805CDCC5840B0D713C286826, | |||||
| C09B5A3CD0643CF37C9CF851, | |||||
| A1DF340E80EC501B1DBE75A0, ); runOnlyForDeploymentPostprocessing = 0; }; | |||||
| 32F46511CABBD859FD1D427D = {isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( | |||||
| B45E888BC48139CA81112E4A, | |||||
| 375013DDDA026F2709E4FDAD, | |||||
| 877F68400FB5A15B39719C61, | |||||
| 38EE4929FFB8B83FB37B6E73, ); runOnlyForDeploymentPostprocessing = 0; }; | |||||
| 3195ADB3A101AAE977C998D2 = {isa = PBXNativeTarget; buildConfigurationList = 850BB95DDE68E87344778037; buildPhases = ( | |||||
| 9DE971716CBA79E89467EFD0, | |||||
| A01C1A7AFBB72E638096E0BA, | |||||
| 32F46511CABBD859FD1D427D, ); buildRules = ( ); dependencies = ( ); name = "AnalyticsCollection - App"; productName = AnalyticsCollection; productReference = 707149C59A1AF9752E428B97; productType = "com.apple.product-type.application"; }; | |||||
| 8C6201B9CB81795542E3302D = {isa = PBXProject; buildConfigurationList = 65535D1056F6B2C9C545923E; attributes = { LastUpgradeCheck = 0830; TargetAttributes = { 3195ADB3A101AAE977C998D2 = { SystemCapabilities = {com.apple.ApplicationGroups.iOS = { enabled = 0; }; com.apple.InAppPurchase = { enabled = 0; }; com.apple.InterAppAudio = { enabled = 0; }; com.apple.Push = { enabled = 0; }; com.apple.Sandbox = { enabled = 0; }; }; }; }; }; compatibilityVersion = "Xcode 3.2"; hasScannedForEncodings = 0; mainGroup = 5CB45B3816ED17D0620DDEBF; projectDirPath = ""; projectRoot = ""; targets = (3195ADB3A101AAE977C998D2); }; | |||||
| }; | |||||
| rootObject = 8C6201B9CB81795542E3302D; | |||||
| } | |||||
| @@ -0,0 +1,29 @@ | |||||
| <?xml version="1.0" encoding="UTF-8"?> | |||||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |||||
| <plist> | |||||
| <dict> | |||||
| <key>CFBundleExecutable</key> | |||||
| <string>${EXECUTABLE_NAME}</string> | |||||
| <key>CFBundleIconFile</key> | |||||
| <string></string> | |||||
| <key>CFBundleIdentifier</key> | |||||
| <string>com.yourcompany.AnalyticsCollection</string> | |||||
| <key>CFBundleName</key> | |||||
| <string>AnalyticsCollection</string> | |||||
| <key>CFBundleDisplayName</key> | |||||
| <string>AnalyticsCollection</string> | |||||
| <key>CFBundlePackageType</key> | |||||
| <string>APPL</string> | |||||
| <key>CFBundleSignature</key> | |||||
| <string>????</string> | |||||
| <key>CFBundleShortVersionString</key> | |||||
| <string>1.0.0</string> | |||||
| <key>CFBundleVersion</key> | |||||
| <string>1.0.0</string> | |||||
| <key>NSHumanReadableCopyright</key> | |||||
| <string></string> | |||||
| <key>NSHighResolutionCapable</key> | |||||
| <true/> | |||||
| </dict> | |||||
| </plist> | |||||
| @@ -0,0 +1,20 @@ | |||||
| Microsoft Visual Studio Solution File, Format Version 11.00 | |||||
| # Visual Studio 2017 | |||||
| Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AnalyticsCollection - App", "AnalyticsCollection_App.vcxproj", "{C52D63D2-B7D8-F34E-1B84-186CB9D963EB}" | |||||
| EndProject | |||||
| Global | |||||
| GlobalSection(SolutionConfigurationPlatforms) = preSolution | |||||
| Debug|x64 = Debug|x64 | |||||
| Release|x64 = Release|x64 | |||||
| EndGlobalSection | |||||
| GlobalSection(ProjectConfigurationPlatforms) = postSolution | |||||
| {C52D63D2-B7D8-F34E-1B84-186CB9D963EB}.Debug|x64.ActiveCfg = Debug|x64 | |||||
| {C52D63D2-B7D8-F34E-1B84-186CB9D963EB}.Debug|x64.Build.0 = Debug|x64 | |||||
| {C52D63D2-B7D8-F34E-1B84-186CB9D963EB}.Release|x64.ActiveCfg = Release|x64 | |||||
| {C52D63D2-B7D8-F34E-1B84-186CB9D963EB}.Release|x64.Build.0 = Release|x64 | |||||
| EndGlobalSection | |||||
| GlobalSection(SolutionProperties) = preSolution | |||||
| HideSolutionNode = FALSE | |||||
| EndGlobalSection | |||||
| EndGlobal | |||||
| @@ -0,0 +1,29 @@ | |||||
| #ifdef JUCE_USER_DEFINED_RC_FILE | |||||
| #include JUCE_USER_DEFINED_RC_FILE | |||||
| #else | |||||
| #undef WIN32_LEAN_AND_MEAN | |||||
| #define WIN32_LEAN_AND_MEAN | |||||
| #include <windows.h> | |||||
| VS_VERSION_INFO VERSIONINFO | |||||
| FILEVERSION 1,0,0,0 | |||||
| BEGIN | |||||
| BLOCK "StringFileInfo" | |||||
| BEGIN | |||||
| BLOCK "040904E4" | |||||
| BEGIN | |||||
| VALUE "FileDescription", "AnalyticsCollection\0" | |||||
| VALUE "FileVersion", "1.0.0\0" | |||||
| VALUE "ProductName", "AnalyticsCollection\0" | |||||
| VALUE "ProductVersion", "1.0.0\0" | |||||
| END | |||||
| END | |||||
| BLOCK "VarFileInfo" | |||||
| BEGIN | |||||
| VALUE "Translation", 0x409, 1252 | |||||
| END | |||||
| END | |||||
| #endif | |||||
| @@ -0,0 +1,265 @@ | |||||
| // !$*UTF8*$! | |||||
| { | |||||
| archiveVersion = 1; | |||||
| classes = { | |||||
| }; | |||||
| objectVersion = 46; | |||||
| objects = { | |||||
| 95AA57DF380DDDCD099D4000 = {isa = PBXBuildFile; fileRef = 707149C59A1AF9752E428B97; }; | |||||
| F7E415084D290C237F9E638A = {isa = PBXBuildFile; fileRef = A93F5541F6B3C067538499EF; }; | |||||
| A808E8D738B9BD079492797F = {isa = PBXBuildFile; fileRef = D87EBFBF8CF2D8160F22405B; }; | |||||
| 921F2D865DD5EBF5AA00DF38 = {isa = PBXBuildFile; fileRef = 644905C665C9F08A8700FE0D; }; | |||||
| 107547912F5D18FB3DD33009 = {isa = PBXBuildFile; fileRef = 192797C933B56812538409D4; }; | |||||
| 38EE4929FFB8B83FB37B6E73 = {isa = PBXBuildFile; fileRef = FBCE051A0BA6C9FA3E64B47B; }; | |||||
| F6BB4E84E37BD38B6CA3025E = {isa = PBXBuildFile; fileRef = E206CE5D6771CAAA3C56F465; }; | |||||
| 02E32ED5F96146B51FE4669C = {isa = PBXBuildFile; fileRef = BC02966C48A4F51E9A187E4A; }; | |||||
| D293FC19C031441D146F2410 = {isa = PBXBuildFile; fileRef = 6A86C9751E9DCFA62D4562DB; }; | |||||
| 962036B1BB2EDB0F9D53E125 = {isa = PBXBuildFile; fileRef = 33B9806EFA95DA05ACD9344E; }; | |||||
| 6297B7A712B1E5A74311F162 = {isa = PBXBuildFile; fileRef = 5DC0FF6BC4AE24FABC41F20E; }; | |||||
| 132F9FBC9EB36AF2E755325D = {isa = PBXBuildFile; fileRef = AD2CFF58DA5E1C6EDF9CC399; }; | |||||
| 805CDCC5840B0D713C286826 = {isa = PBXBuildFile; fileRef = A0DDFB3559C431E96EC59392; }; | |||||
| C09B5A3CD0643CF37C9CF851 = {isa = PBXBuildFile; fileRef = 61FADB63565026F559F43F3B; }; | |||||
| A1DF340E80EC501B1DBE75A0 = {isa = PBXBuildFile; fileRef = 65311EED96DCA9B62EBFEA04; }; | |||||
| 02589D465A73E0112B97BD3A = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_core"; path = "../../../../modules/juce_core"; sourceTree = "SOURCE_ROOT"; }; | |||||
| 192797C933B56812538409D4 = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; | |||||
| 1AA9DA887BE127DCED5228BB = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_events"; path = "../../../../modules/juce_events"; sourceTree = "SOURCE_ROOT"; }; | |||||
| 33B9806EFA95DA05ACD9344E = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "include_juce_analytics.cpp"; path = "../../JuceLibraryCode/include_juce_analytics.cpp"; sourceTree = "SOURCE_ROOT"; }; | |||||
| 5219A3D3BECB8C7135C90377 = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_gui_basics"; path = "../../../../modules/juce_gui_basics"; sourceTree = "SOURCE_ROOT"; }; | |||||
| 5DC0FF6BC4AE24FABC41F20E = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "include_juce_core.mm"; path = "../../JuceLibraryCode/include_juce_core.mm"; sourceTree = "SOURCE_ROOT"; }; | |||||
| 61FADB63565026F559F43F3B = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "include_juce_graphics.mm"; path = "../../JuceLibraryCode/include_juce_graphics.mm"; sourceTree = "SOURCE_ROOT"; }; | |||||
| 644905C665C9F08A8700FE0D = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreText.framework; path = System/Library/Frameworks/CoreText.framework; sourceTree = SDKROOT; }; | |||||
| 65311EED96DCA9B62EBFEA04 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "include_juce_gui_basics.mm"; path = "../../JuceLibraryCode/include_juce_gui_basics.mm"; sourceTree = "SOURCE_ROOT"; }; | |||||
| 6A86C9751E9DCFA62D4562DB = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Main.cpp; path = ../../Source/Main.cpp; sourceTree = "SOURCE_ROOT"; }; | |||||
| 707149C59A1AF9752E428B97 = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AnalyticsCollection.app; sourceTree = "BUILT_PRODUCTS_DIR"; }; | |||||
| 7A9FA859A2C2AE9FDDC99AD9 = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "Info-App.plist"; path = "Info-App.plist"; sourceTree = "SOURCE_ROOT"; }; | |||||
| 886AEA380A40C905503764EB = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_graphics"; path = "../../../../modules/juce_graphics"; sourceTree = "SOURCE_ROOT"; }; | |||||
| 8A74F3F7422C89A897D93397 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AppConfig.h; path = ../../JuceLibraryCode/AppConfig.h; sourceTree = "SOURCE_ROOT"; }; | |||||
| 8B927F72BA8726A064560942 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = GoogleAnalyticsDestination.h; path = ../../Source/GoogleAnalyticsDestination.h; sourceTree = "SOURCE_ROOT"; }; | |||||
| 91208A06115D573563996967 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = JuceHeader.h; path = ../../JuceLibraryCode/JuceHeader.h; sourceTree = "SOURCE_ROOT"; }; | |||||
| 996BEF5ADCE2EC85EB9F637F = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_data_structures"; path = "../../../../modules/juce_data_structures"; sourceTree = "SOURCE_ROOT"; }; | |||||
| A0DDFB3559C431E96EC59392 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "include_juce_events.mm"; path = "../../JuceLibraryCode/include_juce_events.mm"; sourceTree = "SOURCE_ROOT"; }; | |||||
| A93F5541F6B3C067538499EF = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; | |||||
| AD2CFF58DA5E1C6EDF9CC399 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "include_juce_data_structures.mm"; path = "../../JuceLibraryCode/include_juce_data_structures.mm"; sourceTree = "SOURCE_ROOT"; }; | |||||
| BC02966C48A4F51E9A187E4A = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = AnalyticsCollection/Images.xcassets; sourceTree = "SOURCE_ROOT"; }; | |||||
| D352CDB4CA7E8B21FAA83B8C = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MainComponent.h; path = ../../Source/MainComponent.h; sourceTree = "SOURCE_ROOT"; }; | |||||
| D87EBFBF8CF2D8160F22405B = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreImage.framework; path = System/Library/Frameworks/CoreImage.framework; sourceTree = SDKROOT; }; | |||||
| E206CE5D6771CAAA3C56F465 = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; | |||||
| F2CF007AA4C90AC7A5AD1604 = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_analytics"; path = "../../../../modules/juce_analytics"; sourceTree = "SOURCE_ROOT"; }; | |||||
| FBCE051A0BA6C9FA3E64B47B = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; | |||||
| D269FA28B5D6012AEFE0BF20 = {isa = PBXGroup; children = ( | |||||
| 8B927F72BA8726A064560942, | |||||
| D352CDB4CA7E8B21FAA83B8C, | |||||
| 6A86C9751E9DCFA62D4562DB, ); name = Source; sourceTree = "<group>"; }; | |||||
| 2B971235E85DF9D98B6FC8AF = {isa = PBXGroup; children = ( | |||||
| D269FA28B5D6012AEFE0BF20, ); name = AnalyticsCollection; sourceTree = "<group>"; }; | |||||
| 0B35DCE65DF34DECBF1D8118 = {isa = PBXGroup; children = ( | |||||
| F2CF007AA4C90AC7A5AD1604, | |||||
| 02589D465A73E0112B97BD3A, | |||||
| 996BEF5ADCE2EC85EB9F637F, | |||||
| 1AA9DA887BE127DCED5228BB, | |||||
| 886AEA380A40C905503764EB, | |||||
| 5219A3D3BECB8C7135C90377, ); name = "Juce Modules"; sourceTree = "<group>"; }; | |||||
| B24D9AE60E0CE5D1A75693B5 = {isa = PBXGroup; children = ( | |||||
| 8A74F3F7422C89A897D93397, | |||||
| 33B9806EFA95DA05ACD9344E, | |||||
| 5DC0FF6BC4AE24FABC41F20E, | |||||
| AD2CFF58DA5E1C6EDF9CC399, | |||||
| A0DDFB3559C431E96EC59392, | |||||
| 61FADB63565026F559F43F3B, | |||||
| 65311EED96DCA9B62EBFEA04, | |||||
| 91208A06115D573563996967, ); name = "Juce Library Code"; sourceTree = "<group>"; }; | |||||
| 782C3BD0C802236A266FDEDD = {isa = PBXGroup; children = ( | |||||
| 7A9FA859A2C2AE9FDDC99AD9, | |||||
| BC02966C48A4F51E9A187E4A, ); name = Resources; sourceTree = "<group>"; }; | |||||
| F70B9CB615E26A697D2CBEB4 = {isa = PBXGroup; children = ( | |||||
| A93F5541F6B3C067538499EF, | |||||
| D87EBFBF8CF2D8160F22405B, | |||||
| 644905C665C9F08A8700FE0D, | |||||
| 192797C933B56812538409D4, | |||||
| FBCE051A0BA6C9FA3E64B47B, | |||||
| E206CE5D6771CAAA3C56F465, ); name = Frameworks; sourceTree = "<group>"; }; | |||||
| 40E8A594A7EAFA1EF5707952 = {isa = PBXGroup; children = ( | |||||
| 707149C59A1AF9752E428B97, ); name = Products; sourceTree = "<group>"; }; | |||||
| 5CB45B3816ED17D0620DDEBF = {isa = PBXGroup; children = ( | |||||
| 2B971235E85DF9D98B6FC8AF, | |||||
| 0B35DCE65DF34DECBF1D8118, | |||||
| B24D9AE60E0CE5D1A75693B5, | |||||
| 782C3BD0C802236A266FDEDD, | |||||
| F70B9CB615E26A697D2CBEB4, | |||||
| 40E8A594A7EAFA1EF5707952, ); name = Source; sourceTree = "<group>"; }; | |||||
| 6FF8E864589AD3C2C06BF546 = {isa = XCBuildConfiguration; buildSettings = { | |||||
| ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; | |||||
| ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; | |||||
| CLANG_CXX_LANGUAGE_STANDARD = "c++11"; | |||||
| CLANG_LINK_OBJC_RUNTIME = NO; | |||||
| COMBINE_HIDPI_IMAGES = YES; | |||||
| CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)"; | |||||
| COPY_PHASE_STRIP = NO; | |||||
| GCC_DYNAMIC_NO_PIC = NO; | |||||
| GCC_OPTIMIZATION_LEVEL = 0; | |||||
| GCC_PREPROCESSOR_DEFINITIONS = ( | |||||
| "_DEBUG=1", | |||||
| "DEBUG=1", | |||||
| "JUCER_XCODE_IPHONE_5BC26AE3=1", | |||||
| "JUCE_APP_VERSION=1.0.0", | |||||
| "JUCE_APP_VERSION_HEX=0x10000", | |||||
| "JucePlugin_Build_VST=0", | |||||
| "JucePlugin_Build_VST3=0", | |||||
| "JucePlugin_Build_AU=0", | |||||
| "JucePlugin_Build_AUv3=0", | |||||
| "JucePlugin_Build_RTAS=0", | |||||
| "JucePlugin_Build_AAX=0", | |||||
| "JucePlugin_Build_Standalone=0", ); | |||||
| GCC_VERSION = com.apple.compilers.llvm.clang.1_0; | |||||
| HEADER_SEARCH_PATHS = ("../../JuceLibraryCode", "../../../../modules", "$(inherited)"); | |||||
| INFOPLIST_FILE = Info-App.plist; | |||||
| INFOPLIST_PREPROCESS = NO; | |||||
| INSTALL_PATH = "$(HOME)/Applications"; | |||||
| PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.AnalyticsCollection; | |||||
| USE_HEADERMAP = NO; }; name = Debug; }; | |||||
| 8575FCD908F2B0E4E641C1A0 = {isa = XCBuildConfiguration; buildSettings = { | |||||
| ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; | |||||
| ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; | |||||
| CLANG_CXX_LANGUAGE_STANDARD = "c++11"; | |||||
| CLANG_LINK_OBJC_RUNTIME = NO; | |||||
| COMBINE_HIDPI_IMAGES = YES; | |||||
| CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)"; | |||||
| DEAD_CODE_STRIPPING = YES; | |||||
| GCC_GENERATE_DEBUGGING_SYMBOLS = NO; | |||||
| GCC_OPTIMIZATION_LEVEL = 3; | |||||
| GCC_PREPROCESSOR_DEFINITIONS = ( | |||||
| "_NDEBUG=1", | |||||
| "NDEBUG=1", | |||||
| "JUCER_XCODE_IPHONE_5BC26AE3=1", | |||||
| "JUCE_APP_VERSION=1.0.0", | |||||
| "JUCE_APP_VERSION_HEX=0x10000", | |||||
| "JucePlugin_Build_VST=0", | |||||
| "JucePlugin_Build_VST3=0", | |||||
| "JucePlugin_Build_AU=0", | |||||
| "JucePlugin_Build_AUv3=0", | |||||
| "JucePlugin_Build_RTAS=0", | |||||
| "JucePlugin_Build_AAX=0", | |||||
| "JucePlugin_Build_Standalone=0", ); | |||||
| GCC_SYMBOLS_PRIVATE_EXTERN = YES; | |||||
| GCC_VERSION = com.apple.compilers.llvm.clang.1_0; | |||||
| HEADER_SEARCH_PATHS = ("../../JuceLibraryCode", "../../../../modules", "$(inherited)"); | |||||
| INFOPLIST_FILE = Info-App.plist; | |||||
| INFOPLIST_PREPROCESS = NO; | |||||
| INSTALL_PATH = "$(HOME)/Applications"; | |||||
| PRODUCT_BUNDLE_IDENTIFIER = com.yourcompany.AnalyticsCollection; | |||||
| USE_HEADERMAP = NO; }; name = Release; }; | |||||
| 0399310F2F5034CFCB14437B = {isa = XCBuildConfiguration; buildSettings = { | |||||
| "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; | |||||
| ALWAYS_SEARCH_USER_PATHS = NO; | |||||
| CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; | |||||
| CLANG_WARN_BOOL_CONVERSION = YES; | |||||
| CLANG_WARN_COMMA = YES; | |||||
| CLANG_WARN_CONSTANT_CONVERSION = YES; | |||||
| CLANG_WARN_EMPTY_BODY = YES; | |||||
| CLANG_WARN_ENUM_CONVERSION = YES; | |||||
| CLANG_WARN_INFINITE_RECURSION = YES; | |||||
| CLANG_WARN_INT_CONVERSION = YES; | |||||
| CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; | |||||
| CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; | |||||
| CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; | |||||
| CLANG_WARN_STRICT_PROTOTYPES = YES; | |||||
| CLANG_WARN_SUSPICIOUS_MOVE = YES; | |||||
| CLANG_WARN_UNREACHABLE_CODE = YES; | |||||
| CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; | |||||
| DEBUG_INFORMATION_FORMAT = "dwarf"; | |||||
| ENABLE_STRICT_OBJC_MSGSEND = YES; | |||||
| ENABLE_TESTABILITY = YES; | |||||
| GCC_C_LANGUAGE_STANDARD = c11; | |||||
| GCC_INLINES_ARE_PRIVATE_EXTERN = YES; | |||||
| GCC_MODEL_TUNING = G5; | |||||
| GCC_NO_COMMON_BLOCKS = YES; | |||||
| GCC_WARN_64_TO_32_BIT_CONVERSION = YES; | |||||
| GCC_WARN_ABOUT_RETURN_TYPE = YES; | |||||
| GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; | |||||
| GCC_WARN_MISSING_PARENTHESES = YES; | |||||
| GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; | |||||
| GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES; | |||||
| GCC_WARN_UNDECLARED_SELECTOR = YES; | |||||
| GCC_WARN_UNINITIALIZED_AUTOS = YES; | |||||
| GCC_WARN_UNUSED_FUNCTION = YES; | |||||
| GCC_WARN_UNUSED_VARIABLE = YES; | |||||
| IPHONEOS_DEPLOYMENT_TARGET = 9.3; | |||||
| ONLY_ACTIVE_ARCH = YES; | |||||
| PRODUCT_NAME = "AnalyticsCollection"; | |||||
| SDKROOT = iphoneos; | |||||
| TARGETED_DEVICE_FAMILY = "1,2"; | |||||
| WARNING_CFLAGS = -Wreorder; | |||||
| ZERO_LINK = NO; }; name = Debug; }; | |||||
| D9987A1AC287063A4E090185 = {isa = XCBuildConfiguration; buildSettings = { | |||||
| "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; | |||||
| ALWAYS_SEARCH_USER_PATHS = NO; | |||||
| CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; | |||||
| CLANG_WARN_BOOL_CONVERSION = YES; | |||||
| CLANG_WARN_COMMA = YES; | |||||
| CLANG_WARN_CONSTANT_CONVERSION = YES; | |||||
| CLANG_WARN_EMPTY_BODY = YES; | |||||
| CLANG_WARN_ENUM_CONVERSION = YES; | |||||
| CLANG_WARN_INFINITE_RECURSION = YES; | |||||
| CLANG_WARN_INT_CONVERSION = YES; | |||||
| CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; | |||||
| CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; | |||||
| CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; | |||||
| CLANG_WARN_STRICT_PROTOTYPES = YES; | |||||
| CLANG_WARN_SUSPICIOUS_MOVE = YES; | |||||
| CLANG_WARN_UNREACHABLE_CODE = YES; | |||||
| CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; | |||||
| DEBUG_INFORMATION_FORMAT = "dwarf"; | |||||
| ENABLE_STRICT_OBJC_MSGSEND = YES; | |||||
| GCC_C_LANGUAGE_STANDARD = c11; | |||||
| GCC_INLINES_ARE_PRIVATE_EXTERN = YES; | |||||
| GCC_MODEL_TUNING = G5; | |||||
| GCC_NO_COMMON_BLOCKS = YES; | |||||
| GCC_WARN_64_TO_32_BIT_CONVERSION = YES; | |||||
| GCC_WARN_ABOUT_RETURN_TYPE = YES; | |||||
| GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; | |||||
| GCC_WARN_MISSING_PARENTHESES = YES; | |||||
| GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; | |||||
| GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES; | |||||
| GCC_WARN_UNDECLARED_SELECTOR = YES; | |||||
| GCC_WARN_UNINITIALIZED_AUTOS = YES; | |||||
| GCC_WARN_UNUSED_FUNCTION = YES; | |||||
| GCC_WARN_UNUSED_VARIABLE = YES; | |||||
| IPHONEOS_DEPLOYMENT_TARGET = 9.3; | |||||
| PRODUCT_NAME = "AnalyticsCollection"; | |||||
| SDKROOT = iphoneos; | |||||
| TARGETED_DEVICE_FAMILY = "1,2"; | |||||
| WARNING_CFLAGS = -Wreorder; | |||||
| ZERO_LINK = NO; }; name = Release; }; | |||||
| E1B8C9CDDA25A31AA3C9C1BC = {isa = PBXTargetDependency; target = 3195ADB3A101AAE977C998D2; }; | |||||
| 65535D1056F6B2C9C545923E = {isa = XCConfigurationList; buildConfigurations = ( | |||||
| 0399310F2F5034CFCB14437B, | |||||
| D9987A1AC287063A4E090185, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; | |||||
| 850BB95DDE68E87344778037 = {isa = XCConfigurationList; buildConfigurations = ( | |||||
| 6FF8E864589AD3C2C06BF546, | |||||
| 8575FCD908F2B0E4E641C1A0, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; | |||||
| 9DE971716CBA79E89467EFD0 = {isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( | |||||
| 02E32ED5F96146B51FE4669C, ); runOnlyForDeploymentPostprocessing = 0; }; | |||||
| A01C1A7AFBB72E638096E0BA = {isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( | |||||
| D293FC19C031441D146F2410, | |||||
| 962036B1BB2EDB0F9D53E125, | |||||
| 6297B7A712B1E5A74311F162, | |||||
| 132F9FBC9EB36AF2E755325D, | |||||
| 805CDCC5840B0D713C286826, | |||||
| C09B5A3CD0643CF37C9CF851, | |||||
| A1DF340E80EC501B1DBE75A0, ); runOnlyForDeploymentPostprocessing = 0; }; | |||||
| 32F46511CABBD859FD1D427D = {isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( | |||||
| F7E415084D290C237F9E638A, | |||||
| A808E8D738B9BD079492797F, | |||||
| 921F2D865DD5EBF5AA00DF38, | |||||
| 107547912F5D18FB3DD33009, | |||||
| 38EE4929FFB8B83FB37B6E73, | |||||
| F6BB4E84E37BD38B6CA3025E, ); runOnlyForDeploymentPostprocessing = 0; }; | |||||
| 3195ADB3A101AAE977C998D2 = {isa = PBXNativeTarget; buildConfigurationList = 850BB95DDE68E87344778037; buildPhases = ( | |||||
| 9DE971716CBA79E89467EFD0, | |||||
| A01C1A7AFBB72E638096E0BA, | |||||
| 32F46511CABBD859FD1D427D, ); buildRules = ( ); dependencies = ( ); name = "AnalyticsCollection - App"; productName = AnalyticsCollection; productReference = 707149C59A1AF9752E428B97; productType = "com.apple.product-type.application"; }; | |||||
| 8C6201B9CB81795542E3302D = {isa = PBXProject; buildConfigurationList = 65535D1056F6B2C9C545923E; attributes = { LastUpgradeCheck = 0830; TargetAttributes = { 3195ADB3A101AAE977C998D2 = { SystemCapabilities = {com.apple.ApplicationGroups.iOS = { enabled = 0; }; com.apple.InAppPurchase = { enabled = 0; }; com.apple.InterAppAudio = { enabled = 0; }; com.apple.Push = { enabled = 0; }; com.apple.Sandbox = { enabled = 0; }; }; }; }; }; compatibilityVersion = "Xcode 3.2"; hasScannedForEncodings = 0; mainGroup = 5CB45B3816ED17D0620DDEBF; projectDirPath = ""; projectRoot = ""; targets = (3195ADB3A101AAE977C998D2); }; | |||||
| }; | |||||
| rootObject = 8C6201B9CB81795542E3302D; | |||||
| } | |||||
| @@ -0,0 +1,158 @@ | |||||
| { | |||||
| "images": [ | |||||
| { | |||||
| "idiom": "iphone", | |||||
| "size": "20x20", | |||||
| "filename": "Icon-Notification-20@2x.png", | |||||
| "scale": "2x" | |||||
| }, | |||||
| { | |||||
| "idiom": "iphone", | |||||
| "size": "20x20", | |||||
| "filename": "Icon-Notification-20@3x.png", | |||||
| "scale": "3x" | |||||
| }, | |||||
| { | |||||
| "idiom": "iphone", | |||||
| "size": "29x29", | |||||
| "filename": "Icon-29.png", | |||||
| "scale": "1x" | |||||
| }, | |||||
| { | |||||
| "idiom": "iphone", | |||||
| "size": "29x29", | |||||
| "filename": "Icon-29@2x.png", | |||||
| "scale": "2x" | |||||
| }, | |||||
| { | |||||
| "idiom": "iphone", | |||||
| "size": "29x29", | |||||
| "filename": "Icon-29@3x.png", | |||||
| "scale": "3x" | |||||
| }, | |||||
| { | |||||
| "idiom": "iphone", | |||||
| "size": "40x40", | |||||
| "filename": "Icon-Spotlight-40@2x.png", | |||||
| "scale": "2x" | |||||
| }, | |||||
| { | |||||
| "idiom": "iphone", | |||||
| "size": "40x40", | |||||
| "filename": "Icon-Spotlight-40@3x.png", | |||||
| "scale": "3x" | |||||
| }, | |||||
| { | |||||
| "idiom": "iphone", | |||||
| "size": "57x57", | |||||
| "filename": "Icon.png", | |||||
| "scale": "1x" | |||||
| }, | |||||
| { | |||||
| "idiom": "iphone", | |||||
| "size": "57x57", | |||||
| "filename": "Icon@2x.png", | |||||
| "scale": "2x" | |||||
| }, | |||||
| { | |||||
| "idiom": "iphone", | |||||
| "size": "60x60", | |||||
| "filename": "Icon-60@2x.png", | |||||
| "scale": "2x" | |||||
| }, | |||||
| { | |||||
| "idiom": "iphone", | |||||
| "size": "60x60", | |||||
| "filename": "Icon-@3x.png", | |||||
| "scale": "3x" | |||||
| }, | |||||
| { | |||||
| "idiom": "ipad", | |||||
| "size": "20x20", | |||||
| "filename": "Icon-Notifications-20.png", | |||||
| "scale": "1x" | |||||
| }, | |||||
| { | |||||
| "idiom": "ipad", | |||||
| "size": "20x20", | |||||
| "filename": "Icon-Notifications-20@2x.png", | |||||
| "scale": "2x" | |||||
| }, | |||||
| { | |||||
| "idiom": "ipad", | |||||
| "size": "29x29", | |||||
| "filename": "Icon-Small-1.png", | |||||
| "scale": "1x" | |||||
| }, | |||||
| { | |||||
| "idiom": "ipad", | |||||
| "size": "29x29", | |||||
| "filename": "Icon-Small@2x-1.png", | |||||
| "scale": "2x" | |||||
| }, | |||||
| { | |||||
| "idiom": "ipad", | |||||
| "size": "40x40", | |||||
| "filename": "Icon-Spotlight-40.png", | |||||
| "scale": "1x" | |||||
| }, | |||||
| { | |||||
| "idiom": "ipad", | |||||
| "size": "40x40", | |||||
| "filename": "Icon-Spotlight-40@2x-1.png", | |||||
| "scale": "2x" | |||||
| }, | |||||
| { | |||||
| "idiom": "ipad", | |||||
| "size": "50x50", | |||||
| "filename": "Icon-Small-50.png", | |||||
| "scale": "1x" | |||||
| }, | |||||
| { | |||||
| "idiom": "ipad", | |||||
| "size": "50x50", | |||||
| "filename": "Icon-Small-50@2x.png", | |||||
| "scale": "2x" | |||||
| }, | |||||
| { | |||||
| "idiom": "ipad", | |||||
| "size": "72x72", | |||||
| "filename": "Icon-72.png", | |||||
| "scale": "1x" | |||||
| }, | |||||
| { | |||||
| "idiom": "ipad", | |||||
| "size": "72x72", | |||||
| "filename": "Icon-72@2x.png", | |||||
| "scale": "2x" | |||||
| }, | |||||
| { | |||||
| "idiom": "ipad", | |||||
| "size": "76x76", | |||||
| "filename": "Icon-76.png", | |||||
| "scale": "1x" | |||||
| }, | |||||
| { | |||||
| "idiom": "ipad", | |||||
| "size": "76x76", | |||||
| "filename": "Icon-76@2x.png", | |||||
| "scale": "2x" | |||||
| }, | |||||
| { | |||||
| "idiom": "ipad", | |||||
| "size": "83.5x83.5", | |||||
| "filename": "Icon-83.5@2x.png", | |||||
| "scale": "2x" | |||||
| }, | |||||
| { | |||||
| "idiom": "ios-marketing", | |||||
| "size": "1024x1024", | |||||
| "filename": "Icon-AppStore-1024.png", | |||||
| "scale": "1x" | |||||
| } | |||||
| ], | |||||
| "info": { | |||||
| "version": 1, | |||||
| "author": "xcode" | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,57 @@ | |||||
| { | |||||
| "images": [ | |||||
| { | |||||
| "orientation": "portrait", | |||||
| "idiom": "iphone", | |||||
| "extent": "full-screen", | |||||
| "minimum-system-version": "7.0", | |||||
| "scale": "2x", | |||||
| "filename": "LaunchImage-iphone-2x.png" | |||||
| }, | |||||
| { | |||||
| "orientation": "portrait", | |||||
| "idiom": "iphone", | |||||
| "extent": "full-screen", | |||||
| "minimum-system-version": "7.0", | |||||
| "scale": "2x", | |||||
| "filename": "LaunchImage-iphone-retina4.png", | |||||
| "subtype": "retina4" | |||||
| }, | |||||
| { | |||||
| "orientation": "portrait", | |||||
| "idiom": "ipad", | |||||
| "extent": "full-screen", | |||||
| "minimum-system-version": "7.0", | |||||
| "scale": "1x", | |||||
| "filename": "LaunchImage-ipad-portrait-1x.png" | |||||
| }, | |||||
| { | |||||
| "orientation": "landscape", | |||||
| "idiom": "ipad", | |||||
| "extent": "full-screen", | |||||
| "minimum-system-version": "7.0", | |||||
| "scale": "1x", | |||||
| "filename": "LaunchImage-ipad-landscape-1x.png" | |||||
| }, | |||||
| { | |||||
| "orientation": "portrait", | |||||
| "idiom": "ipad", | |||||
| "extent": "full-screen", | |||||
| "minimum-system-version": "7.0", | |||||
| "scale": "2x", | |||||
| "filename": "LaunchImage-ipad-portrait-2x.png" | |||||
| }, | |||||
| { | |||||
| "orientation": "landscape", | |||||
| "idiom": "ipad", | |||||
| "extent": "full-screen", | |||||
| "minimum-system-version": "7.0", | |||||
| "scale": "2x", | |||||
| "filename": "LaunchImage-ipad-landscape-2x.png" | |||||
| } | |||||
| ], | |||||
| "info": { | |||||
| "version": 1, | |||||
| "author": "xcode" | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,43 @@ | |||||
| <?xml version="1.0" encoding="UTF-8"?> | |||||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |||||
| <plist> | |||||
| <dict> | |||||
| <key>LSRequiresIPhoneOS</key> | |||||
| <true/> | |||||
| <key>UIViewControllerBasedStatusBarAppearance</key> | |||||
| <false/> | |||||
| <key>CFBundleExecutable</key> | |||||
| <string>${EXECUTABLE_NAME}</string> | |||||
| <key>CFBundleIdentifier</key> | |||||
| <string>com.yourcompany.AnalyticsCollection</string> | |||||
| <key>CFBundleName</key> | |||||
| <string>AnalyticsCollection</string> | |||||
| <key>CFBundleDisplayName</key> | |||||
| <string>AnalyticsCollection</string> | |||||
| <key>CFBundlePackageType</key> | |||||
| <string>APPL</string> | |||||
| <key>CFBundleSignature</key> | |||||
| <string>????</string> | |||||
| <key>CFBundleShortVersionString</key> | |||||
| <string>1.0.0</string> | |||||
| <key>CFBundleVersion</key> | |||||
| <string>1.0.0</string> | |||||
| <key>NSHumanReadableCopyright</key> | |||||
| <string></string> | |||||
| <key>NSHighResolutionCapable</key> | |||||
| <true/> | |||||
| <key>UIRequiresFullScreen</key> | |||||
| <true/> | |||||
| <key>UIStatusBarHidden</key> | |||||
| <true/> | |||||
| <key>UISupportedInterfaceOrientations</key> | |||||
| <array> | |||||
| <string>UIInterfaceOrientationPortrait</string> | |||||
| <string>UIInterfaceOrientationLandscapeLeft</string> | |||||
| <string>UIInterfaceOrientationLandscapeRight</string> | |||||
| </array> | |||||
| <key>UIBackgroundModes</key> | |||||
| <array/> | |||||
| </dict> | |||||
| </plist> | |||||
| @@ -0,0 +1,138 @@ | |||||
| /* | |||||
| IMPORTANT! This file is auto-generated each time you save your | |||||
| project - if you alter its contents, your changes may be overwritten! | |||||
| There's a section below where you can add your own custom code safely, and the | |||||
| Projucer will preserve the contents of that block, but the best way to change | |||||
| any of these definitions is by using the Projucer's project settings. | |||||
| Any commented-out settings will assume their default values. | |||||
| */ | |||||
| #pragma once | |||||
| //============================================================================== | |||||
| // [BEGIN_USER_CODE_SECTION] | |||||
| // (You can add your own code in this section, and the Projucer will not overwrite it) | |||||
| // [END_USER_CODE_SECTION] | |||||
| /* | |||||
| ============================================================================== | |||||
| In accordance with the terms of the JUCE 5 End-Use License Agreement, the | |||||
| JUCE Code in SECTION A cannot be removed, changed or otherwise rendered | |||||
| ineffective unless you have a JUCE Indie or Pro license, or are using JUCE | |||||
| under the GPL v3 license. | |||||
| End User License Agreement: www.juce.com/juce-5-licence | |||||
| ============================================================================== | |||||
| */ | |||||
| // BEGIN SECTION A | |||||
| #ifndef JUCE_DISPLAY_SPLASH_SCREEN | |||||
| #define JUCE_DISPLAY_SPLASH_SCREEN 0 | |||||
| #endif | |||||
| #ifndef JUCE_REPORT_APP_USAGE | |||||
| #define JUCE_REPORT_APP_USAGE 0 | |||||
| #endif | |||||
| // END SECTION A | |||||
| #define JUCE_USE_DARK_SPLASH_SCREEN 1 | |||||
| //============================================================================== | |||||
| #define JUCE_MODULE_AVAILABLE_juce_analytics 1 | |||||
| #define JUCE_MODULE_AVAILABLE_juce_core 1 | |||||
| #define JUCE_MODULE_AVAILABLE_juce_data_structures 1 | |||||
| #define JUCE_MODULE_AVAILABLE_juce_events 1 | |||||
| #define JUCE_MODULE_AVAILABLE_juce_graphics 1 | |||||
| #define JUCE_MODULE_AVAILABLE_juce_gui_basics 1 | |||||
| #define JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED 1 | |||||
| //============================================================================== | |||||
| // juce_core flags: | |||||
| #ifndef JUCE_FORCE_DEBUG | |||||
| //#define JUCE_FORCE_DEBUG 1 | |||||
| #endif | |||||
| #ifndef JUCE_LOG_ASSERTIONS | |||||
| //#define JUCE_LOG_ASSERTIONS 1 | |||||
| #endif | |||||
| #ifndef JUCE_CHECK_MEMORY_LEAKS | |||||
| //#define JUCE_CHECK_MEMORY_LEAKS 1 | |||||
| #endif | |||||
| #ifndef JUCE_DONT_AUTOLINK_TO_WIN32_LIBRARIES | |||||
| //#define JUCE_DONT_AUTOLINK_TO_WIN32_LIBRARIES 1 | |||||
| #endif | |||||
| #ifndef JUCE_INCLUDE_ZLIB_CODE | |||||
| //#define JUCE_INCLUDE_ZLIB_CODE 1 | |||||
| #endif | |||||
| #ifndef JUCE_USE_CURL | |||||
| //#define JUCE_USE_CURL 1 | |||||
| #endif | |||||
| #ifndef JUCE_CATCH_UNHANDLED_EXCEPTIONS | |||||
| //#define JUCE_CATCH_UNHANDLED_EXCEPTIONS 1 | |||||
| #endif | |||||
| #ifndef JUCE_ALLOW_STATIC_NULL_VARIABLES | |||||
| //#define JUCE_ALLOW_STATIC_NULL_VARIABLES 1 | |||||
| #endif | |||||
| //============================================================================== | |||||
| // juce_events flags: | |||||
| #ifndef JUCE_EXECUTE_APP_SUSPEND_ON_IOS_BACKGROUND_TASK | |||||
| //#define JUCE_EXECUTE_APP_SUSPEND_ON_IOS_BACKGROUND_TASK 1 | |||||
| #endif | |||||
| //============================================================================== | |||||
| // juce_graphics flags: | |||||
| #ifndef JUCE_USE_COREIMAGE_LOADER | |||||
| //#define JUCE_USE_COREIMAGE_LOADER 1 | |||||
| #endif | |||||
| #ifndef JUCE_USE_DIRECTWRITE | |||||
| //#define JUCE_USE_DIRECTWRITE 1 | |||||
| #endif | |||||
| //============================================================================== | |||||
| // juce_gui_basics flags: | |||||
| #ifndef JUCE_ENABLE_REPAINT_DEBUGGING | |||||
| //#define JUCE_ENABLE_REPAINT_DEBUGGING 1 | |||||
| #endif | |||||
| #ifndef JUCE_USE_XSHM | |||||
| //#define JUCE_USE_XSHM 1 | |||||
| #endif | |||||
| #ifndef JUCE_USE_XRENDER | |||||
| //#define JUCE_USE_XRENDER 1 | |||||
| #endif | |||||
| #ifndef JUCE_USE_XCURSOR | |||||
| //#define JUCE_USE_XCURSOR 1 | |||||
| #endif | |||||
| //============================================================================== | |||||
| #ifndef JUCE_STANDALONE_APPLICATION | |||||
| #if defined(JucePlugin_Name) && defined(JucePlugin_Build_Standalone) | |||||
| #define JUCE_STANDALONE_APPLICATION JucePlugin_Build_Standalone | |||||
| #else | |||||
| #define JUCE_STANDALONE_APPLICATION 1 | |||||
| #endif | |||||
| #endif | |||||
| @@ -0,0 +1,38 @@ | |||||
| /* | |||||
| IMPORTANT! This file is auto-generated each time you save your | |||||
| project - if you alter its contents, your changes may be overwritten! | |||||
| This is the header file that your files should include in order to get all the | |||||
| JUCE library headers. You should avoid including the JUCE headers directly in | |||||
| your own source files, because that wouldn't pick up the correct configuration | |||||
| options for your app. | |||||
| */ | |||||
| #pragma once | |||||
| #include "AppConfig.h" | |||||
| #include <juce_analytics/juce_analytics.h> | |||||
| #include <juce_core/juce_core.h> | |||||
| #include <juce_data_structures/juce_data_structures.h> | |||||
| #include <juce_events/juce_events.h> | |||||
| #include <juce_graphics/juce_graphics.h> | |||||
| #include <juce_gui_basics/juce_gui_basics.h> | |||||
| #if ! DONT_SET_USING_JUCE_NAMESPACE | |||||
| // If your code uses a lot of JUCE classes, then this will obviously save you | |||||
| // a lot of typing, but can be disabled by setting DONT_SET_USING_JUCE_NAMESPACE. | |||||
| using namespace juce; | |||||
| #endif | |||||
| #if ! JUCE_DONT_DECLARE_PROJECTINFO | |||||
| namespace ProjectInfo | |||||
| { | |||||
| const char* const projectName = "AnalyticsCollection"; | |||||
| const char* const versionString = "1.0.0"; | |||||
| const int versionNumber = 0x10000; | |||||
| } | |||||
| #endif | |||||
| @@ -0,0 +1,12 @@ | |||||
| Important Note!! | |||||
| ================ | |||||
| The purpose of this folder is to contain files that are auto-generated by the Projucer, | |||||
| and ALL files in this folder will be mercilessly DELETED and completely re-written whenever | |||||
| the Projucer saves your project. | |||||
| Therefore, it's a bad idea to make any manual changes to the files in here, or to | |||||
| put any of your own files in here if you don't want to lose them. (Of course you may choose | |||||
| to add the folder's contents to your version-control system so that you can re-merge your own | |||||
| modifications after the Projucer has saved its changes). | |||||
| @@ -0,0 +1,9 @@ | |||||
| /* | |||||
| IMPORTANT! This file is auto-generated each time you save your | |||||
| project - if you alter its contents, your changes may be overwritten! | |||||
| */ | |||||
| #include "AppConfig.h" | |||||
| #include <juce_analytics/juce_analytics.cpp> | |||||
| @@ -0,0 +1,9 @@ | |||||
| /* | |||||
| IMPORTANT! This file is auto-generated each time you save your | |||||
| project - if you alter its contents, your changes may be overwritten! | |||||
| */ | |||||
| #include "AppConfig.h" | |||||
| #include <juce_core/juce_core.cpp> | |||||
| @@ -0,0 +1,9 @@ | |||||
| /* | |||||
| IMPORTANT! This file is auto-generated each time you save your | |||||
| project - if you alter its contents, your changes may be overwritten! | |||||
| */ | |||||
| #include "AppConfig.h" | |||||
| #include <juce_core/juce_core.mm> | |||||
| @@ -0,0 +1,9 @@ | |||||
| /* | |||||
| IMPORTANT! This file is auto-generated each time you save your | |||||
| project - if you alter its contents, your changes may be overwritten! | |||||
| */ | |||||
| #include "AppConfig.h" | |||||
| #include <juce_data_structures/juce_data_structures.cpp> | |||||
| @@ -0,0 +1,9 @@ | |||||
| /* | |||||
| IMPORTANT! This file is auto-generated each time you save your | |||||
| project - if you alter its contents, your changes may be overwritten! | |||||
| */ | |||||
| #include "AppConfig.h" | |||||
| #include <juce_data_structures/juce_data_structures.mm> | |||||
| @@ -0,0 +1,9 @@ | |||||
| /* | |||||
| IMPORTANT! This file is auto-generated each time you save your | |||||
| project - if you alter its contents, your changes may be overwritten! | |||||
| */ | |||||
| #include "AppConfig.h" | |||||
| #include <juce_events/juce_events.cpp> | |||||
| @@ -0,0 +1,9 @@ | |||||
| /* | |||||
| IMPORTANT! This file is auto-generated each time you save your | |||||
| project - if you alter its contents, your changes may be overwritten! | |||||
| */ | |||||
| #include "AppConfig.h" | |||||
| #include <juce_events/juce_events.mm> | |||||
| @@ -0,0 +1,9 @@ | |||||
| /* | |||||
| IMPORTANT! This file is auto-generated each time you save your | |||||
| project - if you alter its contents, your changes may be overwritten! | |||||
| */ | |||||
| #include "AppConfig.h" | |||||
| #include <juce_graphics/juce_graphics.cpp> | |||||
| @@ -0,0 +1,9 @@ | |||||
| /* | |||||
| IMPORTANT! This file is auto-generated each time you save your | |||||
| project - if you alter its contents, your changes may be overwritten! | |||||
| */ | |||||
| #include "AppConfig.h" | |||||
| #include <juce_graphics/juce_graphics.mm> | |||||
| @@ -0,0 +1,9 @@ | |||||
| /* | |||||
| IMPORTANT! This file is auto-generated each time you save your | |||||
| project - if you alter its contents, your changes may be overwritten! | |||||
| */ | |||||
| #include "AppConfig.h" | |||||
| #include <juce_gui_basics/juce_gui_basics.cpp> | |||||
| @@ -0,0 +1,9 @@ | |||||
| /* | |||||
| IMPORTANT! This file is auto-generated each time you save your | |||||
| project - if you alter its contents, your changes may be overwritten! | |||||
| */ | |||||
| #include "AppConfig.h" | |||||
| #include <juce_gui_basics/juce_gui_basics.mm> | |||||
| @@ -0,0 +1,217 @@ | |||||
| #include "../JuceLibraryCode/JuceHeader.h" | |||||
| class GoogleAnalyticsDestination : public ThreadedAnalyticsDestination | |||||
| { | |||||
| public: | |||||
| GoogleAnalyticsDestination() | |||||
| : ThreadedAnalyticsDestination ("GoogleAnalyticsThread") | |||||
| { | |||||
| { | |||||
| // Choose where to save any unsent events. | |||||
| auto appDataDir = File::getSpecialLocation (File::userApplicationDataDirectory) | |||||
| .getChildFile (JUCEApplication::getInstance()->getApplicationName()); | |||||
| if (! appDataDir.exists()) | |||||
| appDataDir.createDirectory(); | |||||
| savedEventsFile = appDataDir.getChildFile ("analytics_events.xml"); | |||||
| } | |||||
| { | |||||
| // It's often a good idea to construct any analytics service API keys | |||||
| // at runtime, so they're not searchable in the binary distribution of | |||||
| // your application (but we've not done this here). You should replace | |||||
| // the following key with your own to get this example application | |||||
| // fully working. | |||||
| apiKey = "UA-XXXXXXXXX-1"; | |||||
| } | |||||
| startAnalyticsThread (initialPeriodMs); | |||||
| } | |||||
| ~GoogleAnalyticsDestination() | |||||
| { | |||||
| // Here we sleep so that our background thread has a chance to send the | |||||
| // last lot of batched events. Be careful - if your app takes too long to | |||||
| // shut down then some operating systems will kill it forcibly! | |||||
| Thread::sleep (initialPeriodMs); | |||||
| stopAnalyticsThread (1000); | |||||
| } | |||||
| int getMaximumBatchSize() override { return 20; } | |||||
| bool logBatchedEvents (const Array<AnalyticsEvent>& events) override | |||||
| { | |||||
| // Send events to Google Analytics. | |||||
| String appData ("v=1&tid=" + apiKey + "&t=event&"); | |||||
| StringArray postData; | |||||
| for (auto& event : events) | |||||
| { | |||||
| StringPairArray data; | |||||
| if (event.name == "startup") | |||||
| { | |||||
| data.set ("ec", "info"); | |||||
| data.set ("ea", "appStarted"); | |||||
| } | |||||
| else if (event.name == "shutdown") | |||||
| { | |||||
| data.set ("ec", "info"); | |||||
| data.set ("ea", "appStopped"); | |||||
| } | |||||
| else if (event.name == "button_press") | |||||
| { | |||||
| data.set ("ec", "button_press"); | |||||
| data.set ("ea", event.parameters["id"]); | |||||
| } | |||||
| else | |||||
| { | |||||
| continue; | |||||
| } | |||||
| data.set ("cid", event.userID); | |||||
| StringArray eventData; | |||||
| for (auto& key : data.getAllKeys()) | |||||
| eventData.add (key + "=" + URL::addEscapeChars (data[key], true)); | |||||
| postData.add (appData + eventData.joinIntoString ("&")); | |||||
| } | |||||
| auto url = URL ("https://www.google-analytics.com/batch") | |||||
| .withPOSTData (postData.joinIntoString ("\n")); | |||||
| { | |||||
| const ScopedLock lock (webStreamCreation); | |||||
| if (shouldExit) | |||||
| return false; | |||||
| webStream = new WebInputStream (url, true); | |||||
| } | |||||
| const auto success = webStream->connect (nullptr); | |||||
| // Do an exponential backoff if we failed to connect. | |||||
| if (success) | |||||
| periodMs = initialPeriodMs; | |||||
| else | |||||
| periodMs *= 2; | |||||
| setBatchPeriod (periodMs); | |||||
| return success; | |||||
| } | |||||
| void stopLoggingEvents() override | |||||
| { | |||||
| const ScopedLock lock (webStreamCreation); | |||||
| shouldExit = true; | |||||
| if (webStream != nullptr) | |||||
| webStream->cancel(); | |||||
| } | |||||
| private: | |||||
| void saveUnloggedEvents (const std::deque<AnalyticsEvent>& eventsToSave) override | |||||
| { | |||||
| // Save unsent events to disk. Here we use XML as a serialisation format, but | |||||
| // you can use anything else as long as the restoreUnloggedEvents method can | |||||
| // restore events from disk. If you're saving very large numbers of events then | |||||
| // a binary format may be more suitable if it is faster - remember that this | |||||
| // method is called on app shutdown so it needs to complete quickly! | |||||
| XmlDocument previouslySavedEvents (savedEventsFile); | |||||
| ScopedPointer<XmlElement> xml = previouslySavedEvents.getDocumentElement(); | |||||
| if (xml == nullptr || xml->getTagName() != "events") | |||||
| xml = new XmlElement ("events"); | |||||
| for (auto& event : eventsToSave) | |||||
| { | |||||
| auto* xmlEvent = new XmlElement ("google_analytics_event"); | |||||
| xmlEvent->setAttribute ("name", event.name); | |||||
| xmlEvent->setAttribute ("timestamp", (int) event.timestamp); | |||||
| xmlEvent->setAttribute ("user_id", event.userID); | |||||
| auto* parameters = new XmlElement ("parameters"); | |||||
| for (auto& key : event.parameters.getAllKeys()) | |||||
| parameters->setAttribute (key, event.parameters[key]); | |||||
| xmlEvent->addChildElement (parameters); | |||||
| auto* userProperties = new XmlElement ("user_properties"); | |||||
| for (auto& key : event.userProperties.getAllKeys()) | |||||
| userProperties->setAttribute (key, event.userProperties[key]); | |||||
| xmlEvent->addChildElement (userProperties); | |||||
| xml->addChildElement (xmlEvent); | |||||
| } | |||||
| xml->writeToFile (savedEventsFile, {}); | |||||
| } | |||||
| void restoreUnloggedEvents (std::deque<AnalyticsEvent>& restoredEventQueue) override | |||||
| { | |||||
| XmlDocument savedEvents (savedEventsFile); | |||||
| ScopedPointer<XmlElement> xml = savedEvents.getDocumentElement(); | |||||
| if (xml == nullptr || xml->getTagName() != "events") | |||||
| return; | |||||
| const auto numEvents = xml->getNumChildElements(); | |||||
| for (auto iEvent = 0; iEvent < numEvents; ++iEvent) | |||||
| { | |||||
| const auto* xmlEvent = xml->getChildElement (iEvent); | |||||
| StringPairArray parameters; | |||||
| const auto* xmlParameters = xmlEvent->getChildByName ("parameters"); | |||||
| const auto numParameters = xmlParameters->getNumAttributes(); | |||||
| for (auto iParam = 0; iParam < numParameters; ++iParam) | |||||
| parameters.set (xmlParameters->getAttributeName (iParam), | |||||
| xmlParameters->getAttributeValue (iParam)); | |||||
| StringPairArray userProperties; | |||||
| const auto* xmlUserProperties = xmlEvent->getChildByName ("user_properties"); | |||||
| const auto numUserProperties = xmlUserProperties->getNumAttributes(); | |||||
| for (auto iProp = 0; iProp < numUserProperties; ++iProp) | |||||
| userProperties.set (xmlUserProperties->getAttributeName (iProp), | |||||
| xmlUserProperties->getAttributeValue (iProp)); | |||||
| restoredEventQueue.push_back ({ | |||||
| xmlEvent->getStringAttribute ("name"), | |||||
| (uint32) xmlEvent->getIntAttribute ("timestamp"), | |||||
| parameters, | |||||
| xmlEvent->getStringAttribute ("user_id"), | |||||
| userProperties | |||||
| }); | |||||
| } | |||||
| savedEventsFile.deleteFile(); | |||||
| } | |||||
| const int initialPeriodMs = 1000; | |||||
| int periodMs = initialPeriodMs; | |||||
| CriticalSection webStreamCreation; | |||||
| bool shouldExit = false; | |||||
| ScopedPointer<WebInputStream> webStream; | |||||
| String apiKey; | |||||
| File savedEventsFile; | |||||
| }; | |||||
| @@ -0,0 +1,106 @@ | |||||
| #include "../JuceLibraryCode/JuceHeader.h" | |||||
| #include "GoogleAnalyticsDestination.h" | |||||
| #include "MainComponent.h" | |||||
| //============================================================================== | |||||
| class AnalyticsCollectionApplication : public JUCEApplication | |||||
| { | |||||
| public: | |||||
| //============================================================================== | |||||
| AnalyticsCollectionApplication() {} | |||||
| const String getApplicationName() override { return ProjectInfo::projectName; } | |||||
| const String getApplicationVersion() override { return ProjectInfo::versionString; } | |||||
| bool moreThanOneInstanceAllowed() override { return true; } | |||||
| //============================================================================== | |||||
| void initialise (const String&) override | |||||
| { | |||||
| // Add an analytics identifier for the user. Make sure you don't collect | |||||
| // identifiable information accidentally if you haven't asked for permission! | |||||
| Analytics::getInstance()->setUserId ("AnonUser1234"); | |||||
| // Add any other constant user information. | |||||
| StringPairArray userData; | |||||
| userData.set ("group", "beta"); | |||||
| Analytics::getInstance()->setUserProperties (userData); | |||||
| // Add any analytics destinations we want to use to the Analytics singleton. | |||||
| Analytics::getInstance()->addDestination (new GoogleAnalyticsDestination()); | |||||
| Analytics::getInstance()->logEvent ("startup", {}); | |||||
| mainWindow = new MainWindow (getApplicationName()); | |||||
| } | |||||
| void shutdown() override | |||||
| { | |||||
| Analytics::getInstance()->logEvent ("shutdown", {}); | |||||
| // Add your application's shutdown code here.. | |||||
| mainWindow = nullptr; // (deletes our window) | |||||
| } | |||||
| //============================================================================== | |||||
| void systemRequestedQuit() override | |||||
| { | |||||
| // This is called when the app is being asked to quit: you can ignore this | |||||
| // request and let the app carry on running, or call quit() to allow the app to close. | |||||
| quit(); | |||||
| } | |||||
| void anotherInstanceStarted (const String&) override | |||||
| { | |||||
| // When another instance of the app is launched while this one is running, | |||||
| // this method is invoked, and the commandLine parameter tells you what | |||||
| // the other instance's command-line arguments were. | |||||
| } | |||||
| //============================================================================== | |||||
| /* | |||||
| This class implements the desktop window that contains an instance of | |||||
| our MainContentComponent class. | |||||
| */ | |||||
| class MainWindow : public DocumentWindow | |||||
| { | |||||
| public: | |||||
| MainWindow (String name) : DocumentWindow (name, | |||||
| Desktop::getInstance().getDefaultLookAndFeel() | |||||
| .findColour (ResizableWindow::backgroundColourId), | |||||
| DocumentWindow::allButtons) | |||||
| { | |||||
| setUsingNativeTitleBar (true); | |||||
| setContentOwned (new MainContentComponent(), true); | |||||
| centreWithSize (getWidth(), getHeight()); | |||||
| setVisible (true); | |||||
| } | |||||
| void closeButtonPressed() override | |||||
| { | |||||
| // This is called when the user tries to close this window. Here, we'll just | |||||
| // ask the app to quit when this happens, but you can change this to do | |||||
| // whatever you need. | |||||
| JUCEApplication::getInstance()->systemRequestedQuit(); | |||||
| } | |||||
| /* Note: Be careful if you override any DocumentWindow methods - the base | |||||
| class uses a lot of them, so by overriding you might break its functionality. | |||||
| It's best to do all your work in your content component instead, but if | |||||
| you really have to override any DocumentWindow methods, make sure your | |||||
| subclass also calls the superclass's method. | |||||
| */ | |||||
| private: | |||||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainWindow) | |||||
| }; | |||||
| private: | |||||
| ScopedPointer<MainWindow> mainWindow; | |||||
| }; | |||||
| //============================================================================== | |||||
| // This macro generates the main() routine that launches the app. | |||||
| START_JUCE_APPLICATION (AnalyticsCollectionApplication) | |||||
| @@ -0,0 +1,38 @@ | |||||
| #pragma once | |||||
| #include "../JuceLibraryCode/JuceHeader.h" | |||||
| class MainContentComponent : public Component | |||||
| { | |||||
| public: | |||||
| //============================================================================== | |||||
| MainContentComponent() | |||||
| { | |||||
| addAndMakeVisible (eventButton); | |||||
| setSize (300, 200); | |||||
| StringPairArray logButtonPressParameters; | |||||
| logButtonPressParameters.set ("id", "a"); | |||||
| logEventButtonPress = new ButtonTracker (eventButton, "button_press", logButtonPressParameters); | |||||
| } | |||||
| ~MainContentComponent() {} | |||||
| void paint (Graphics& g) override | |||||
| { | |||||
| g.fillAll (getLookAndFeel().findColour (ResizableWindow::backgroundColourId)); | |||||
| } | |||||
| void resized() override | |||||
| { | |||||
| eventButton.centreWithSize (100, 50); | |||||
| } | |||||
| private: | |||||
| //============================================================================== | |||||
| TextButton eventButton { "Press me!" }; | |||||
| ScopedPointer<ButtonTracker> logEventButtonPress; | |||||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainContentComponent) | |||||
| }; | |||||
| @@ -39,6 +39,7 @@ | |||||
| <MODULEPATH id="juce_audio_utils" path="../../modules"/> | <MODULEPATH id="juce_audio_utils" path="../../modules"/> | ||||
| <MODULEPATH id="juce_blocks_basics" path="../../modules"/> | <MODULEPATH id="juce_blocks_basics" path="../../modules"/> | ||||
| <MODULEPATH id="juce_product_unlocking" path="../../modules"/> | <MODULEPATH id="juce_product_unlocking" path="../../modules"/> | ||||
| <MODULEPATH id="juce_analytics" path="../../modules"/> | |||||
| </MODULEPATHS> | </MODULEPATHS> | ||||
| </XCODE_MAC> | </XCODE_MAC> | ||||
| <LINUX_MAKE targetFolder="Builds/LinuxMakefile"> | <LINUX_MAKE targetFolder="Builds/LinuxMakefile"> | ||||
| @@ -67,6 +68,7 @@ | |||||
| <MODULEPATH id="juce_audio_utils" path="../../modules"/> | <MODULEPATH id="juce_audio_utils" path="../../modules"/> | ||||
| <MODULEPATH id="juce_blocks_basics" path="../../modules"/> | <MODULEPATH id="juce_blocks_basics" path="../../modules"/> | ||||
| <MODULEPATH id="juce_product_unlocking" path="../../modules"/> | <MODULEPATH id="juce_product_unlocking" path="../../modules"/> | ||||
| <MODULEPATH id="juce_analytics" path="../../modules"/> | |||||
| </MODULEPATHS> | </MODULEPATHS> | ||||
| </LINUX_MAKE> | </LINUX_MAKE> | ||||
| <VS2017 targetFolder="Builds/VisualStudio2017"> | <VS2017 targetFolder="Builds/VisualStudio2017"> | ||||
| @@ -97,10 +99,12 @@ | |||||
| <MODULEPATH id="juce_audio_formats" path="../../modules"/> | <MODULEPATH id="juce_audio_formats" path="../../modules"/> | ||||
| <MODULEPATH id="juce_audio_devices" path="../../modules"/> | <MODULEPATH id="juce_audio_devices" path="../../modules"/> | ||||
| <MODULEPATH id="juce_audio_basics" path="../../modules"/> | <MODULEPATH id="juce_audio_basics" path="../../modules"/> | ||||
| <MODULEPATH id="juce_analytics" path="../../modules"/> | |||||
| </MODULEPATHS> | </MODULEPATHS> | ||||
| </VS2017> | </VS2017> | ||||
| </EXPORTFORMATS> | </EXPORTFORMATS> | ||||
| <MODULES> | <MODULES> | ||||
| <MODULE id="juce_analytics" showAllCode="1" useLocalCopy="0" useGlobalPath="0"/> | |||||
| <MODULES id="juce_audio_basics" showAllCode="1" useLocalCopy="0"/> | <MODULES id="juce_audio_basics" showAllCode="1" useLocalCopy="0"/> | ||||
| <MODULES id="juce_audio_devices" showAllCode="1" useLocalCopy="0"/> | <MODULES id="juce_audio_devices" showAllCode="1" useLocalCopy="0"/> | ||||
| <MODULES id="juce_audio_formats" showAllCode="1" useLocalCopy="0"/> | <MODULES id="juce_audio_formats" showAllCode="1" useLocalCopy="0"/> | ||||
| @@ -0,0 +1,67 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library. | |||||
| Copyright (c) 2017 - ROLI Ltd. | |||||
| JUCE is an open source library subject to commercial or open-source | |||||
| licensing. | |||||
| The code included in this file is provided under the terms of the ISC license | |||||
| http://www.isc.org/downloads/software-support-policy/isc-license. Permission | |||||
| To use, copy, modify, and/or distribute this software for any purpose with or | |||||
| without fee is hereby granted provided that the above copyright notice and | |||||
| this permission notice appear in all copies. | |||||
| JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | |||||
| EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | |||||
| DISCLAIMED. | |||||
| ============================================================================== | |||||
| */ | |||||
| namespace juce | |||||
| { | |||||
| void Analytics::addDestination (AnalyticsDestination* destination) | |||||
| { | |||||
| destinations.add (destination); | |||||
| } | |||||
| void Analytics::setUserId (const String& newUserId) | |||||
| { | |||||
| userId = newUserId; | |||||
| } | |||||
| void Analytics::setUserProperties (const StringPairArray& properties) | |||||
| { | |||||
| userProperties = properties; | |||||
| } | |||||
| void Analytics::logEvent (const String& eventName, | |||||
| const StringPairArray& parameters) | |||||
| { | |||||
| if (! isSuspended) | |||||
| { | |||||
| AnalyticsDestination::AnalyticsEvent event | |||||
| { | |||||
| eventName, | |||||
| Time::getMillisecondCounter(), | |||||
| parameters, | |||||
| userId, | |||||
| userProperties | |||||
| }; | |||||
| for (auto* destination : destinations) | |||||
| destination->logEvent (event); | |||||
| } | |||||
| } | |||||
| void Analytics::setSuspended (bool shouldBeSuspended) | |||||
| { | |||||
| isSuspended = shouldBeSuspended; | |||||
| } | |||||
| juce_ImplementSingleton (Analytics) | |||||
| } | |||||
| @@ -0,0 +1,99 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library. | |||||
| Copyright (c) 2017 - ROLI Ltd. | |||||
| JUCE is an open source library subject to commercial or open-source | |||||
| licensing. | |||||
| The code included in this file is provided under the terms of the ISC license | |||||
| http://www.isc.org/downloads/software-support-policy/isc-license. Permission | |||||
| To use, copy, modify, and/or distribute this software for any purpose with or | |||||
| without fee is hereby granted provided that the above copyright notice and | |||||
| this permission notice appear in all copies. | |||||
| JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | |||||
| EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | |||||
| DISCLAIMED. | |||||
| ============================================================================== | |||||
| */ | |||||
| namespace juce | |||||
| { | |||||
| //============================================================================== | |||||
| /** | |||||
| A singleton class to manage analytics data. | |||||
| Use an Analytics object to manage sending analytics data to one or more | |||||
| AnalyticsDestinations. | |||||
| @see AnalyticsDestination, ThreadedAnalyticsDestination, | |||||
| AnalyticsDestination::AnalyticsEvent | |||||
| */ | |||||
| class JUCE_API Analytics : public DeletedAtShutdown | |||||
| { | |||||
| public: | |||||
| //============================================================================== | |||||
| /** Adds an AnalyticsDestination to the list of AnalyticsDestinations | |||||
| managed by this Analytics object. | |||||
| The Analytics class will take ownership of the AnalyticsDestination | |||||
| passed to this function. | |||||
| @param destination the AnalyticsDestination to manage | |||||
| */ | |||||
| void addDestination (AnalyticsDestination* destination); | |||||
| /** Sets a user ID that will be added to all AnalyticsEvents sent to | |||||
| AnalyticsDestinations. | |||||
| @param newUserId the userId to add to AnalyticsEvents | |||||
| */ | |||||
| void setUserId (const String& newUserId); | |||||
| /** Sets some user properties that will be added to all AnalyticsEvents sent | |||||
| to AnalyticsDestinations. | |||||
| @param properties the userProperties to add to AnalyticsEvents | |||||
| */ | |||||
| void setUserProperties (const StringPairArray& properties); | |||||
| /** Sends an AnalyticsEvent to all AnalyticsDestinations. | |||||
| The AnalyticsEvent will be timestamped, and will have the userId and | |||||
| userProperties populated by values previously set by calls to | |||||
| setUserId and setUserProperties. The name and parameters will be | |||||
| populated by the arguments supplied to this function. | |||||
| @param eventName the event name | |||||
| @param parameters the event parameters | |||||
| */ | |||||
| void logEvent (const String& eventName, const StringPairArray& parameters); | |||||
| /** Suspends analytics submission to AnalyticsDestinations. | |||||
| @param shouldBeSuspended if event submission should be suspended | |||||
| */ | |||||
| void setSuspended (bool shouldBeSuspended); | |||||
| juce_DeclareSingleton (Analytics, true) | |||||
| private: | |||||
| //============================================================================== | |||||
| Analytics() = default; | |||||
| String userId; | |||||
| StringPairArray userProperties; | |||||
| bool isSuspended = false; | |||||
| OwnedArray<AnalyticsDestination> destinations; | |||||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Analytics) | |||||
| }; | |||||
| } // namespace juce | |||||
| @@ -0,0 +1,55 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library. | |||||
| Copyright (c) 2017 - ROLI Ltd. | |||||
| JUCE is an open source library subject to commercial or open-source | |||||
| licensing. | |||||
| The code included in this file is provided under the terms of the ISC license | |||||
| http://www.isc.org/downloads/software-support-policy/isc-license. Permission | |||||
| To use, copy, modify, and/or distribute this software for any purpose with or | |||||
| without fee is hereby granted provided that the above copyright notice and | |||||
| this permission notice appear in all copies. | |||||
| JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | |||||
| EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | |||||
| DISCLAIMED. | |||||
| ============================================================================== | |||||
| */ | |||||
| namespace juce | |||||
| { | |||||
| ButtonTracker::ButtonTracker (Button& buttonToTrack, | |||||
| const String& triggeredEventName, | |||||
| const StringPairArray& triggeredEventParameters) | |||||
| : button (buttonToTrack), | |||||
| eventName (triggeredEventName), | |||||
| eventParameters (triggeredEventParameters) | |||||
| { | |||||
| button.addListener (this); | |||||
| } | |||||
| ButtonTracker::~ButtonTracker() | |||||
| { | |||||
| button.removeListener (this); | |||||
| } | |||||
| void ButtonTracker::buttonClicked (Button* b) | |||||
| { | |||||
| if (b == &button) | |||||
| { | |||||
| auto params = eventParameters; | |||||
| if (button.getClickingTogglesState()) | |||||
| params.set ("ButtonState", button.getToggleState() ? "On" : "Off"); | |||||
| Analytics::getInstance()->logEvent (eventName, params); | |||||
| } | |||||
| } | |||||
| } // namespace juce | |||||
| @@ -0,0 +1,70 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library. | |||||
| Copyright (c) 2017 - ROLI Ltd. | |||||
| JUCE is an open source library subject to commercial or open-source | |||||
| licensing. | |||||
| The code included in this file is provided under the terms of the ISC license | |||||
| http://www.isc.org/downloads/software-support-policy/isc-license. Permission | |||||
| To use, copy, modify, and/or distribute this software for any purpose with or | |||||
| without fee is hereby granted provided that the above copyright notice and | |||||
| this permission notice appear in all copies. | |||||
| JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | |||||
| EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | |||||
| DISCLAIMED. | |||||
| ============================================================================== | |||||
| */ | |||||
| namespace juce | |||||
| { | |||||
| //============================================================================== | |||||
| /** | |||||
| A class that automatically sends analytics events to the Analytics singleton | |||||
| when a button is clicked. | |||||
| @see Analytics, AnalyticsDestination::AnalyticsEvent | |||||
| */ | |||||
| class JUCE_API ButtonTracker : private Button::Listener | |||||
| { | |||||
| public: | |||||
| //============================================================================== | |||||
| /** | |||||
| Creating one of these automatically sends analytics events to the Analytics | |||||
| singeton when the corresponding button is clicked. | |||||
| The name and parameters of the analytics event will be populated from the | |||||
| variables supplied here. If clicking changes the button's state then the | |||||
| parameters will have a {"ButtonState", "On"/"Off"} entry added. | |||||
| @param buttonToTrack the button to track | |||||
| @param triggeredEventName the name of the generated event | |||||
| @param triggeredEventParameters the parameters to add to the generated | |||||
| event | |||||
| @see Analytics, AnalyticsDestination::AnalyticsEvent | |||||
| */ | |||||
| ButtonTracker (Button& buttonToTrack, | |||||
| const String& triggeredEventName, | |||||
| const StringPairArray& triggeredEventParameters = {}); | |||||
| /** Destructor. */ | |||||
| ~ButtonTracker(); | |||||
| private: | |||||
| /** @internal */ | |||||
| void buttonClicked (Button*) override; | |||||
| Button& button; | |||||
| const String eventName; | |||||
| const StringPairArray eventParameters; | |||||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ButtonTracker) | |||||
| }; | |||||
| } // namespace juce | |||||
| @@ -0,0 +1,86 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library. | |||||
| Copyright (c) 2017 - ROLI Ltd. | |||||
| JUCE is an open source library subject to commercial or open-source | |||||
| licensing. | |||||
| The code included in this file is provided under the terms of the ISC license | |||||
| http://www.isc.org/downloads/software-support-policy/isc-license. Permission | |||||
| To use, copy, modify, and/or distribute this software for any purpose with or | |||||
| without fee is hereby granted provided that the above copyright notice and | |||||
| this permission notice appear in all copies. | |||||
| JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | |||||
| EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | |||||
| DISCLAIMED. | |||||
| ============================================================================== | |||||
| */ | |||||
| namespace juce | |||||
| { | |||||
| //============================================================================== | |||||
| /** | |||||
| An interface for handling analytics events collected by an Analytics object. | |||||
| For basic analytics logging you can implement this interface and add your | |||||
| class to an Analytics object. | |||||
| For more advanced logging you may want to subclass | |||||
| ThreadedAnalyticsDestination instead, which is more suitable for interacting | |||||
| with web servers and other time consuming destinations. | |||||
| @see Analytics, ThreadedAnalyticsDestination | |||||
| */ | |||||
| struct JUCE_API AnalyticsDestination | |||||
| { | |||||
| /** Contains information about an event to be logged. */ | |||||
| struct AnalyticsEvent | |||||
| { | |||||
| /** The name of the event. */ | |||||
| String name; | |||||
| /** | |||||
| The timestamp of the event. | |||||
| Timestamps are automatically applied by an Analytics object and are | |||||
| derived from Time::getMillisecondCounter(). As such these timestamps | |||||
| do not represent absolute times, but relative timings of events for | |||||
| each user in each session will be accurate. | |||||
| */ | |||||
| uint32 timestamp; | |||||
| /** The parameters of the event. */ | |||||
| StringPairArray parameters; | |||||
| /** The user ID associated with the event. */ | |||||
| String userID; | |||||
| /** Properties associated with the user. */ | |||||
| StringPairArray userProperties; | |||||
| }; | |||||
| /** Constructor. */ | |||||
| AnalyticsDestination() = default; | |||||
| /** Destructor. */ | |||||
| virtual ~AnalyticsDestination() {} | |||||
| /** | |||||
| When an AnalyticsDestination is added to an Analytics object this method | |||||
| is called when an analytics event is triggered from the Analytics | |||||
| object. | |||||
| Override this method to log the event information somewhere useful. | |||||
| */ | |||||
| virtual void logEvent (const AnalyticsEvent& event) = 0; | |||||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AnalyticsDestination) | |||||
| }; | |||||
| } // namespace juce | |||||
| @@ -0,0 +1,350 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library. | |||||
| Copyright (c) 2017 - ROLI Ltd. | |||||
| JUCE is an open source library subject to commercial or open-source | |||||
| licensing. | |||||
| The code included in this file is provided under the terms of the ISC license | |||||
| http://www.isc.org/downloads/software-support-policy/isc-license. Permission | |||||
| To use, copy, modify, and/or distribute this software for any purpose with or | |||||
| without fee is hereby granted provided that the above copyright notice and | |||||
| this permission notice appear in all copies. | |||||
| JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | |||||
| EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | |||||
| DISCLAIMED. | |||||
| ============================================================================== | |||||
| */ | |||||
| namespace juce | |||||
| { | |||||
| ThreadedAnalyticsDestination::ThreadedAnalyticsDestination (const String& threadName) | |||||
| : dispatcher (threadName, *this) | |||||
| {} | |||||
| ThreadedAnalyticsDestination::~ThreadedAnalyticsDestination() | |||||
| { | |||||
| // If you hit this assertion then the analytics thread has not been shut down | |||||
| // before this class is destroyed. Call stopAnalyticsThread() in your destructor! | |||||
| jassert (! dispatcher.isThreadRunning()); | |||||
| } | |||||
| void ThreadedAnalyticsDestination::setBatchPeriod (int newBatchPeriodMilliseconds) | |||||
| { | |||||
| dispatcher.batchPeriodMilliseconds = newBatchPeriodMilliseconds; | |||||
| } | |||||
| void ThreadedAnalyticsDestination::logEvent (const AnalyticsEvent& event) | |||||
| { | |||||
| dispatcher.addToQueue (event); | |||||
| } | |||||
| void ThreadedAnalyticsDestination::startAnalyticsThread (int initialBatchPeriodMilliseconds) | |||||
| { | |||||
| setBatchPeriod (initialBatchPeriodMilliseconds); | |||||
| dispatcher.startThread(); | |||||
| } | |||||
| void ThreadedAnalyticsDestination::stopAnalyticsThread (int timeout) | |||||
| { | |||||
| dispatcher.signalThreadShouldExit(); | |||||
| stopLoggingEvents(); | |||||
| dispatcher.stopThread (timeout); | |||||
| if (dispatcher.eventQueue.size() > 0) | |||||
| saveUnloggedEvents (dispatcher.eventQueue); | |||||
| } | |||||
| ThreadedAnalyticsDestination::EventDispatcher::EventDispatcher (const String& threadName, | |||||
| ThreadedAnalyticsDestination& destination) | |||||
| : Thread (threadName), | |||||
| parent (destination) | |||||
| {} | |||||
| void ThreadedAnalyticsDestination::EventDispatcher::run() | |||||
| { | |||||
| // We may have inserted some events into the queue (on the message thread) | |||||
| // before this thread has started, so make sure the old events are at the | |||||
| // front of the queue. | |||||
| { | |||||
| std::deque<AnalyticsEvent> restoredEventQueue; | |||||
| parent.restoreUnloggedEvents (restoredEventQueue); | |||||
| const ScopedLock lock (queueAccess); | |||||
| for (auto rit = restoredEventQueue.rbegin(); rit != restoredEventQueue.rend(); ++rit) | |||||
| eventQueue.push_front (*rit); | |||||
| } | |||||
| const int maxBatchSize = parent.getMaximumBatchSize(); | |||||
| while (! threadShouldExit()) | |||||
| { | |||||
| auto eventsToSendCapacity = maxBatchSize - eventsToSend.size(); | |||||
| if (eventsToSendCapacity > 0) | |||||
| { | |||||
| const ScopedLock lock (queueAccess); | |||||
| const auto numEventsInQueue = (int) eventQueue.size(); | |||||
| if (numEventsInQueue > 0) | |||||
| { | |||||
| const auto numEventsToAdd = jmin (eventsToSendCapacity, numEventsInQueue); | |||||
| for (size_t i = 0; i < (size_t) numEventsToAdd; ++i) | |||||
| eventsToSend.add (eventQueue[i]); | |||||
| } | |||||
| } | |||||
| const auto submissionTime = Time::getMillisecondCounter(); | |||||
| if (! eventsToSend.isEmpty()) | |||||
| { | |||||
| if (parent.logBatchedEvents (eventsToSend)) | |||||
| { | |||||
| const ScopedLock lock (queueAccess); | |||||
| for (auto i = 0; i < eventsToSend.size(); ++i) | |||||
| eventQueue.pop_front(); | |||||
| eventsToSend.clearQuick(); | |||||
| } | |||||
| } | |||||
| while (Time::getMillisecondCounter() - submissionTime < (uint32) batchPeriodMilliseconds.get()) | |||||
| { | |||||
| if (threadShouldExit()) | |||||
| return; | |||||
| Thread::sleep (100); | |||||
| } | |||||
| } | |||||
| } | |||||
| void ThreadedAnalyticsDestination::EventDispatcher::addToQueue (const AnalyticsEvent& event) | |||||
| { | |||||
| const ScopedLock lock (queueAccess); | |||||
| eventQueue.push_back (event); | |||||
| } | |||||
| //============================================================================== | |||||
| #if JUCE_UNIT_TESTS | |||||
| namespace DestinationTestHelpers | |||||
| { | |||||
| //============================================================================== | |||||
| struct TestDestination : public ThreadedAnalyticsDestination | |||||
| { | |||||
| TestDestination (std::deque<AnalyticsEvent>& loggedEvents, | |||||
| std::deque<AnalyticsEvent>& unloggedEvents) | |||||
| : ThreadedAnalyticsDestination ("ThreadedAnalyticsDestinationTest"), | |||||
| loggedEventQueue (loggedEvents), | |||||
| unloggedEventStore (unloggedEvents) | |||||
| {} | |||||
| virtual ~TestDestination() {} | |||||
| int getMaximumBatchSize() override | |||||
| { | |||||
| return 5; | |||||
| } | |||||
| void saveUnloggedEvents (const std::deque<AnalyticsEvent>& eventsToSave) override | |||||
| { | |||||
| unloggedEventStore = eventsToSave; | |||||
| } | |||||
| void restoreUnloggedEvents (std::deque<AnalyticsEvent>& restoredEventQueue) override | |||||
| { | |||||
| restoredEventQueue = unloggedEventStore; | |||||
| } | |||||
| std::deque<AnalyticsEvent>& loggedEventQueue; | |||||
| std::deque<AnalyticsEvent>& unloggedEventStore; | |||||
| }; | |||||
| //============================================================================== | |||||
| struct BasicDestination : public TestDestination | |||||
| { | |||||
| BasicDestination (std::deque<AnalyticsEvent>& loggedEvents, | |||||
| std::deque<AnalyticsEvent>& unloggedEvents) | |||||
| : TestDestination (loggedEvents, unloggedEvents) | |||||
| { | |||||
| startAnalyticsThread (100); | |||||
| } | |||||
| virtual ~BasicDestination() | |||||
| { | |||||
| stopAnalyticsThread (1000); | |||||
| } | |||||
| bool logBatchedEvents (const Array<AnalyticsEvent>& events) override | |||||
| { | |||||
| jassert (events.size() <= getMaximumBatchSize()); | |||||
| for (auto& event : events) | |||||
| loggedEventQueue.push_back (event); | |||||
| return true; | |||||
| } | |||||
| void stopLoggingEvents() override {} | |||||
| }; | |||||
| //============================================================================== | |||||
| struct SlowWebDestination : public TestDestination | |||||
| { | |||||
| SlowWebDestination (std::deque<AnalyticsEvent>& loggedEvents, | |||||
| std::deque<AnalyticsEvent>& unloggedEvents) | |||||
| : TestDestination (loggedEvents, unloggedEvents) | |||||
| { | |||||
| startAnalyticsThread (initialPeriod); | |||||
| } | |||||
| virtual ~SlowWebDestination() | |||||
| { | |||||
| stopAnalyticsThread (1000); | |||||
| } | |||||
| bool logBatchedEvents (const Array<AnalyticsEvent>& events) override | |||||
| { | |||||
| threadHasStarted.signal(); | |||||
| jassert (events.size() <= getMaximumBatchSize()); | |||||
| { | |||||
| const ScopedLock lock (webStreamCreation); | |||||
| if (shouldExit) | |||||
| return false; | |||||
| // An attempt to connect to an unroutable IP address will hang | |||||
| // indefinitely, which simulates a very slow server | |||||
| webStream = new WebInputStream (URL ("http://1.192.0.0"), true); | |||||
| } | |||||
| String data; | |||||
| for (auto& event : events) | |||||
| data << event.name; | |||||
| webStream->withExtraHeaders (data); | |||||
| const auto success = webStream->connect (nullptr); | |||||
| // Exponential backoff on failure | |||||
| if (success) | |||||
| period = initialPeriod; | |||||
| else | |||||
| period *= 2; | |||||
| setBatchPeriod (period); | |||||
| return success; | |||||
| } | |||||
| void stopLoggingEvents() override | |||||
| { | |||||
| const ScopedLock lock (webStreamCreation); | |||||
| shouldExit = true; | |||||
| if (webStream != nullptr) | |||||
| webStream->cancel(); | |||||
| } | |||||
| const int initialPeriod = 100; | |||||
| int period = initialPeriod; | |||||
| CriticalSection webStreamCreation; | |||||
| bool shouldExit = false; | |||||
| ScopedPointer<WebInputStream> webStream; | |||||
| WaitableEvent threadHasStarted; | |||||
| }; | |||||
| } | |||||
| //============================================================================== | |||||
| struct ThreadedAnalyticsDestinationTests : public UnitTest | |||||
| { | |||||
| ThreadedAnalyticsDestinationTests() | |||||
| : UnitTest ("ThreadedAnalyticsDestination") | |||||
| {} | |||||
| void compareEventQueues (const std::deque<AnalyticsDestination::AnalyticsEvent>& a, | |||||
| const std::deque<AnalyticsDestination::AnalyticsEvent>& b) | |||||
| { | |||||
| const auto numEntries = a.size(); | |||||
| expectEquals (b.size(), numEntries); | |||||
| for (size_t i = 0; i < numEntries; ++i) | |||||
| { | |||||
| expectEquals (a[i].name, b[i].name); | |||||
| expect (a[i].timestamp == b[i].timestamp); | |||||
| } | |||||
| } | |||||
| void runTest() override | |||||
| { | |||||
| std::deque<AnalyticsDestination::AnalyticsEvent> testEvents; | |||||
| for (int i = 0; i < 7; ++i) | |||||
| testEvents.push_back ({ String (i), Time::getMillisecondCounter(), {}, "TestUser", {} }); | |||||
| std::deque<AnalyticsDestination::AnalyticsEvent> loggedEvents, unloggedEvents; | |||||
| beginTest ("Basic"); | |||||
| { | |||||
| DestinationTestHelpers::BasicDestination destination (loggedEvents, unloggedEvents); | |||||
| for (auto& event : testEvents) | |||||
| destination.logEvent (event); | |||||
| Thread::sleep (400); | |||||
| compareEventQueues (loggedEvents, testEvents); | |||||
| expect (unloggedEvents.size() == 0); | |||||
| loggedEvents.clear(); | |||||
| } | |||||
| beginTest ("Web"); | |||||
| { | |||||
| { | |||||
| DestinationTestHelpers::SlowWebDestination destination (loggedEvents, unloggedEvents); | |||||
| for (auto& event : testEvents) | |||||
| destination.logEvent (event); | |||||
| } | |||||
| expect (loggedEvents.size() == 0); | |||||
| compareEventQueues (unloggedEvents, testEvents); | |||||
| { | |||||
| DestinationTestHelpers::SlowWebDestination destination (loggedEvents, unloggedEvents); | |||||
| destination.threadHasStarted.wait(); | |||||
| unloggedEvents.clear(); | |||||
| } | |||||
| expect (loggedEvents.size() == 0); | |||||
| compareEventQueues (unloggedEvents, testEvents); | |||||
| unloggedEvents.clear(); | |||||
| } | |||||
| } | |||||
| }; | |||||
| static ThreadedAnalyticsDestinationTests threadedAnalyticsDestinationTests; | |||||
| #endif | |||||
| } // namespace juce | |||||
| @@ -0,0 +1,212 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library. | |||||
| Copyright (c) 2017 - ROLI Ltd. | |||||
| JUCE is an open source library subject to commercial or open-source | |||||
| licensing. | |||||
| The code included in this file is provided under the terms of the ISC license | |||||
| http://www.isc.org/downloads/software-support-policy/isc-license. Permission | |||||
| To use, copy, modify, and/or distribute this software for any purpose with or | |||||
| without fee is hereby granted provided that the above copyright notice and | |||||
| this permission notice appear in all copies. | |||||
| JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | |||||
| EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | |||||
| DISCLAIMED. | |||||
| ============================================================================== | |||||
| */ | |||||
| namespace juce | |||||
| { | |||||
| //============================================================================== | |||||
| /** | |||||
| A base class for dispatching analytics events on a dedicated thread. | |||||
| This class is particularly useful for sending analytics events to a web | |||||
| server without blocking the message thread. It can also save (and restore) | |||||
| events that were not dispatched so no information is lost when an internet | |||||
| connection is absent or something else prevents successful logging. | |||||
| Once startAnalyticsThread is called the logBatchedEvents method is | |||||
| periodically invoked on an analytics thread, with the period determined by | |||||
| calls to setBatchPeriod. Here events are grouped together into batches, with | |||||
| the maximum batch size set by the implementation of getMaximumBatchSize. | |||||
| It's important to call stopAnalyticsThread in the destructor of your | |||||
| subclass (or before then) to give the analytics thread time to shut down. | |||||
| Calling stopAnalyticsThread will, in turn, call stopLoggingEvents, which | |||||
| you should use to terminate the currently running logBatchedEvents call. | |||||
| @see Analytics, AnalyticsDestination, AnalyticsDestination::AnalyticsEvent | |||||
| */ | |||||
| class JUCE_API ThreadedAnalyticsDestination : public AnalyticsDestination | |||||
| { | |||||
| public: | |||||
| //============================================================================== | |||||
| /** | |||||
| Creates a ThreadedAnalyticsDestination. | |||||
| @param threadName used to identify the analytics | |||||
| thread in debug builds | |||||
| */ | |||||
| ThreadedAnalyticsDestination (const String& threadName = "Analytics thread"); | |||||
| /** Destructor. */ | |||||
| virtual ~ThreadedAnalyticsDestination(); | |||||
| //============================================================================== | |||||
| /** | |||||
| Override this method to provide the maximum batch size you can handle in | |||||
| your subclass. | |||||
| Calls to logBatchedEvents will contain no more than this number of events. | |||||
| */ | |||||
| virtual int getMaximumBatchSize() = 0; | |||||
| /** | |||||
| This method will be called periodically on the analytics thread. | |||||
| If this method returns false then the subsequent call of this function will | |||||
| contain the same events as previous call, plus any new events that have been | |||||
| generated in the period between calls. The order of events will not be | |||||
| changed. This allows you to retry logging events until they are logged | |||||
| successfully. | |||||
| @param events a list of events to be logged | |||||
| @returns if the events were successfully logged | |||||
| */ | |||||
| virtual bool logBatchedEvents (const Array<AnalyticsEvent>& events) = 0; | |||||
| /** | |||||
| You must always call stopAnalyticsThread in the destructor of your subclass | |||||
| (or before then) to give the analytics thread time to shut down. | |||||
| Calling stopAnalyticsThread triggers a call to this method. At this point | |||||
| you are guaranteed that logBatchedEvents has been called for the last time | |||||
| and you should make sure that the current call to logBatchedEvents finishes | |||||
| as quickly as possible. This method and a subsequent call to | |||||
| saveUnloggedEvents must both complete before the timeout supplied to | |||||
| stopAnalyticsThread. | |||||
| In a normal use case stopLoggingEvents will be called on the message thread | |||||
| from the destructor of your ThreadedAnalyticsDestination subclass, and must | |||||
| stop the logBatchedEvents method which is running on the analytics thread. | |||||
| @see stopAnalyticsThread | |||||
| */ | |||||
| virtual void stopLoggingEvents() = 0; | |||||
| //============================================================================== | |||||
| /** | |||||
| Call this to set the period between logBatchedEvents invocations. | |||||
| This method is thread safe and can be used to implements things like | |||||
| exponential backoff in logBatchedEvents calls. | |||||
| @param newSubmissionPeriodMilliseconds the new submission period to | |||||
| use in milliseconds | |||||
| */ | |||||
| void setBatchPeriod (int newSubmissionPeriodMilliseconds); | |||||
| /** | |||||
| Adds an event to the queue, which will ultimately be submitted to | |||||
| logBatchedEvents. | |||||
| This method is thread safe. | |||||
| @param event the analytics event to add to the queue | |||||
| */ | |||||
| void logEvent (const AnalyticsEvent& event) override final; | |||||
| protected: | |||||
| //============================================================================== | |||||
| /** | |||||
| Starts the analytics thread, with an initial event batching period. | |||||
| @param initialBatchPeriodMilliseconds the initial event batching period | |||||
| in milliseconds | |||||
| */ | |||||
| void startAnalyticsThread (int initialBatchPeriodMilliseconds); | |||||
| //============================================================================== | |||||
| /** | |||||
| Triggers the shutdown of the analytics thread. | |||||
| You must call this method in the destructor of your subclass (or before | |||||
| then) to give the analytics thread time to shut down. | |||||
| This method invokes stopLoggingEvents and you should ensure that both the | |||||
| analytics thread and a call to saveUnloggedEvents are able to finish before | |||||
| the supplied timeout. This timeout is important because on platforms like | |||||
| iOS an app is killed if it takes too long to shut down. | |||||
| @param timeoutMilliseconds the number of milliseconds before | |||||
| the analytics thread is forcibly | |||||
| terminated | |||||
| */ | |||||
| void stopAnalyticsThread (int timeoutMilliseconds); | |||||
| private: | |||||
| //============================================================================== | |||||
| /** | |||||
| This method will be called when the analytics thread is shut down, | |||||
| giving you the chance to save any analytics events that could not be | |||||
| logged. Once saved these events can be put back into the queue of events | |||||
| when the ThreadedAnalyticsDestination is recreated via | |||||
| restoreUnloggedEvents. | |||||
| This method should return as quickly as possible, as both | |||||
| stopLoggingEvents and this method need to complete inside the timeout | |||||
| set in stopAnalyticsThread. | |||||
| @param eventsToSave the events that could not be logged | |||||
| @see stopAnalyticsThread, stopLoggingEvents, restoreUnloggedEvents | |||||
| */ | |||||
| virtual void saveUnloggedEvents (const std::deque<AnalyticsEvent>& eventsToSave) = 0; | |||||
| /** | |||||
| The counterpart to saveUnloggedEvents. | |||||
| Events added to the event queue provided by this method will be the | |||||
| first events supplied to logBatchedEvents calls. Use this method to | |||||
| restore any unlogged events previously stored in a call to | |||||
| saveUnloggedEvents. | |||||
| This method is called on the analytics thread. | |||||
| @param restoredEventQueue place restored events into this queue | |||||
| @see saveUnloggedEvents | |||||
| */ | |||||
| virtual void restoreUnloggedEvents (std::deque<AnalyticsEvent>& restoredEventQueue) = 0; | |||||
| struct EventDispatcher : public Thread | |||||
| { | |||||
| EventDispatcher (const String& threadName, ThreadedAnalyticsDestination&); | |||||
| void run() override; | |||||
| void addToQueue (const AnalyticsEvent&); | |||||
| ThreadedAnalyticsDestination& parent; | |||||
| std::deque<AnalyticsEvent> eventQueue; | |||||
| CriticalSection queueAccess; | |||||
| Atomic<int> batchPeriodMilliseconds { 1000 }; | |||||
| Array<AnalyticsEvent> eventsToSend; | |||||
| }; | |||||
| const String destinationName; | |||||
| EventDispatcher dispatcher; | |||||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ThreadedAnalyticsDestination) | |||||
| }; | |||||
| } // namespace juce | |||||
| @@ -0,0 +1,40 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library. | |||||
| Copyright (c) 2017 - ROLI Ltd. | |||||
| JUCE is an open source library subject to commercial or open-source | |||||
| licensing. | |||||
| By using JUCE, you agree to the terms of both the JUCE 5 End-User License | |||||
| Agreement and JUCE 5 Privacy Policy (both updated and effective as of the | |||||
| 27th April 2017). | |||||
| End User License Agreement: www.juce.com/juce-5-licence | |||||
| Privacy Policy: www.juce.com/juce-5-privacy-policy | |||||
| Or: You may also use this code under the terms of the GPL v3 (see | |||||
| www.gnu.org/licenses). | |||||
| JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | |||||
| EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | |||||
| DISCLAIMED. | |||||
| ============================================================================== | |||||
| */ | |||||
| #ifdef JUCE_ANALYTICS_H_INCLUDED | |||||
| /* When you add this cpp file to your project, you mustn't include it in a file where you've | |||||
| already included any other headers - just put it inside a file on its own, possibly with your config | |||||
| flags preceding it, but don't include anything else. That also includes avoiding any automatic prefix | |||||
| header files that the compiler may be using. | |||||
| */ | |||||
| #error "Incorrect use of JUCE cpp file" | |||||
| #endif | |||||
| #include "juce_analytics.h" | |||||
| #include "destinations/juce_ThreadedAnalyticsDestination.cpp" | |||||
| #include "analytics/juce_Analytics.cpp" | |||||
| #include "analytics/juce_ButtonTracker.cpp" | |||||
| @@ -0,0 +1,56 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library. | |||||
| Copyright (c) 2017 - ROLI Ltd. | |||||
| JUCE is an open source library subject to commercial or open-source | |||||
| licensing. | |||||
| The code included in this file is provided under the terms of the ISC license | |||||
| http://www.isc.org/downloads/software-support-policy/isc-license. Permission | |||||
| To use, copy, modify, and/or distribute this software for any purpose with or | |||||
| without fee is hereby granted provided that the above copyright notice and | |||||
| this permission notice appear in all copies. | |||||
| JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | |||||
| EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | |||||
| DISCLAIMED. | |||||
| ============================================================================== | |||||
| */ | |||||
| /******************************************************************************* | |||||
| The block below describes the properties of this module, and is read by | |||||
| the Projucer to automatically generate project code that uses it. | |||||
| For details about the syntax and how to create or use a module, see the | |||||
| JUCE Module Format.txt file. | |||||
| BEGIN_JUCE_MODULE_DECLARATION | |||||
| ID: juce_analytics | |||||
| vendor: juce | |||||
| version: 5.1.1 | |||||
| name: JUCE analytics classes | |||||
| description: Classes to collect analytics and send to destinations | |||||
| website: http://www.juce.com/juce | |||||
| license: GPL/Commercial | |||||
| dependencies: juce_gui_basics | |||||
| END_JUCE_MODULE_DECLARATION | |||||
| *******************************************************************************/ | |||||
| #pragma once | |||||
| #define JUCE_ANALYTICS_H_INCLUDED | |||||
| #include <queue> | |||||
| #include <juce_gui_basics/juce_gui_basics.h> | |||||
| #include "destinations/juce_AnalyticsDestination.h" | |||||
| #include "destinations/juce_ThreadedAnalyticsDestination.h" | |||||
| #include "analytics/juce_Analytics.h" | |||||
| #include "analytics/juce_ButtonTracker.h" | |||||