Merge remote-tracking branch 'origin/savya' into work_branch
# Conflicts: # Assets/Darkmatter/Content/Fonts/static/Fredoka-SemiBold SDF.asset
This commit is contained in:
8
Assets/AddressableAssetsData/iOS.meta
Normal file
8
Assets/AddressableAssetsData/iOS.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 684ad60441f714a338ca786efcac33b6
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/AppsFlyer.meta
Normal file
8
Assets/AppsFlyer.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7863556d88b814e09ba9cfc75a91d655
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
71
Assets/AppsFlyer/AFAdRevenueData.cs
Normal file
71
Assets/AppsFlyer/AFAdRevenueData.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AppsFlyerSDK
|
||||
{
|
||||
public enum MediationNetwork : ulong
|
||||
{
|
||||
GoogleAdMob = 1,
|
||||
IronSource = 2,
|
||||
ApplovinMax = 3,
|
||||
Fyber = 4,
|
||||
Appodeal = 5,
|
||||
Admost = 6,
|
||||
Topon = 7,
|
||||
Tradplus = 8,
|
||||
Yandex = 9,
|
||||
ChartBoost = 10,
|
||||
Unity = 11,
|
||||
ToponPte = 12,
|
||||
Custom = 13,
|
||||
DirectMonetization = 14
|
||||
}
|
||||
|
||||
public static class AdRevenueScheme
|
||||
{
|
||||
/**
|
||||
* code ISO 3166-1 format
|
||||
*/
|
||||
public const string COUNTRY = "country";
|
||||
|
||||
/**
|
||||
* ID of the ad unit for the impression
|
||||
*/
|
||||
public const string AD_UNIT = "ad_unit";
|
||||
|
||||
/**
|
||||
* Format of the ad
|
||||
*/
|
||||
public const string AD_TYPE = "ad_type";
|
||||
|
||||
/**
|
||||
* ID of the ad placement for the impression
|
||||
*/
|
||||
public const string PLACEMENT = "placement";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
// Data class representing ad revenue information.
|
||||
//
|
||||
// @property monetizationNetwork The name of the network that monetized the ad.
|
||||
// @property mediationNetwork An instance of MediationNetwork representing the mediation service used.
|
||||
// @property currencyIso4217Code The ISO 4217 currency code describing the currency of the revenue.
|
||||
// @property eventRevenue The amount of revenue generated by the ad.
|
||||
/// </summary>
|
||||
public class AFAdRevenueData
|
||||
{
|
||||
public string monetizationNetwork { get; private set; }
|
||||
public MediationNetwork mediationNetwork { get; private set; }
|
||||
public string currencyIso4217Code { get; private set; }
|
||||
public double eventRevenue { get; private set; }
|
||||
|
||||
public AFAdRevenueData(string monetization, MediationNetwork mediation, string currency, double revenue)
|
||||
{
|
||||
monetizationNetwork = monetization;
|
||||
mediationNetwork = mediation;
|
||||
currencyIso4217Code = currency;
|
||||
eventRevenue = revenue;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
11
Assets/AppsFlyer/AFAdRevenueData.cs.meta
Normal file
11
Assets/AppsFlyer/AFAdRevenueData.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 49e1906ae949e4bfea400bd1da9f7e39
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
72
Assets/AppsFlyer/AFInAppEvents.cs
Normal file
72
Assets/AppsFlyer/AFInAppEvents.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
public class AFInAppEvents {
|
||||
/**
|
||||
* Event Type
|
||||
* */
|
||||
public const string LEVEL_ACHIEVED = "af_level_achieved";
|
||||
public const string ADD_PAYMENT_INFO = "af_add_payment_info";
|
||||
public const string ADD_TO_CART = "af_add_to_cart";
|
||||
public const string ADD_TO_WISH_LIST = "af_add_to_wishlist";
|
||||
public const string COMPLETE_REGISTRATION = "af_complete_registration";
|
||||
public const string TUTORIAL_COMPLETION = "af_tutorial_completion";
|
||||
public const string INITIATED_CHECKOUT = "af_initiated_checkout";
|
||||
public const string PURCHASE = "af_purchase";
|
||||
public const string RATE = "af_rate";
|
||||
public const string SEARCH = "af_search";
|
||||
public const string SPENT_CREDIT = "af_spent_credits";
|
||||
public const string ACHIEVEMENT_UNLOCKED = "af_achievement_unlocked";
|
||||
public const string CONTENT_VIEW = "af_content_view";
|
||||
public const string TRAVEL_BOOKING = "af_travel_booking";
|
||||
public const string SHARE = "af_share";
|
||||
public const string INVITE = "af_invite";
|
||||
public const string LOGIN = "af_login";
|
||||
public const string RE_ENGAGE = "af_re_engage";
|
||||
public const string UPDATE = "af_update";
|
||||
public const string OPENED_FROM_PUSH_NOTIFICATION = "af_opened_from_push_notification";
|
||||
public const string LOCATION_CHANGED = "af_location_changed";
|
||||
public const string LOCATION_COORDINATES = "af_location_coordinates";
|
||||
public const string ORDER_ID = "af_order_id";
|
||||
/**
|
||||
* Event Parameter Name
|
||||
* **/
|
||||
public const string LEVEL = "af_level";
|
||||
public const string SCORE = "af_score";
|
||||
public const string SUCCESS = "af_success";
|
||||
public const string PRICE = "af_price";
|
||||
public const string CONTENT_TYPE = "af_content_type";
|
||||
public const string CONTENT_ID = "af_content_id";
|
||||
public const string CONTENT_LIST = "af_content_list";
|
||||
public const string CURRENCY = "af_currency";
|
||||
public const string QUANTITY = "af_quantity";
|
||||
public const string REGSITRATION_METHOD = "af_registration_method";
|
||||
public const string PAYMENT_INFO_AVAILIBLE = "af_payment_info_available";
|
||||
public const string MAX_RATING_VALUE = "af_max_rating_value";
|
||||
public const string RATING_VALUE = "af_rating_value";
|
||||
public const string SEARCH_STRING = "af_search_string";
|
||||
public const string DATE_A = "af_date_a";
|
||||
public const string DATE_B = "af_date_b";
|
||||
public const string DESTINATION_A = "af_destination_a";
|
||||
public const string DESTINATION_B = "af_destination_b";
|
||||
public const string DESCRIPTION = "af_description";
|
||||
public const string CLASS = "af_class";
|
||||
public const string EVENT_START = "af_event_start";
|
||||
public const string EVENT_END = "af_event_end";
|
||||
public const string LATITUDE = "af_lat";
|
||||
public const string LONGTITUDE = "af_long";
|
||||
public const string CUSTOMER_USER_ID = "af_customer_user_id";
|
||||
public const string VALIDATED = "af_validated";
|
||||
public const string REVENUE = "af_revenue";
|
||||
public const string RECEIPT_ID = "af_receipt_id";
|
||||
public const string PARAM_1 = "af_param_1";
|
||||
public const string PARAM_2 = "af_param_2";
|
||||
public const string PARAM_3 = "af_param_3";
|
||||
public const string PARAM_4 = "af_param_4";
|
||||
public const string PARAM_5 = "af_param_5";
|
||||
public const string PARAM_6 = "af_param_6";
|
||||
public const string PARAM_7 = "af_param_7";
|
||||
public const string PARAM_8 = "af_param_8";
|
||||
public const string PARAM_9 = "af_param_9";
|
||||
public const string PARAM_10 = "af_param_10";
|
||||
}
|
||||
11
Assets/AppsFlyer/AFInAppEvents.cs.meta
Normal file
11
Assets/AppsFlyer/AFInAppEvents.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4075c6cf6f3d94b9a9f37f826e6a0e6f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
547
Assets/AppsFlyer/AFMiniJSON.cs
Executable file
547
Assets/AppsFlyer/AFMiniJSON.cs
Executable file
@@ -0,0 +1,547 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Calvin Rien
|
||||
*
|
||||
* Based on the JSON parser by Patrick van Bergen
|
||||
* http://techblog.procurios.nl/k/618/news/view/14605/14863/How-do-I-write-my-own-parser-for-JSON.html
|
||||
*
|
||||
* Simplified it so that it doesn't throw exceptions
|
||||
* and can be used in Unity iPhone with maximum code stripping.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace AFMiniJSON {
|
||||
// Example usage:
|
||||
//
|
||||
// using UnityEngine;
|
||||
// using System.Collections;
|
||||
// using System.Collections.Generic;
|
||||
// using MiniJSON;
|
||||
//
|
||||
// public class MiniJSONTest : MonoBehaviour {
|
||||
// void Start () {
|
||||
// var jsonString = "{ \"array\": [1.44,2,3], " +
|
||||
// "\"object\": {\"key1\":\"value1\", \"key2\":256}, " +
|
||||
// "\"string\": \"The quick brown fox \\\"jumps\\\" over the lazy dog \", " +
|
||||
// "\"unicode\": \"\\u3041 Men\u00fa sesi\u00f3n\", " +
|
||||
// "\"int\": 65536, " +
|
||||
// "\"float\": 3.1415926, " +
|
||||
// "\"bool\": true, " +
|
||||
// "\"null\": null }";
|
||||
//
|
||||
// var dict = Json.Deserialize(jsonString) as Dictionary<string,object>;
|
||||
//
|
||||
// Debug.Log("deserialized: " + dict.GetType());
|
||||
// Debug.Log("dict['array'][0]: " + ((List<object>) dict["array"])[0]);
|
||||
// Debug.Log("dict['string']: " + (string) dict["string"]);
|
||||
// Debug.Log("dict['float']: " + (double) dict["float"]); // floats come out as doubles
|
||||
// Debug.Log("dict['int']: " + (long) dict["int"]); // ints come out as longs
|
||||
// Debug.Log("dict['unicode']: " + (string) dict["unicode"]);
|
||||
//
|
||||
// var str = Json.Serialize(dict);
|
||||
//
|
||||
// Debug.Log("serialized: " + str);
|
||||
// }
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// This class encodes and decodes JSON strings.
|
||||
/// Spec. details, see http://www.json.org/
|
||||
///
|
||||
/// JSON uses Arrays and Objects. These correspond here to the datatypes IList and IDictionary.
|
||||
/// All numbers are parsed to doubles.
|
||||
/// </summary>
|
||||
public static class Json {
|
||||
/// <summary>
|
||||
/// Parses the string json into a value
|
||||
/// </summary>
|
||||
/// <param name="json">A JSON string.</param>
|
||||
/// <returns>An List<object>, a Dictionary<string, object>, a double, an integer,a string, null, true, or false</returns>
|
||||
public static object Deserialize(string json) {
|
||||
// save the string for debug information
|
||||
if (json == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Parser.Parse(json);
|
||||
}
|
||||
|
||||
sealed class Parser : IDisposable {
|
||||
const string WORD_BREAK = "{}[],:\"";
|
||||
|
||||
public static bool IsWordBreak(char c) {
|
||||
return Char.IsWhiteSpace(c) || WORD_BREAK.IndexOf(c) != -1;
|
||||
}
|
||||
|
||||
enum TOKEN {
|
||||
NONE,
|
||||
CURLY_OPEN,
|
||||
CURLY_CLOSE,
|
||||
SQUARED_OPEN,
|
||||
SQUARED_CLOSE,
|
||||
COLON,
|
||||
COMMA,
|
||||
STRING,
|
||||
NUMBER,
|
||||
TRUE,
|
||||
FALSE,
|
||||
NULL
|
||||
};
|
||||
|
||||
StringReader json;
|
||||
|
||||
Parser(string jsonString) {
|
||||
json = new StringReader(jsonString);
|
||||
}
|
||||
|
||||
public static object Parse(string jsonString) {
|
||||
using (var instance = new Parser(jsonString)) {
|
||||
return instance.ParseValue();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
json.Dispose();
|
||||
json = null;
|
||||
}
|
||||
|
||||
Dictionary<string, object> ParseObject() {
|
||||
Dictionary<string, object> table = new Dictionary<string, object>();
|
||||
|
||||
// ditch opening brace
|
||||
json.Read();
|
||||
|
||||
// {
|
||||
while (true) {
|
||||
switch (NextToken) {
|
||||
case TOKEN.NONE:
|
||||
return null;
|
||||
case TOKEN.COMMA:
|
||||
continue;
|
||||
case TOKEN.CURLY_CLOSE:
|
||||
return table;
|
||||
default:
|
||||
// name
|
||||
string name = ParseString();
|
||||
if (name == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// :
|
||||
if (NextToken != TOKEN.COLON) {
|
||||
return null;
|
||||
}
|
||||
// ditch the colon
|
||||
json.Read();
|
||||
|
||||
// value
|
||||
table[name] = ParseValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<object> ParseArray() {
|
||||
List<object> array = new List<object>();
|
||||
|
||||
// ditch opening bracket
|
||||
json.Read();
|
||||
|
||||
// [
|
||||
var parsing = true;
|
||||
while (parsing) {
|
||||
TOKEN nextToken = NextToken;
|
||||
|
||||
switch (nextToken) {
|
||||
case TOKEN.NONE:
|
||||
return null;
|
||||
case TOKEN.COMMA:
|
||||
continue;
|
||||
case TOKEN.SQUARED_CLOSE:
|
||||
parsing = false;
|
||||
break;
|
||||
default:
|
||||
object value = ParseByToken(nextToken);
|
||||
|
||||
array.Add(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
object ParseValue() {
|
||||
TOKEN nextToken = NextToken;
|
||||
return ParseByToken(nextToken);
|
||||
}
|
||||
|
||||
object ParseByToken(TOKEN token) {
|
||||
switch (token) {
|
||||
case TOKEN.STRING:
|
||||
return ParseString();
|
||||
case TOKEN.NUMBER:
|
||||
return ParseNumber();
|
||||
case TOKEN.CURLY_OPEN:
|
||||
return ParseObject();
|
||||
case TOKEN.SQUARED_OPEN:
|
||||
return ParseArray();
|
||||
case TOKEN.TRUE:
|
||||
return true;
|
||||
case TOKEN.FALSE:
|
||||
return false;
|
||||
case TOKEN.NULL:
|
||||
return null;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
string ParseString() {
|
||||
StringBuilder s = new StringBuilder();
|
||||
char c;
|
||||
|
||||
// ditch opening quote
|
||||
json.Read();
|
||||
|
||||
bool parsing = true;
|
||||
while (parsing) {
|
||||
|
||||
if (json.Peek() == -1) {
|
||||
parsing = false;
|
||||
break;
|
||||
}
|
||||
|
||||
c = NextChar;
|
||||
switch (c) {
|
||||
case '"':
|
||||
parsing = false;
|
||||
break;
|
||||
case '\\':
|
||||
if (json.Peek() == -1) {
|
||||
parsing = false;
|
||||
break;
|
||||
}
|
||||
|
||||
c = NextChar;
|
||||
switch (c) {
|
||||
case '"':
|
||||
case '\\':
|
||||
case '/':
|
||||
s.Append(c);
|
||||
break;
|
||||
case 'b':
|
||||
s.Append('\b');
|
||||
break;
|
||||
case 'f':
|
||||
s.Append('\f');
|
||||
break;
|
||||
case 'n':
|
||||
s.Append('\n');
|
||||
break;
|
||||
case 'r':
|
||||
s.Append('\r');
|
||||
break;
|
||||
case 't':
|
||||
s.Append('\t');
|
||||
break;
|
||||
case 'u':
|
||||
var hex = new char[4];
|
||||
|
||||
for (int i=0; i< 4; i++) {
|
||||
hex[i] = NextChar;
|
||||
}
|
||||
|
||||
s.Append((char) Convert.ToInt32(new string(hex), 16));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
s.Append(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return s.ToString();
|
||||
}
|
||||
|
||||
object ParseNumber() {
|
||||
string number = NextWord;
|
||||
|
||||
if (number.IndexOf('.') == -1) {
|
||||
long parsedInt;
|
||||
Int64.TryParse(number, out parsedInt);
|
||||
return parsedInt;
|
||||
}
|
||||
|
||||
double parsedDouble;
|
||||
Double.TryParse(number, out parsedDouble);
|
||||
return parsedDouble;
|
||||
}
|
||||
|
||||
void EatWhitespace() {
|
||||
while (Char.IsWhiteSpace(PeekChar)) {
|
||||
json.Read();
|
||||
|
||||
if (json.Peek() == -1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char PeekChar {
|
||||
get {
|
||||
return Convert.ToChar(json.Peek());
|
||||
}
|
||||
}
|
||||
|
||||
char NextChar {
|
||||
get {
|
||||
return Convert.ToChar(json.Read());
|
||||
}
|
||||
}
|
||||
|
||||
string NextWord {
|
||||
get {
|
||||
StringBuilder word = new StringBuilder();
|
||||
|
||||
while (!IsWordBreak(PeekChar)) {
|
||||
word.Append(NextChar);
|
||||
|
||||
if (json.Peek() == -1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return word.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
TOKEN NextToken {
|
||||
get {
|
||||
EatWhitespace();
|
||||
|
||||
if (json.Peek() == -1) {
|
||||
return TOKEN.NONE;
|
||||
}
|
||||
|
||||
switch (PeekChar) {
|
||||
case '{':
|
||||
return TOKEN.CURLY_OPEN;
|
||||
case '}':
|
||||
json.Read();
|
||||
return TOKEN.CURLY_CLOSE;
|
||||
case '[':
|
||||
return TOKEN.SQUARED_OPEN;
|
||||
case ']':
|
||||
json.Read();
|
||||
return TOKEN.SQUARED_CLOSE;
|
||||
case ',':
|
||||
json.Read();
|
||||
return TOKEN.COMMA;
|
||||
case '"':
|
||||
return TOKEN.STRING;
|
||||
case ':':
|
||||
return TOKEN.COLON;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case '-':
|
||||
return TOKEN.NUMBER;
|
||||
}
|
||||
|
||||
switch (NextWord) {
|
||||
case "false":
|
||||
return TOKEN.FALSE;
|
||||
case "true":
|
||||
return TOKEN.TRUE;
|
||||
case "null":
|
||||
return TOKEN.NULL;
|
||||
}
|
||||
|
||||
return TOKEN.NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a IDictionary / IList object or a simple type (string, int, etc.) into a JSON string
|
||||
/// </summary>
|
||||
/// <param name="json">A Dictionary<string, object> / List<object></param>
|
||||
/// <returns>A JSON encoded string, or null if object 'json' is not serializable</returns>
|
||||
public static string Serialize(object obj) {
|
||||
return Serializer.Serialize(obj);
|
||||
}
|
||||
|
||||
sealed class Serializer {
|
||||
StringBuilder builder;
|
||||
|
||||
Serializer() {
|
||||
builder = new StringBuilder();
|
||||
}
|
||||
|
||||
public static string Serialize(object obj) {
|
||||
var instance = new Serializer();
|
||||
|
||||
instance.SerializeValue(obj);
|
||||
|
||||
return instance.builder.ToString();
|
||||
}
|
||||
|
||||
void SerializeValue(object value) {
|
||||
IList asList;
|
||||
IDictionary asDict;
|
||||
string asStr;
|
||||
|
||||
if (value == null) {
|
||||
builder.Append("null");
|
||||
} else if ((asStr = value as string) != null) {
|
||||
SerializeString(asStr);
|
||||
} else if (value is bool) {
|
||||
builder.Append((bool) value ? "true" : "false");
|
||||
} else if ((asList = value as IList) != null) {
|
||||
SerializeArray(asList);
|
||||
} else if ((asDict = value as IDictionary) != null) {
|
||||
SerializeObject(asDict);
|
||||
} else if (value is char) {
|
||||
SerializeString(new string((char) value, 1));
|
||||
} else {
|
||||
SerializeOther(value);
|
||||
}
|
||||
}
|
||||
|
||||
void SerializeObject(IDictionary obj) {
|
||||
bool first = true;
|
||||
|
||||
builder.Append('{');
|
||||
|
||||
foreach (object e in obj.Keys) {
|
||||
if (!first) {
|
||||
builder.Append(',');
|
||||
}
|
||||
|
||||
SerializeString(e.ToString());
|
||||
builder.Append(':');
|
||||
|
||||
SerializeValue(obj[e]);
|
||||
|
||||
first = false;
|
||||
}
|
||||
|
||||
builder.Append('}');
|
||||
}
|
||||
|
||||
void SerializeArray(IList anArray) {
|
||||
builder.Append('[');
|
||||
|
||||
bool first = true;
|
||||
|
||||
foreach (object obj in anArray) {
|
||||
if (!first) {
|
||||
builder.Append(',');
|
||||
}
|
||||
|
||||
SerializeValue(obj);
|
||||
|
||||
first = false;
|
||||
}
|
||||
|
||||
builder.Append(']');
|
||||
}
|
||||
|
||||
void SerializeString(string str) {
|
||||
builder.Append('\"');
|
||||
|
||||
char[] charArray = str.ToCharArray();
|
||||
foreach (var c in charArray) {
|
||||
switch (c) {
|
||||
case '"':
|
||||
builder.Append("\\\"");
|
||||
break;
|
||||
case '\\':
|
||||
builder.Append("\\\\");
|
||||
break;
|
||||
case '\b':
|
||||
builder.Append("\\b");
|
||||
break;
|
||||
case '\f':
|
||||
builder.Append("\\f");
|
||||
break;
|
||||
case '\n':
|
||||
builder.Append("\\n");
|
||||
break;
|
||||
case '\r':
|
||||
builder.Append("\\r");
|
||||
break;
|
||||
case '\t':
|
||||
builder.Append("\\t");
|
||||
break;
|
||||
default:
|
||||
int codepoint = Convert.ToInt32(c);
|
||||
if ((codepoint >= 32) && (codepoint <= 126)) {
|
||||
builder.Append(c);
|
||||
} else {
|
||||
builder.Append("\\u");
|
||||
builder.Append(codepoint.ToString("x4"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
builder.Append('\"');
|
||||
}
|
||||
|
||||
void SerializeOther(object value) {
|
||||
// NOTE: decimals lose precision during serialization.
|
||||
// They always have, I'm just letting you know.
|
||||
// Previously floats and doubles lost precision too.
|
||||
if (value is float) {
|
||||
builder.Append(((float) value).ToString("R"));
|
||||
} else if (value is int
|
||||
|| value is uint
|
||||
|| value is long
|
||||
|| value is sbyte
|
||||
|| value is byte
|
||||
|| value is short
|
||||
|| value is ushort
|
||||
|| value is ulong) {
|
||||
builder.Append(value);
|
||||
} else if (value is double
|
||||
|| value is decimal) {
|
||||
builder.Append(Convert.ToDouble(value).ToString("R"));
|
||||
} else {
|
||||
SerializeString(value.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/AppsFlyer/AFMiniJSON.cs.meta
Normal file
11
Assets/AppsFlyer/AFMiniJSON.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bc3d1c806d507463e9b560eb09d8eb0e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
30
Assets/AppsFlyer/AFPurchaseDetailsAndroid.cs
Normal file
30
Assets/AppsFlyer/AFPurchaseDetailsAndroid.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AppsFlyerSDK
|
||||
{
|
||||
public enum AFPurchaseType
|
||||
{
|
||||
Subscription = 0,
|
||||
OneTimePurchase = 1
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Purchase details class matching Android SDK AFPurchaseDetails
|
||||
/// </summary>
|
||||
public class AFPurchaseDetailsAndroid
|
||||
{
|
||||
public AFPurchaseType purchaseType { get; private set; }
|
||||
public string purchaseToken { get; private set; }
|
||||
public string productId { get; private set; }
|
||||
|
||||
public AFPurchaseDetailsAndroid(AFPurchaseType type, String purchaseToken, String productId)
|
||||
{
|
||||
this.purchaseType = type;
|
||||
this.purchaseToken = purchaseToken;
|
||||
this.productId = productId;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
11
Assets/AppsFlyer/AFPurchaseDetailsAndroid.cs.meta
Normal file
11
Assets/AppsFlyer/AFPurchaseDetailsAndroid.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d71b3864006f94ac08938b2ebdc940bc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
37
Assets/AppsFlyer/AFSDKPurchaseDetailsIOS.cs
Normal file
37
Assets/AppsFlyer/AFSDKPurchaseDetailsIOS.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AppsFlyerSDK
|
||||
{
|
||||
/// <summary>
|
||||
/// Purchase type enum matching iOS SDK AFSDKPurchaseType
|
||||
/// </summary>
|
||||
public enum AFSDKPurchaseType
|
||||
{
|
||||
Subscription,
|
||||
OneTimePurchase
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Purchase details class matching iOS SDK AFSDKPurchaseDetails
|
||||
/// </summary>
|
||||
public class AFSDKPurchaseDetailsIOS
|
||||
{
|
||||
public string productId { get; private set; }
|
||||
public string transactionId { get; private set; }
|
||||
public AFSDKPurchaseType purchaseType { get; private set; }
|
||||
|
||||
private AFSDKPurchaseDetailsIOS(string productId, string transactionId, AFSDKPurchaseType purchaseType)
|
||||
{
|
||||
this.productId = productId;
|
||||
this.transactionId = transactionId;
|
||||
this.purchaseType = purchaseType;
|
||||
}
|
||||
|
||||
public static AFSDKPurchaseDetailsIOS Init(string productId, string transactionId, AFSDKPurchaseType purchaseType)
|
||||
{
|
||||
return new AFSDKPurchaseDetailsIOS(productId, transactionId, purchaseType);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
11
Assets/AppsFlyer/AFSDKPurchaseDetailsIOS.cs.meta
Normal file
11
Assets/AppsFlyer/AFSDKPurchaseDetailsIOS.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 44bb6c4472701416080eb050732075ea
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
38
Assets/AppsFlyer/AFSDKValidateAndLogResult.cs
Normal file
38
Assets/AppsFlyer/AFSDKValidateAndLogResult.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AppsFlyerSDK
|
||||
{
|
||||
public enum AFSDKValidateAndLogStatus
|
||||
{
|
||||
AFSDKValidateAndLogStatusSuccess,
|
||||
AFSDKValidateAndLogStatusFailure,
|
||||
AFSDKValidateAndLogStatusError
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
//
|
||||
/// </summary>
|
||||
public class AFSDKValidateAndLogResult
|
||||
{
|
||||
public AFSDKValidateAndLogStatus status { get; private set; }
|
||||
public Dictionary<string, object> result { get; private set; }
|
||||
public Dictionary<string, object> errorData { get; private set; }
|
||||
public string error { get; private set; }
|
||||
|
||||
private AFSDKValidateAndLogResult(AFSDKValidateAndLogStatus status, Dictionary<string, object> result, Dictionary<string, object> errorData, string error)
|
||||
{
|
||||
this.status = status;
|
||||
this.result = result;
|
||||
this.errorData = errorData;
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
public static AFSDKValidateAndLogResult Init(AFSDKValidateAndLogStatus status, Dictionary<string, object> result, Dictionary<string, object> errorData, string error)
|
||||
{
|
||||
return new AFSDKValidateAndLogResult(status, result, errorData, error);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
11
Assets/AppsFlyer/AFSDKValidateAndLogResult.cs.meta
Normal file
11
Assets/AppsFlyer/AFSDKValidateAndLogResult.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2df1c6f1eab2e4849bf2762a8d78933f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
13
Assets/AppsFlyer/AppsFlyer.asmdef
Normal file
13
Assets/AppsFlyer/AppsFlyer.asmdef
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "AppsFlyer",
|
||||
"references": [],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
7
Assets/AppsFlyer/AppsFlyer.asmdef.meta
Normal file
7
Assets/AppsFlyer/AppsFlyer.asmdef.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2a37df438292d4903b4e5159c5de3bf9
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1113
Assets/AppsFlyer/AppsFlyer.cs
Normal file
1113
Assets/AppsFlyer/AppsFlyer.cs
Normal file
File diff suppressed because it is too large
Load Diff
11
Assets/AppsFlyer/AppsFlyer.cs.meta
Normal file
11
Assets/AppsFlyer/AppsFlyer.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 45161025a517d427381d3d06153a5ad3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
852
Assets/AppsFlyer/AppsFlyerAndroid.cs
Normal file
852
Assets/AppsFlyer/AppsFlyerAndroid.cs
Normal file
@@ -0,0 +1,852 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AppsFlyerSDK
|
||||
{
|
||||
|
||||
#if UNITY_ANDROID
|
||||
public class AppsFlyerAndroid : IAppsFlyerAndroidBridge
|
||||
{
|
||||
public bool isInit { get; set; }
|
||||
|
||||
private static AndroidJavaClass appsFlyerAndroid = new AndroidJavaClass("com.appsflyer.unity.AppsFlyerAndroidWrapper");
|
||||
|
||||
public AppsFlyerAndroid() { }
|
||||
|
||||
/// <summary>
|
||||
/// Use this method to init the sdk for the application.
|
||||
/// Call this method before startSDK.
|
||||
/// </summary>
|
||||
/// <param name="devkey"> AppsFlyer's Dev-Key, which is accessible from your AppsFlyer account under 'App Settings' in the dashboard.</param>
|
||||
/// <param name="gameObject">The current game object. This is used to get the conversion data callbacks. Pass null if you do not need the callbacks.</param>
|
||||
public void initSDK(string devkey, MonoBehaviour gameObject)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("initSDK", devkey, gameObject ? gameObject.name : null);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use this method to start the sdk for the application.
|
||||
/// The AppsFlyer's Dev-Key must be provided.
|
||||
/// </summary>
|
||||
/// <param name="devkey"> AppsFlyer's Dev-Key, which is accessible from your AppsFlyer account under 'App Settings' in the dashboard.</param>
|
||||
public void startSDK(bool onRequestResponse, string CallBackObjectName)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("startTracking", onRequestResponse, CallBackObjectName);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Once this API is invoked, our SDK no longer communicates with our servers and stops functioning.
|
||||
/// In some extreme cases you might want to shut down all SDK activity due to legal and privacy compliance.
|
||||
/// This can be achieved with the stopSDK API.
|
||||
/// </summary>
|
||||
/// <param name="isSDKStopped">boolean should SDK be stopped.</param>
|
||||
public void stopSDK(bool isSDKStopped)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("stopTracking", isSDKStopped);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the AppsFlyer SDK version used in app.
|
||||
/// </summary>
|
||||
/// <returns>AppsFlyer SDK version.</returns>
|
||||
public string getSdkVersion()
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
return appsFlyerAndroid.CallStatic<string>("getSdkVersion");
|
||||
#else
|
||||
return "";
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manually pass the Firebase / GCM Device Token for Uninstall measurement.
|
||||
/// </summary>
|
||||
/// <param name="token">Firebase Device Token.</param>
|
||||
public void updateServerUninstallToken(string token)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("updateServerUninstallToken", token);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enables Debug logs for the AppsFlyer SDK.
|
||||
/// Should only be set to true in development / debug.
|
||||
/// </summary>
|
||||
/// <param name="shouldEnable">shouldEnable boolean.</param>
|
||||
public void setIsDebug(bool shouldEnable)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("setIsDebug", shouldEnable);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// By default, IMEI and Android ID are not collected by the SDK if the OS version is higher than KitKat (4.4)
|
||||
/// and the device contains Google Play Services(on SDK versions 4.8.8 and below the specific app needed GPS).
|
||||
/// Use this API to explicitly send IMEI to AppsFlyer.
|
||||
/// </summary>
|
||||
/// <param name="aImei">device's IMEI.</param>
|
||||
public void setImeiData(string aImei)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("setImeiData", aImei);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// By default, IMEI and Android ID are not collected by the SDK if the OS version is higher than KitKat(4.4)
|
||||
/// and the device contains Google Play Services(on SDK versions 4.8.8 and below the specific app needed GPS).
|
||||
/// Use this API to explicitly send Android ID to AppsFlyer.
|
||||
/// </summary>
|
||||
/// <param name="aAndroidId">device's Android ID.</param>
|
||||
public void setAndroidIdData(string aAndroidId)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("setAndroidIdData", aAndroidId);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Setting your own customer ID enables you to cross-reference your own unique ID with AppsFlyer’s unique ID and the other devices’ IDs.
|
||||
/// This ID is available in AppsFlyer CSV reports along with Postback APIs for cross-referencing with your internal IDs.
|
||||
/// </summary>
|
||||
/// <param name="id">Customer ID for client.</param>
|
||||
public void setCustomerUserId(string id)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("setCustomerUserId", id);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// It is possible to delay the SDK Initialization until the customerUserID is set.
|
||||
/// This feature makes sure that the SDK doesn't begin functioning until the customerUserID is provided.
|
||||
/// If this API is used, all in-app events and any other SDK API calls are discarded, until the customerUserID is provided.
|
||||
/// </summary>
|
||||
/// <param name="wait">wait boolean.</param>
|
||||
public void waitForCustomerUserId(bool wait)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("waitForCustomerUserId", wait);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use this API to provide the SDK with the relevant customer user id and trigger the SDK to begin its normal activity.
|
||||
/// </summary>
|
||||
/// <param name="id">Customer ID for client.</param>
|
||||
public void setCustomerIdAndStartSDK(string id)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("setCustomerIdAndTrack", id);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the current AF_STORE value.
|
||||
/// </summary>
|
||||
/// <returns>AF_Store value.</returns>
|
||||
public string getOutOfStore()
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
return appsFlyerAndroid.CallStatic<string>("getOutOfStore");
|
||||
#else
|
||||
return "";
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manually set the AF_STORE value.
|
||||
/// </summary>
|
||||
/// <param name="sourceName">value to be set.</param>
|
||||
public void setOutOfStore(string sourceName)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("setOutOfStore", sourceName);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the OneLink ID that should be used for User-Invites.
|
||||
/// The link that is generated for the user invite will use this OneLink as the base link.
|
||||
/// </summary>
|
||||
/// <param name="oneLinkId">OneLink ID obtained from the AppsFlyer Dashboard.</param>
|
||||
public void setAppInviteOneLinkID(string oneLinkId)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("setAppInviteOneLinkID", oneLinkId);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set additional data to be sent to AppsFlyer.
|
||||
/// </summary>
|
||||
/// <param name="customData">additional data Dictionary.</param>
|
||||
public void setAdditionalData(Dictionary<string, string> customData)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("setAdditionalData", convertDictionaryToJavaMap(customData));
|
||||
#endif
|
||||
}
|
||||
|
||||
//// <summary>
|
||||
/// Set the deepLink timeout value that should be used for DDL.
|
||||
/// </summary>
|
||||
/// <param name="deepLinkTimeout">deepLink timeout in milliseconds.</param>
|
||||
public void setDeepLinkTimeout(long deepLinkTimeout)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("setDeepLinkTimeout", deepLinkTimeout);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the user emails.
|
||||
/// </summary>
|
||||
/// <param name="emails">User emails.</param>
|
||||
public void setUserEmails(params string[] userEmails)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("setUserEmails", (object)userEmails);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Set the user phone number.
|
||||
/// </summary>
|
||||
/// <param name="phoneNumber">User phoneNumber.</param>
|
||||
public void setPhoneNumber(string phoneNumber){
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("setPhoneNumber", phoneNumber);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the user emails and encrypt them.
|
||||
/// cryptMethod Encryption method:
|
||||
/// EmailCryptType.EmailCryptTypeMD5
|
||||
/// EmailCryptType.EmailCryptTypeSHA1
|
||||
/// EmailCryptType.EmailCryptTypeSHA256
|
||||
/// EmailCryptType.EmailCryptTypeNone
|
||||
/// </summary>
|
||||
/// <param name="cryptMethod">Encryption method.</param>
|
||||
/// <param name="emails">User emails.</param>
|
||||
public void setUserEmails(EmailCryptType cryptMethod, params string[] emails)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("setUserEmails", getEmailType(cryptMethod), (object)emails);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opt-out of collection of Android ID.
|
||||
/// If the app does NOT contain Google Play Services, Android ID is collected by the SDK.
|
||||
/// However, apps with Google play services should avoid Android ID collection as this is in violation of the Google Play policy.
|
||||
/// </summary>
|
||||
/// <param name="isCollect">boolean, false to opt-out.</param>
|
||||
public void setCollectAndroidID(bool isCollect)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("setCollectAndroidID", isCollect);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opt-out of collection of IMEI.
|
||||
/// If the app does NOT contain Google Play Services, device IMEI is collected by the SDK.
|
||||
/// However, apps with Google play services should avoid IMEI collection as this is in violation of the Google Play policy.
|
||||
/// </summary>
|
||||
/// <param name="isCollect">boolean, false to opt-out.</param>
|
||||
public void setCollectIMEI(bool isCollect)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("setCollectIMEI", isCollect);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Advertisers can wrap AppsFlyer OneLink within another Universal Link.
|
||||
/// This Universal Link will invoke the app but any deep linking data will not propagate to AppsFlyer.
|
||||
/// </summary>
|
||||
/// <param name="urls">Array of urls.</param>
|
||||
public void setResolveDeepLinkURLs(params string[] urls)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("setResolveDeepLinkURLs", (object)urls);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Advertisers can use this method to set vanity onelink domains.
|
||||
/// </summary>
|
||||
/// <param name="domains">Array of domains.</param>
|
||||
public void setOneLinkCustomDomain(params string[] domains)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("setOneLinkCustomDomain", (object)domains);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manually set that the application was updated.
|
||||
/// </summary>
|
||||
/// <param name="isUpdate">isUpdate boolean value.</param>
|
||||
public void setIsUpdate(bool isUpdate)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("setIsUpdate", isUpdate);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Setting user local currency code for in-app purchases.
|
||||
/// The currency code should be a 3 character ISO 4217 code. (default is USD).
|
||||
/// You can set the currency code for all events by calling the following method.
|
||||
/// </summary>
|
||||
/// <param name="currencyCode">3 character ISO 4217 code.</param>
|
||||
public void setCurrencyCode(string currencyCode)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("setCurrencyCode", currencyCode);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manually record the location of the user.
|
||||
/// </summary>
|
||||
/// <param name="latitude">latitude as double.</param>
|
||||
/// <param name="longitude">longitude as double.</param>
|
||||
public void recordLocation(double latitude, double longitude)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("trackLocation", latitude, longitude);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send an In-App Event.
|
||||
/// In-App Events provide insight on what is happening in your app.
|
||||
/// </summary>
|
||||
/// <param name="eventName">Event Name as String.</param>
|
||||
/// <param name="eventValues">Event Values as Dictionary.</param>
|
||||
public void sendEvent(string eventName, Dictionary<string, string> eventValues)
|
||||
{
|
||||
sendEvent(eventName, eventValues, false, AppsFlyer.CallBackObjectName);
|
||||
}
|
||||
|
||||
public void sendEvent(string eventName, Dictionary<string, string> eventValues, bool shouldCallback, string callBackObjectName)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("trackEvent", eventName, convertDictionaryToJavaMap(eventValues), shouldCallback, callBackObjectName);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Anonymize user Data.
|
||||
/// Use this API during the SDK Initialization to explicitly anonymize a user's installs, events and sessions.
|
||||
/// Default is false.
|
||||
/// </summary>
|
||||
/// <param name="isDisabled">isDisabled boolean.</param>
|
||||
public void anonymizeUser(bool isDisabled)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("setDeviceTrackingDisabled", isDisabled);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calling enableTCFDataCollection(true) will enable collecting and sending any TCF related data.
|
||||
/// Calling enableTCFDataCollection(false) will disable the collection of TCF related data and from sending it.
|
||||
/// </summary>
|
||||
/// <param name = "shouldCollectTcfData" >should start TCF Data collection boolean.</param>
|
||||
public void enableTCFDataCollection(bool shouldCollectTcfData)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("enableTCFDataCollection", shouldCollectTcfData);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enable the collection of Facebook Deferred AppLinks.
|
||||
/// Requires Facebook SDK and Facebook app on target/client device.
|
||||
/// This API must be invoked prior to initializing the AppsFlyer SDK in order to function properly.
|
||||
/// </summary>
|
||||
/// <param name="isEnabled">should Facebook's deferred app links be processed by the AppsFlyer SDK.</param>
|
||||
public void enableFacebookDeferredApplinks(bool isEnabled)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("enableFacebookDeferredApplinks", isEnabled);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets or updates the user consent data related to GDPR and DMA regulations for advertising and data usage purposes within the application.
|
||||
/// call this method when GDPR user is true
|
||||
/// </summary>
|
||||
/// <param name = "hasConsentForDataUsage" >hasConsentForDataUsage boolean.</param>
|
||||
/// <param name = "hasConsentForAdsPersonalization" >hasConsentForAdsPersonalization boolean.</param>
|
||||
public void setConsentData(AppsFlyerConsent appsFlyerConsent)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
string isUserSubjectToGDPR = appsFlyerConsent.isUserSubjectToGDPR?.ToString().ToLower() ?? "null";
|
||||
string hasConsentForDataUsage = appsFlyerConsent.hasConsentForDataUsage?.ToString().ToLower() ?? "null";
|
||||
string hasConsentForAdsPersonalization = appsFlyerConsent.hasConsentForAdsPersonalization?.ToString().ToLower() ?? "null";
|
||||
string hasConsentForAdStorage = appsFlyerConsent.hasConsentForAdStorage?.ToString().ToLower() ?? "null";
|
||||
|
||||
appsFlyerAndroid.CallStatic("setConsentData", isUserSubjectToGDPR, hasConsentForDataUsage, hasConsentForAdsPersonalization, hasConsentForAdStorage);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs ad revenue data along with additional parameters if provided.
|
||||
/// <param name = "adRevenueData" >instance of AFAdRevenueData containing ad revenue information.</param>
|
||||
/// <param name = "additionalParameters" >An optional map of additional parameters to be logged with ad revenue data. This can be null if there are no additional parameters.</param>
|
||||
public void logAdRevenue(AFAdRevenueData adRevenueData, Dictionary<string, string> additionalParameters)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("logAdRevenue", adRevenueData.monetizationNetwork, getMediationNetwork(adRevenueData.mediationNetwork), adRevenueData.currencyIso4217Code, adRevenueData.eventRevenue, convertDictionaryToJavaMap(additionalParameters));
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restrict reengagement via deep-link to once per each unique deep-link.
|
||||
/// Otherwise deep re-occurring deep-links will be permitted for non-singleTask Activities and deep-linking via AppsFlyer deep-links.
|
||||
/// The default value is false.
|
||||
/// </summary>
|
||||
/// <param name="doConsume">doConsume boolean.</param>
|
||||
public void setConsumeAFDeepLinks(bool doConsume)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("setConsumeAFDeepLinks", doConsume);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specify the manufacturer or media source name to which the preinstall is attributed.
|
||||
/// </summary>
|
||||
/// <param name="mediaSource">Manufacturer or media source name for preinstall attribution.</param>
|
||||
/// <param name="campaign">Campaign name for preinstall attribution.</param>
|
||||
/// <param name="siteId">Site ID for preinstall attribution.</param>
|
||||
public void setPreinstallAttribution(string mediaSource, string campaign, string siteId)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("setPreinstallAttribution", mediaSource, campaign, siteId);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Boolean indicator for preinstall by Manufacturer.
|
||||
/// </summary>
|
||||
/// <returns>boolean isPreInstalledApp.</returns>
|
||||
public bool isPreInstalledApp()
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
return appsFlyerAndroid.CallStatic<bool>("isPreInstalledApp");
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the Facebook attribution ID, if one exists.
|
||||
/// </summary>
|
||||
/// <returns>string Facebook attribution ID.</returns>
|
||||
public string getAttributionId()
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
return appsFlyerAndroid.CallStatic<string>("getAttributionId");
|
||||
#else
|
||||
return "";
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get AppsFlyer's unique device ID is created for every new install of an app.
|
||||
/// </summary>
|
||||
/// <returns>AppsFlyer's unique device ID.</returns>
|
||||
public string getAppsFlyerId()
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
return appsFlyerAndroid.CallStatic<string>("getAppsFlyerId");
|
||||
#else
|
||||
return "";
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// [Deprecated] API for server verification of in-app purchases - please use V2 with AFPurchaseDetailsAndroid instead.
|
||||
/// An af_purchase event with the relevant values will be automatically sent if the validation is successful.
|
||||
/// </summary>
|
||||
/// <param name="publicKey">License Key obtained from the Google Play Console.</param>
|
||||
/// <param name="signature"><code>data.INAPP_DATA_SIGNATURE</code> from <code>onActivityResult(int requestCode, int resultCode, Intent data)</code></param>
|
||||
/// <param name="purchaseData"><code>data.INAPP_PURCHASE_DATA</code> from <code>onActivityResult(int requestCode, int resultCode, Intent data)</code></param>
|
||||
/// <param name="price">Purchase price, should be derived from <code>skuDetails.getStringArrayList("DETAILS_LIST")</code></param>
|
||||
/// <param name="currency">Purchase currency, should be derived from <code>skuDetails.getStringArrayList("DETAILS_LIST")</code></param>
|
||||
/// <param name="additionalParameters">additionalParameters Freehand parameters to be sent with the purchase (if validated).</param>
|
||||
[System.Obsolete("This method is deprecated. Use validateAndSendInAppPurchase(AFPurchaseDetailsAndroid details, Dictionary<string, string> purchaseAdditionalDetails, MonoBehaviour gameObject) instead.")]
|
||||
public void validateAndSendInAppPurchase(string publicKey, string signature, string purchaseData, string price, string currency, Dictionary<string, string> additionalParameters, MonoBehaviour gameObject)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("validateAndTrackInAppPurchase", publicKey, signature, purchaseData, price, currency, convertDictionaryToJavaMap(additionalParameters), gameObject ? gameObject.name : null);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// V2 - API for server verification of in-app purchases.
|
||||
/// An af_purchase event with the relevant values will be automatically sent if the validation is successful.
|
||||
/// </summary>
|
||||
/// <param name="details">AFPurchaseDetailsAndroid instance.</param>
|
||||
/// <param name="purchaseAdditionalDetails">purchaseAdditionalDetails Freehand parameters to be sent with the purchase (if validated).</param>
|
||||
public void validateAndSendInAppPurchase(AFPurchaseDetailsAndroid details, Dictionary<string, string> purchaseAdditionalDetails, MonoBehaviour gameObject)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("validateAndTrackInAppPurchaseV2", (int)details.purchaseType, details.purchaseToken, details.productId, convertDictionaryToJavaMap(purchaseAdditionalDetails), gameObject ? gameObject.name : null);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Was the stopSDK(boolean) API set to true.
|
||||
/// </summary>
|
||||
/// <returns>boolean isSDKStopped.</returns>
|
||||
public bool isSDKStopped()
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
return appsFlyerAndroid.CallStatic<bool>("isTrackingStopped");
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a custom value for the minimum required time between sessions.
|
||||
/// By default, at least 5 seconds must lapse between 2 app launches to count as separate 2 sessions.
|
||||
/// </summary>
|
||||
/// <param name="seconds">minimum time between 2 separate sessions in seconds.</param>
|
||||
public void setMinTimeBetweenSessions(int seconds)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("setMinTimeBetweenSessions", seconds);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a custom host.
|
||||
/// </summary>
|
||||
/// <param name="hostPrefixName">Host prefix.</param>
|
||||
/// <param name="hostName">Host name.</param>
|
||||
public void setHost(string hostPrefixName, string hostName)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("setHost", hostPrefixName, hostName);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the host name.
|
||||
/// Default value is "appsflyer.com".
|
||||
/// </summary>
|
||||
/// <returns>Host name.</returns>
|
||||
public string getHostName()
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
return appsFlyerAndroid.CallStatic<string>("getHostName");
|
||||
#else
|
||||
return "";
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the custom host prefix.
|
||||
/// </summary>
|
||||
/// <returns>Host prefix.</returns>
|
||||
public string getHostPrefix()
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
return appsFlyerAndroid.CallStatic<string>("getHostPrefix");
|
||||
#else
|
||||
return "";
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used by advertisers to exclude all networks/integrated partners from getting data.
|
||||
/// </summary>
|
||||
public void setSharingFilterForAllPartners()
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("setSharingFilterForAllPartners");
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used by advertisers to set some (one or more) networks/integrated partners to exclude from getting data.
|
||||
/// </summary>
|
||||
/// <param name="partners">partners to exclude from getting data</param>
|
||||
public void setSharingFilter(params string[] partners)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("setSharingFilter", (object)partners);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lets you configure how which partners should the SDK exclude from data-sharing.
|
||||
/// </summary>
|
||||
/// <param name="partners">partners to exclude from getting data</param>
|
||||
public static void setSharingFilterForPartners(params string[] partners)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("setSharingFilterForPartners", (object)partners);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register a Conversion Data Listener.
|
||||
/// Allows the developer to access the user attribution data in real-time for every new install, directly from the SDK level.
|
||||
/// By doing this you can serve users with personalized content or send them to specific activities within the app,
|
||||
/// which can greatly enhance their engagement with your app.
|
||||
/// </summary>
|
||||
public void getConversionData(string objectName)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("getConversionData", objectName);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register a validation listener for the validateAndSendInAppPurchase API.
|
||||
/// </summary>
|
||||
public void initInAppPurchaseValidatorListener(MonoBehaviour gameObject)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("initInAppPurchaseValidatorListener", gameObject ? gameObject.name : null);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// setCollectOaid
|
||||
/// You must include the appsflyer oaid library for this api to work.
|
||||
/// </summary>
|
||||
/// <param name="isCollect">isCollect oaid - set fasle to opt out</param>
|
||||
public void setCollectOaid(bool isCollect)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("setCollectOaid", isCollect);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use the following API to attribute the click and launch the app store's app page.
|
||||
/// </summary>
|
||||
/// <param name="promoted_app_id">promoted App ID</param>
|
||||
/// <param name="campaign">cross promotion campaign</param>
|
||||
/// <param name="userParams">additional user params</param>
|
||||
public void attributeAndOpenStore(string promoted_app_id, string campaign, Dictionary<string, string> userParams, MonoBehaviour gameObject)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("attributeAndOpenStore", promoted_app_id, campaign, convertDictionaryToJavaMap(userParams));
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// To attribute an impression use the following API call.
|
||||
/// Make sure to use the promoted App ID as it appears within the AppsFlyer dashboard.
|
||||
/// </summary>
|
||||
/// <param name="appID">promoted App ID.</param>
|
||||
/// <param name="campaign">cross promotion campaign.</param>
|
||||
/// <param name="parameters">parameters Dictionary.</param>
|
||||
public void recordCrossPromoteImpression(string appID, string campaign, Dictionary<string, string> parameters)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("recordCrossPromoteImpression", appID, campaign, convertDictionaryToJavaMap(parameters));
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The LinkGenerator class builds the invite URL according to various setter methods which allow passing on additional information on the click.
|
||||
/// See - https://support.appsflyer.com/hc/en-us/articles/115004480866-User-invite-attribution-
|
||||
/// </summary>
|
||||
/// <param name="parameters">parameters Dictionary.</param>
|
||||
public void generateUserInviteLink(Dictionary<string, string> parameters, MonoBehaviour gameObject)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("createOneLinkInviteListener", convertDictionaryToJavaMap(parameters), gameObject ? gameObject.name : null);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// To measure push notifications as part of a retargeting campaign.
|
||||
/// </summary>
|
||||
public void handlePushNotifications(){
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("handlePushNotifications");
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use this method if you’re integrating your app with push providers
|
||||
/// that don’t use the default push notification JSON schema the SDK expects.
|
||||
/// See docs for more info.
|
||||
/// </summary>
|
||||
/// <param name="paths">array of nested json path</param>
|
||||
public void addPushNotificationDeepLinkPath(params string[] paths)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("addPushNotificationDeepLinkPath", (object)paths);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// subscribe to unified deep link callbacks
|
||||
/// </summary>
|
||||
public void subscribeForDeepLink(string objectName){
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("subscribeForDeepLink", objectName);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disables collection of various Advertising IDs by the SDK. This includes Google Advertising ID (GAID), OAID and Amazon Advertising ID (AAID)
|
||||
/// </summary>
|
||||
/// <param name="disable">disable boolean.</param>
|
||||
public void setDisableAdvertisingIdentifiers(bool disable)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("setDisableAdvertisingIdentifiers", disable);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows sending custom data for partner integration purposes.
|
||||
/// </summary>
|
||||
public void setPartnerData(string partnerId, Dictionary<string, string> partnerInfo)
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("setPartnerData", partnerId, convertDictionaryToJavaMap(partnerInfo));
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use to opt-out of collecting the network operator name (carrier) and sim operator name from the device.
|
||||
/// </summary>
|
||||
public void setDisableNetworkData(bool disable) {
|
||||
#if !UNITY_EDITOR
|
||||
appsFlyerAndroid.CallStatic("setDisableNetworkData", disable);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal Helper Method.
|
||||
/// </summary>
|
||||
private static AndroidJavaObject getEmailType(EmailCryptType cryptType)
|
||||
{
|
||||
AndroidJavaClass emailsCryptTypeEnum = new AndroidJavaClass("com.appsflyer.AppsFlyerProperties$EmailsCryptType");
|
||||
AndroidJavaObject emailsCryptType;
|
||||
|
||||
switch (cryptType)
|
||||
{
|
||||
case EmailCryptType.EmailCryptTypeSHA256:
|
||||
emailsCryptType = emailsCryptTypeEnum.GetStatic<AndroidJavaObject>("SHA256");
|
||||
break;
|
||||
default:
|
||||
emailsCryptType = emailsCryptTypeEnum.GetStatic<AndroidJavaObject>("NONE");
|
||||
break;
|
||||
}
|
||||
|
||||
return emailsCryptType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal Helper Method.
|
||||
/// </summary>
|
||||
private static AndroidJavaObject getMediationNetwork(MediationNetwork mediationNetwork)
|
||||
{
|
||||
AndroidJavaClass mediationNetworkEnumClass = new AndroidJavaClass("com.appsflyer.MediationNetwork");
|
||||
AndroidJavaObject mediationNetworkObject;
|
||||
|
||||
switch (mediationNetwork)
|
||||
{
|
||||
case MediationNetwork.IronSource:
|
||||
mediationNetworkObject = mediationNetworkEnumClass.GetStatic<AndroidJavaObject>("IRONSOURCE");
|
||||
break;
|
||||
case MediationNetwork.ApplovinMax:
|
||||
mediationNetworkObject = mediationNetworkEnumClass.GetStatic<AndroidJavaObject>("APPLOVIN_MAX");
|
||||
break;
|
||||
case MediationNetwork.GoogleAdMob:
|
||||
mediationNetworkObject = mediationNetworkEnumClass.GetStatic<AndroidJavaObject>("GOOGLE_ADMOB");
|
||||
break;
|
||||
case MediationNetwork.Fyber:
|
||||
mediationNetworkObject = mediationNetworkEnumClass.GetStatic<AndroidJavaObject>("FYBER");
|
||||
break;
|
||||
case MediationNetwork.Appodeal:
|
||||
mediationNetworkObject = mediationNetworkEnumClass.GetStatic<AndroidJavaObject>("APPODEAL");
|
||||
break;
|
||||
case MediationNetwork.Admost:
|
||||
mediationNetworkObject = mediationNetworkEnumClass.GetStatic<AndroidJavaObject>("ADMOST");
|
||||
break;
|
||||
case MediationNetwork.Topon:
|
||||
mediationNetworkObject = mediationNetworkEnumClass.GetStatic<AndroidJavaObject>("TOPON");
|
||||
break;
|
||||
case MediationNetwork.Tradplus:
|
||||
mediationNetworkObject = mediationNetworkEnumClass.GetStatic<AndroidJavaObject>("TRADPLUS");
|
||||
break;
|
||||
case MediationNetwork.Yandex:
|
||||
mediationNetworkObject = mediationNetworkEnumClass.GetStatic<AndroidJavaObject>("YANDEX");
|
||||
break;
|
||||
case MediationNetwork.ChartBoost:
|
||||
mediationNetworkObject = mediationNetworkEnumClass.GetStatic<AndroidJavaObject>("CHARTBOOST");
|
||||
break;
|
||||
case MediationNetwork.Unity:
|
||||
mediationNetworkObject = mediationNetworkEnumClass.GetStatic<AndroidJavaObject>("UNITY");
|
||||
break;
|
||||
case MediationNetwork.ToponPte:
|
||||
mediationNetworkObject = mediationNetworkEnumClass.GetStatic<AndroidJavaObject>("TOPON_PTE");
|
||||
break;
|
||||
case MediationNetwork.Custom:
|
||||
mediationNetworkObject = mediationNetworkEnumClass.GetStatic<AndroidJavaObject>("CUSTOM_MEDIATION");
|
||||
break;
|
||||
case MediationNetwork.DirectMonetization:
|
||||
mediationNetworkObject = mediationNetworkEnumClass.GetStatic<AndroidJavaObject>("DIRECT_MONETIZATION_NETWORK");
|
||||
break;
|
||||
default:
|
||||
mediationNetworkObject = mediationNetworkEnumClass.GetStatic<AndroidJavaObject>("NONE");
|
||||
break;
|
||||
}
|
||||
return mediationNetworkObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal Helper Method.
|
||||
/// </summary>
|
||||
private static AndroidJavaObject convertDictionaryToJavaMap(Dictionary<string, string> dictionary)
|
||||
{
|
||||
AndroidJavaObject map = new AndroidJavaObject("java.util.HashMap");
|
||||
IntPtr putMethod = AndroidJNIHelper.GetMethodID(map.GetRawClass(), "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
|
||||
jvalue[] val;
|
||||
if (dictionary != null)
|
||||
{
|
||||
foreach (var entry in dictionary)
|
||||
{
|
||||
val = AndroidJNIHelper.CreateJNIArgArray(new object[] { entry.Key, entry.Value });
|
||||
AndroidJNI.CallObjectMethod(map.GetRawObject(), putMethod,val);
|
||||
AndroidJNI.DeleteLocalRef(val[0].l);
|
||||
AndroidJNI.DeleteLocalRef(val[1].l);
|
||||
}
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
11
Assets/AppsFlyer/AppsFlyerAndroid.cs.meta
Normal file
11
Assets/AppsFlyer/AppsFlyerAndroid.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 172d18dd98e7e4ed3b30110568b0fae4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
71
Assets/AppsFlyer/AppsFlyerConsent.cs
Normal file
71
Assets/AppsFlyer/AppsFlyerConsent.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AppsFlyerSDK
|
||||
{
|
||||
/// <summary>
|
||||
// Data class representing a user's consent for data processing in accordance with GDPR and DMA
|
||||
// (Digital Markets Act) compliance, specifically regarding advertising preferences.
|
||||
|
||||
// This class should be used to notify and record the user's applicability
|
||||
// under GDPR, their general consent to data usage, and their consent to personalized
|
||||
// advertisements based on user data.
|
||||
|
||||
/// ## Properties:
|
||||
/// - `isUserSubjectToGDPR` (optional) - Indicates whether GDPR regulations apply to the user.
|
||||
/// This may also serve as a general compliance flag for other regional regulations.
|
||||
/// - `hasConsentForDataUsage` (optional) - Indicates whether the user consents to the processing
|
||||
/// of their data for advertising purposes.
|
||||
/// - `hasConsentForAdsPersonalization` (optional) - Indicates whether the user consents to the
|
||||
/// use of their data for personalized advertising.
|
||||
/// - `hasConsentForAdStorage` (optional) - Indicates whether the user consents to ad-related storage access.
|
||||
///
|
||||
/// **Usage Example:**
|
||||
/// ```csharp
|
||||
/// var consent = new AppsFlyerConsent(
|
||||
/// isUserSubjectToGDPR: true,
|
||||
/// hasConsentForDataUsage: true,
|
||||
/// hasConsentForAdsPersonalization: false,
|
||||
/// hasConsentForAdStorage: true
|
||||
/// );
|
||||
/// **Deprecated APIs:**
|
||||
/// - `ForGDPRUser(...)` and `ForNonGDPRUser(...)` should no longer be used.
|
||||
/// - Use `new AppsFlyerConsent(...)` instead with relevant consent fields.
|
||||
///
|
||||
/// </summary>
|
||||
public class AppsFlyerConsent
|
||||
{
|
||||
public bool? isUserSubjectToGDPR { get; private set; }
|
||||
public bool? hasConsentForDataUsage { get; private set; }
|
||||
public bool? hasConsentForAdsPersonalization { get; private set; }
|
||||
public bool? hasConsentForAdStorage { get; private set; }
|
||||
|
||||
public AppsFlyerConsent( bool? isUserSubjectToGDPR = null, bool? hasConsentForDataUsage = null, bool? hasConsentForAdsPersonalization = null, bool? hasConsentForAdStorage = null)
|
||||
{
|
||||
this.isUserSubjectToGDPR = isUserSubjectToGDPR;
|
||||
this.hasConsentForDataUsage = hasConsentForDataUsage;
|
||||
this.hasConsentForAdsPersonalization = hasConsentForAdsPersonalization;
|
||||
this.hasConsentForAdStorage = hasConsentForAdStorage;
|
||||
}
|
||||
|
||||
[Obsolete("Use the new constructor with optional booleans instead.")]
|
||||
private AppsFlyerConsent(bool isGDPR, bool hasForDataUsage, bool hasForAdsPersonalization)
|
||||
{
|
||||
isUserSubjectToGDPR = isGDPR;
|
||||
hasConsentForDataUsage = hasForDataUsage;
|
||||
hasConsentForAdsPersonalization = hasForAdsPersonalization;
|
||||
}
|
||||
|
||||
[Obsolete("Use new AppsFlyerConsent(...) instead.")]
|
||||
public static AppsFlyerConsent ForGDPRUser(bool hasConsentForDataUsage, bool hasConsentForAdsPersonalization)
|
||||
{
|
||||
return new AppsFlyerConsent(true, hasConsentForDataUsage, hasConsentForAdsPersonalization);
|
||||
}
|
||||
|
||||
[Obsolete("Use new AppsFlyerConsent(...) instead.")]
|
||||
public static AppsFlyerConsent ForNonGDPRUser()
|
||||
{
|
||||
return new AppsFlyerConsent(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/AppsFlyer/AppsFlyerConsent.cs.meta
Normal file
11
Assets/AppsFlyer/AppsFlyerConsent.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a97c986fe4ee0461badf7042e08db3f3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
218
Assets/AppsFlyer/AppsFlyerEventArgs.cs
Normal file
218
Assets/AppsFlyer/AppsFlyerEventArgs.cs
Normal file
@@ -0,0 +1,218 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AppsFlyerSDK
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Event args for AppsFlyer requests.
|
||||
/// Used for sessions and in-app events.
|
||||
/// Used to handle post request logic.
|
||||
///
|
||||
/// Examples:
|
||||
/// statusCode / errorDescription
|
||||
///
|
||||
/// 200 - null
|
||||
///
|
||||
/// 10 - "Event timeout. Check 'minTimeBetweenSessions' param"
|
||||
/// 11 - "Skipping event because 'isStopTracking' enabled"
|
||||
/// 40 - Network error: Error description comes from Android
|
||||
/// 41 - "No dev key"
|
||||
/// 50 - "Status code failure" + actual response code from the server
|
||||
///
|
||||
/// </summary>
|
||||
public class AppsFlyerRequestEventArgs : EventArgs
|
||||
{
|
||||
public AppsFlyerRequestEventArgs(int code, string description)
|
||||
{
|
||||
statusCode = code;
|
||||
errorDescription = description;
|
||||
}
|
||||
|
||||
public int statusCode { get; }
|
||||
public string errorDescription { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event args for OnDeepLinkReceived.
|
||||
/// Used to handle deep linking results.
|
||||
/// </summary>
|
||||
public class DeepLinkEventsArgs : EventArgs
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// DeepLink dictionary to get additional parameters
|
||||
/// </summary>
|
||||
public Dictionary<string, object> deepLink;
|
||||
|
||||
/// <summary>
|
||||
/// DeepLink status: FOUND, NOT_FOUND, ERROR
|
||||
/// </summary>
|
||||
public DeepLinkStatus status { get; }
|
||||
|
||||
/// <summary>
|
||||
/// DeepLink error: TIMEOUT, NETWORK, HTTP_STATUS_CODE, UNEXPECTED
|
||||
/// </summary>
|
||||
public DeepLinkError error { get; }
|
||||
|
||||
public string getMatchType()
|
||||
{
|
||||
return getDeepLinkParameter("match_type");
|
||||
}
|
||||
|
||||
public string getDeepLinkValue()
|
||||
{
|
||||
return getDeepLinkParameter("deep_link_value");
|
||||
}
|
||||
|
||||
public string getClickHttpReferrer()
|
||||
{
|
||||
return getDeepLinkParameter("click_http_referrer");
|
||||
}
|
||||
|
||||
public string getMediaSource()
|
||||
{
|
||||
return getDeepLinkParameter("media_source");
|
||||
}
|
||||
|
||||
public string getCampaign()
|
||||
{
|
||||
return getDeepLinkParameter("campaign");
|
||||
}
|
||||
|
||||
public string getCampaignId()
|
||||
{
|
||||
return getDeepLinkParameter("campaign_id");
|
||||
}
|
||||
|
||||
public string getAfSub1()
|
||||
{
|
||||
return getDeepLinkParameter("af_sub1");
|
||||
}
|
||||
|
||||
public string getAfSub2()
|
||||
{
|
||||
return getDeepLinkParameter("af_sub2");
|
||||
}
|
||||
|
||||
public string getAfSub3()
|
||||
{
|
||||
return getDeepLinkParameter("af_sub3");
|
||||
}
|
||||
|
||||
public string getAfSub4()
|
||||
{
|
||||
return getDeepLinkParameter("af_sub4");
|
||||
}
|
||||
|
||||
public string getAfSub5()
|
||||
{
|
||||
return getDeepLinkParameter("af_sub5");
|
||||
}
|
||||
|
||||
public bool isDeferred()
|
||||
{
|
||||
if (deepLink != null && deepLink.ContainsKey("is_deferred"))
|
||||
{
|
||||
try
|
||||
{
|
||||
return (bool)deepLink["is_deferred"];
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
AppsFlyer.AFLog("DeepLinkEventsArgs.isDeferred", String.Format("{0} Exception caught.", e));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Dictionary<string, object> getDeepLinkDictionary()
|
||||
{
|
||||
return deepLink;
|
||||
}
|
||||
|
||||
public DeepLinkEventsArgs(string str)
|
||||
{
|
||||
try
|
||||
{
|
||||
Dictionary<string, object> dictionary = AppsFlyer.CallbackStringToDictionary(str);
|
||||
|
||||
string status = "";
|
||||
string error = "";
|
||||
|
||||
|
||||
if (dictionary.ContainsKey("status") && dictionary["status"] != null)
|
||||
{
|
||||
status = dictionary["status"].ToString();
|
||||
}
|
||||
|
||||
if (dictionary.ContainsKey("error") && dictionary["error"] != null)
|
||||
{
|
||||
error = dictionary["error"].ToString();
|
||||
}
|
||||
|
||||
if (dictionary.ContainsKey("deepLink") && dictionary["deepLink"] != null)
|
||||
{
|
||||
this.deepLink = AppsFlyer.CallbackStringToDictionary(dictionary["deepLink"].ToString());
|
||||
}
|
||||
if (dictionary.ContainsKey("is_deferred"))
|
||||
{
|
||||
this.deepLink["is_deferred"] = dictionary["is_deferred"];
|
||||
}
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case "FOUND":
|
||||
this.status = DeepLinkStatus.FOUND;
|
||||
break;
|
||||
case "NOT_FOUND":
|
||||
this.status = DeepLinkStatus.NOT_FOUND;
|
||||
break;
|
||||
default:
|
||||
this.status = DeepLinkStatus.ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (error)
|
||||
{
|
||||
case "TIMEOUT":
|
||||
this.error = DeepLinkError.TIMEOUT;
|
||||
break;
|
||||
case "NETWORK":
|
||||
this.error = DeepLinkError.NETWORK;
|
||||
break;
|
||||
case "HTTP_STATUS_CODE":
|
||||
this.error = DeepLinkError.HTTP_STATUS_CODE;
|
||||
break;
|
||||
default:
|
||||
this.error = DeepLinkError.UNEXPECTED;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
AppsFlyer.AFLog("DeepLinkEventsArgs.parseDeepLink", String.Format("{0} Exception caught.", e));
|
||||
}
|
||||
}
|
||||
|
||||
private string getDeepLinkParameter(string name)
|
||||
{
|
||||
if (deepLink != null && deepLink.ContainsKey(name) && deepLink[name] != null)
|
||||
{
|
||||
return deepLink[name].ToString();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public enum DeepLinkStatus {
|
||||
FOUND, NOT_FOUND, ERROR
|
||||
}
|
||||
|
||||
public enum DeepLinkError {
|
||||
TIMEOUT, NETWORK, HTTP_STATUS_CODE, UNEXPECTED
|
||||
}
|
||||
}
|
||||
11
Assets/AppsFlyer/AppsFlyerEventArgs.cs.meta
Normal file
11
Assets/AppsFlyer/AppsFlyerEventArgs.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a0fc241ad5a9b43a7b461a6147dbc74c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
52
Assets/AppsFlyer/AppsFlyerObject.prefab
Normal file
52
Assets/AppsFlyer/AppsFlyerObject.prefab
Normal file
@@ -0,0 +1,52 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &7315102894599890749
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 6207133488976360133}
|
||||
- component: {fileID: 4405976200006927252}
|
||||
m_Layer: 0
|
||||
m_Name: AppsFlyerObject
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &6207133488976360133
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7315102894599890749}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &4405976200006927252
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7315102894599890749}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 2a2ec6ba1ee8b48749524f015ed572a6, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
devKey:
|
||||
appID: 6775403944
|
||||
UWPAppID:
|
||||
macOSAppID:
|
||||
isDebug: 0
|
||||
getConversionData: 1
|
||||
7
Assets/AppsFlyer/AppsFlyerObject.prefab.meta
Normal file
7
Assets/AppsFlyer/AppsFlyerObject.prefab.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0bfe3b149145747cc92dc53bb4df4e9b
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
70
Assets/AppsFlyer/AppsFlyerObjectScript.cs
Normal file
70
Assets/AppsFlyer/AppsFlyerObjectScript.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using AppsFlyerSDK;
|
||||
|
||||
// This class is intended to be used the the AppsFlyerObject.prefab
|
||||
|
||||
public class AppsFlyerObjectScript : MonoBehaviour , IAppsFlyerConversionData
|
||||
{
|
||||
|
||||
// These fields are set from the editor so do not modify!
|
||||
//******************************//
|
||||
public string devKey;
|
||||
public string appID;
|
||||
public string UWPAppID;
|
||||
public string macOSAppID;
|
||||
public bool isDebug;
|
||||
public bool getConversionData;
|
||||
//******************************//
|
||||
|
||||
|
||||
void Start()
|
||||
{
|
||||
// These fields are set from the editor so do not modify!
|
||||
//******************************//
|
||||
AppsFlyer.setIsDebug(isDebug);
|
||||
#if UNITY_WSA_10_0 && !UNITY_EDITOR
|
||||
AppsFlyer.initSDK(devKey, UWPAppID, getConversionData ? this : null);
|
||||
#elif UNITY_STANDALONE_OSX && !UNITY_EDITOR
|
||||
AppsFlyer.initSDK(devKey, macOSAppID, getConversionData ? this : null);
|
||||
#else
|
||||
AppsFlyer.initSDK(devKey, appID, getConversionData ? this : null);
|
||||
#endif
|
||||
//******************************/
|
||||
|
||||
AppsFlyer.startSDK();
|
||||
}
|
||||
|
||||
|
||||
void Update()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Mark AppsFlyer CallBacks
|
||||
public void onConversionDataSuccess(string conversionData)
|
||||
{
|
||||
AppsFlyer.AFLog("didReceiveConversionData", conversionData);
|
||||
Dictionary<string, object> conversionDataDictionary = AppsFlyer.CallbackStringToDictionary(conversionData);
|
||||
// add deferred deeplink logic here
|
||||
}
|
||||
|
||||
public void onConversionDataFail(string error)
|
||||
{
|
||||
AppsFlyer.AFLog("didReceiveConversionDataWithError", error);
|
||||
}
|
||||
|
||||
public void onAppOpenAttribution(string attributionData)
|
||||
{
|
||||
AppsFlyer.AFLog("onAppOpenAttribution", attributionData);
|
||||
Dictionary<string, object> attributionDataDictionary = AppsFlyer.CallbackStringToDictionary(attributionData);
|
||||
// add direct deeplink logic here
|
||||
}
|
||||
|
||||
public void onAppOpenAttributionFailure(string error)
|
||||
{
|
||||
AppsFlyer.AFLog("onAppOpenAttributionFailure", error);
|
||||
}
|
||||
|
||||
}
|
||||
11
Assets/AppsFlyer/AppsFlyerObjectScript.cs.meta
Normal file
11
Assets/AppsFlyer/AppsFlyerObjectScript.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2a2ec6ba1ee8b48749524f015ed572a6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
426
Assets/AppsFlyer/AppsFlyerPurchaseConnector.cs
Normal file
426
Assets/AppsFlyer/AppsFlyerPurchaseConnector.cs
Normal file
@@ -0,0 +1,426 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine;
|
||||
using System;
|
||||
|
||||
namespace AppsFlyerSDK
|
||||
{
|
||||
|
||||
public interface IAppsFlyerPurchaseRevenueDataSource
|
||||
{
|
||||
Dictionary<string, object> PurchaseRevenueAdditionalParametersForProducts(HashSet<object> products, HashSet<object> transactions);
|
||||
}
|
||||
|
||||
public interface IAppsFlyerPurchaseRevenueDataSourceStoreKit2
|
||||
{
|
||||
Dictionary<string, object> PurchaseRevenueAdditionalParametersStoreKit2ForProducts(HashSet<object> products, HashSet<object> transactions);
|
||||
}
|
||||
|
||||
public class AppsFlyerPurchaseRevenueBridge : MonoBehaviour
|
||||
{
|
||||
#if UNITY_IOS && !UNITY_EDITOR
|
||||
[DllImport("__Internal")]
|
||||
private static extern void RegisterUnityPurchaseRevenueParamsCallback(Func<string, string, string> callback);
|
||||
|
||||
[DllImport("__Internal")]
|
||||
private static extern void RegisterUnityPurchaseRevenueParamsCallbackSK2(Func<string, string, string> callback);
|
||||
#endif
|
||||
|
||||
private static IAppsFlyerPurchaseRevenueDataSource _dataSource;
|
||||
private static IAppsFlyerPurchaseRevenueDataSourceStoreKit2 _dataSourceSK2;
|
||||
|
||||
public static void RegisterDataSource(IAppsFlyerPurchaseRevenueDataSource dataSource)
|
||||
{
|
||||
_dataSource = dataSource;
|
||||
#if UNITY_IOS && !UNITY_EDITOR
|
||||
RegisterUnityPurchaseRevenueParamsCallback(GetAdditionalParameters);
|
||||
#elif UNITY_ANDROID && !UNITY_EDITOR
|
||||
using (AndroidJavaClass jc = new AndroidJavaClass("com.appsflyer.unity.PurchaseRevenueBridge"))
|
||||
{
|
||||
jc.CallStatic("setUnityBridge", new UnityPurchaseRevenueBridgeProxy());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void RegisterDataSourceStoreKit2(IAppsFlyerPurchaseRevenueDataSourceStoreKit2 dataSource)
|
||||
{
|
||||
#if UNITY_IOS && !UNITY_EDITOR
|
||||
_dataSourceSK2 = dataSource;
|
||||
RegisterUnityPurchaseRevenueParamsCallbackSK2(GetAdditionalParametersSK2);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static Dictionary<string, object> GetAdditionalParametersForAndroid(HashSet<object> products, HashSet<object> transactions)
|
||||
{
|
||||
return _dataSource?.PurchaseRevenueAdditionalParametersForProducts(products, transactions)
|
||||
?? new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
#if UNITY_IOS && !UNITY_EDITOR
|
||||
[AOT.MonoPInvokeCallback(typeof(Func<string, string, string>))]
|
||||
public static string GetAdditionalParameters(string productsJson, string transactionsJson)
|
||||
{
|
||||
try
|
||||
{
|
||||
HashSet<object> products = new HashSet<object>();
|
||||
HashSet<object> transactions = new HashSet<object>();
|
||||
|
||||
if (!string.IsNullOrEmpty(productsJson))
|
||||
{
|
||||
var dict = AFMiniJSON.Json.Deserialize(productsJson) as Dictionary<string, object>;
|
||||
if (dict != null)
|
||||
{
|
||||
if (dict.TryGetValue("products", out var productsObj) && productsObj is List<object> productList)
|
||||
products = new HashSet<object>(productList);
|
||||
|
||||
if (dict.TryGetValue("transactions", out var transactionsObj) && transactionsObj is List<object> transactionList)
|
||||
transactions = new HashSet<object>(transactionList);
|
||||
}
|
||||
}
|
||||
|
||||
var parameters = _dataSource?.PurchaseRevenueAdditionalParametersForProducts(products, transactions)
|
||||
?? new Dictionary<string, object>();
|
||||
return AFMiniJSON.Json.Serialize(parameters);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"[AppsFlyer] Exception in GetAdditionalParameters: {e}");
|
||||
return "{}";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if UNITY_IOS && !UNITY_EDITOR
|
||||
[AOT.MonoPInvokeCallback(typeof(Func<string, string, string>))]
|
||||
public static string GetAdditionalParametersSK2(string productsJson, string transactionsJson)
|
||||
{
|
||||
try
|
||||
{
|
||||
HashSet<object> products = new HashSet<object>();
|
||||
HashSet<object> transactions = new HashSet<object>();
|
||||
|
||||
if (!string.IsNullOrEmpty(productsJson))
|
||||
{
|
||||
var dict = AFMiniJSON.Json.Deserialize(productsJson) as Dictionary<string, object>;
|
||||
if (dict != null && dict.TryGetValue("products", out var productsObj) && productsObj is List<object> productList)
|
||||
products = new HashSet<object>(productList);
|
||||
}
|
||||
if (!string.IsNullOrEmpty(transactionsJson))
|
||||
{
|
||||
var dict = AFMiniJSON.Json.Deserialize(transactionsJson) as Dictionary<string, object>;
|
||||
if (dict != null && dict.TryGetValue("transactions", out var transactionsObj) && transactionsObj is List<object> transactionList)
|
||||
transactions = new HashSet<object>(transactionList);
|
||||
}
|
||||
|
||||
var parameters = _dataSourceSK2?.PurchaseRevenueAdditionalParametersStoreKit2ForProducts(products, transactions)
|
||||
?? new Dictionary<string, object>();
|
||||
return AFMiniJSON.Json.Serialize(parameters);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"[AppsFlyer] Exception in GetAdditionalParametersSK2: {e}");
|
||||
return "{}";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public class UnityPurchaseRevenueBridgeProxy : AndroidJavaProxy
|
||||
{
|
||||
public UnityPurchaseRevenueBridgeProxy() : base("com.appsflyer.unity.PurchaseRevenueBridge$UnityPurchaseRevenueBridge") { }
|
||||
|
||||
public string getAdditionalParameters(string productsJson, string transactionsJson)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Create empty sets if JSON is null or empty
|
||||
HashSet<object> products = new HashSet<object>();
|
||||
HashSet<object> transactions = new HashSet<object>();
|
||||
|
||||
// Only try to parse if we have valid JSON
|
||||
if (!string.IsNullOrEmpty(productsJson))
|
||||
{
|
||||
try
|
||||
{
|
||||
// First try to parse as a simple array
|
||||
var parsedProducts = AFMiniJSON.Json.Deserialize(productsJson);
|
||||
if (parsedProducts is List<object> productList)
|
||||
{
|
||||
products = new HashSet<object>(productList);
|
||||
}
|
||||
else if (parsedProducts is Dictionary<string, object> dict)
|
||||
{
|
||||
if (dict.ContainsKey("events") && dict["events"] is List<object> eventsList)
|
||||
{
|
||||
products = new HashSet<object>(eventsList);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If it's a dictionary but doesn't have events, add the whole dict
|
||||
products.Add(dict);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"Error parsing products JSON: {e.Message}\nJSON: {productsJson}");
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(transactionsJson))
|
||||
{
|
||||
try
|
||||
{
|
||||
// First try to parse as a simple array
|
||||
var parsedTransactions = AFMiniJSON.Json.Deserialize(transactionsJson);
|
||||
if (parsedTransactions is List<object> transactionList)
|
||||
{
|
||||
transactions = new HashSet<object>(transactionList);
|
||||
}
|
||||
else if (parsedTransactions is Dictionary<string, object> dict)
|
||||
{
|
||||
if (dict.ContainsKey("events") && dict["events"] is List<object> eventsList)
|
||||
{
|
||||
transactions = new HashSet<object>(eventsList);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If it's a dictionary but doesn't have events, add the whole dict
|
||||
transactions.Add(dict);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"Error parsing transactions JSON: {e.Message}\nJSON: {transactionsJson}");
|
||||
}
|
||||
}
|
||||
|
||||
var parameters = AppsFlyerPurchaseRevenueBridge.GetAdditionalParametersForAndroid(products, transactions);
|
||||
return AFMiniJSON.Json.Serialize(parameters);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"Error in getAdditionalParameters: {e.Message}\nProducts JSON: {productsJson}\nTransactions JSON: {transactionsJson}");
|
||||
return "{}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class AppsFlyerPurchaseConnector : MonoBehaviour {
|
||||
|
||||
private static AppsFlyerPurchaseConnector instance;
|
||||
private Dictionary<string, object> pendingParameters;
|
||||
private Action<Dictionary<string, object>> pendingCallback;
|
||||
|
||||
public static AppsFlyerPurchaseConnector Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
GameObject go = new GameObject("AppsFlyerPurchaseConnector");
|
||||
instance = go.AddComponent<AppsFlyerPurchaseConnector>();
|
||||
DontDestroyOnLoad(go);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = this;
|
||||
DontDestroyOnLoad(gameObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
private static AndroidJavaClass appsFlyerAndroidConnector = new AndroidJavaClass("com.appsflyer.unity.AppsFlyerAndroidWrapper");
|
||||
#endif
|
||||
|
||||
public static void init(MonoBehaviour unityObject, Store s) {
|
||||
#if UNITY_IOS && !UNITY_EDITOR
|
||||
_initPurchaseConnector(unityObject.name);
|
||||
#elif UNITY_ANDROID && !UNITY_EDITOR
|
||||
int store = mapStoreToInt(s);
|
||||
appsFlyerAndroidConnector.CallStatic("initPurchaseConnector", unityObject ? unityObject.name : null, store);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void build() {
|
||||
#if UNITY_IOS && !UNITY_EDITOR
|
||||
//not for iOS
|
||||
#elif UNITY_ANDROID && !UNITY_EDITOR
|
||||
appsFlyerAndroidConnector.CallStatic("build");
|
||||
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void startObservingTransactions() {
|
||||
#if UNITY_IOS && !UNITY_EDITOR
|
||||
_startObservingTransactions();
|
||||
#elif UNITY_ANDROID && !UNITY_EDITOR
|
||||
appsFlyerAndroidConnector.CallStatic("startObservingTransactions");
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void stopObservingTransactions() {
|
||||
#if UNITY_IOS && !UNITY_EDITOR
|
||||
_stopObservingTransactions();
|
||||
#elif UNITY_ANDROID && !UNITY_EDITOR
|
||||
appsFlyerAndroidConnector.CallStatic("stopObservingTransactions");
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void setIsSandbox(bool isSandbox) {
|
||||
#if UNITY_IOS && !UNITY_EDITOR
|
||||
_setIsSandbox(isSandbox);
|
||||
#elif UNITY_ANDROID && !UNITY_EDITOR
|
||||
appsFlyerAndroidConnector.CallStatic("setIsSandbox", isSandbox);
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void setPurchaseRevenueValidationListeners(bool enableCallbacks) {
|
||||
#if UNITY_IOS && !UNITY_EDITOR
|
||||
_setPurchaseRevenueDelegate();
|
||||
#elif UNITY_ANDROID && !UNITY_EDITOR
|
||||
appsFlyerAndroidConnector.CallStatic("setPurchaseRevenueValidationListeners", enableCallbacks);
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void setAutoLogPurchaseRevenue(params AppsFlyerAutoLogPurchaseRevenueOptions[] autoLogPurchaseRevenueOptions) {
|
||||
#if UNITY_IOS && !UNITY_EDITOR
|
||||
int option = 0;
|
||||
foreach (AppsFlyerAutoLogPurchaseRevenueOptions op in autoLogPurchaseRevenueOptions) {
|
||||
option = option | (int)op;
|
||||
}
|
||||
_setAutoLogPurchaseRevenue(option);
|
||||
#elif UNITY_ANDROID && !UNITY_EDITOR
|
||||
if (autoLogPurchaseRevenueOptions.Length == 0) {
|
||||
return;
|
||||
}
|
||||
foreach (AppsFlyerAutoLogPurchaseRevenueOptions op in autoLogPurchaseRevenueOptions) {
|
||||
switch(op) {
|
||||
case AppsFlyerAutoLogPurchaseRevenueOptions.AppsFlyerAutoLogPurchaseRevenueOptionsDisabled:
|
||||
break;
|
||||
case AppsFlyerAutoLogPurchaseRevenueOptions.AppsFlyerAutoLogPurchaseRevenueOptionsAutoRenewableSubscriptions:
|
||||
appsFlyerAndroidConnector.CallStatic("setAutoLogSubscriptions", true);
|
||||
break;
|
||||
case AppsFlyerAutoLogPurchaseRevenueOptions.AppsFlyerAutoLogPurchaseRevenueOptionsInAppPurchases:
|
||||
appsFlyerAndroidConnector.CallStatic("setAutoLogInApps", true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void setPurchaseRevenueDataSource(IAppsFlyerPurchaseRevenueDataSource dataSource)
|
||||
{
|
||||
#if UNITY_IOS && !UNITY_EDITOR
|
||||
|
||||
if (dataSource != null)
|
||||
{
|
||||
_setPurchaseRevenueDataSource(dataSource.GetType().Name);
|
||||
AppsFlyerPurchaseRevenueBridge.RegisterDataSource(dataSource);
|
||||
}
|
||||
#elif UNITY_ANDROID && !UNITY_EDITOR
|
||||
if (dataSource != null)
|
||||
{
|
||||
AppsFlyerPurchaseRevenueBridge.RegisterDataSource(dataSource);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
public static void setPurchaseRevenueDataSourceStoreKit2(IAppsFlyerPurchaseRevenueDataSourceStoreKit2 dataSourceSK2)
|
||||
{
|
||||
#if UNITY_IOS && !UNITY_EDITOR
|
||||
if (dataSourceSK2 != null)
|
||||
{
|
||||
AppsFlyerPurchaseRevenueBridge.RegisterDataSourceStoreKit2(dataSourceSK2);
|
||||
_setPurchaseRevenueDataSource("AppsFlyerObjectScript_StoreKit2");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
private static int mapStoreToInt(Store s) {
|
||||
switch(s) {
|
||||
case(Store.GOOGLE):
|
||||
return 0;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static void setStoreKitVersion(StoreKitVersion storeKitVersion) {
|
||||
#if UNITY_IOS && !UNITY_EDITOR
|
||||
_setStoreKitVersion((int)storeKitVersion);
|
||||
#elif UNITY_ANDROID && !UNITY_EDITOR
|
||||
// Android doesn't use StoreKit
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void logConsumableTransaction(string transactionJson) {
|
||||
#if UNITY_IOS && !UNITY_EDITOR
|
||||
_logConsumableTransaction(transactionJson);
|
||||
#elif UNITY_ANDROID && !UNITY_EDITOR
|
||||
// Android doesn't use StoreKit
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
#if UNITY_IOS && !UNITY_EDITOR
|
||||
|
||||
[DllImport("__Internal")]
|
||||
private static extern void _startObservingTransactions();
|
||||
[DllImport("__Internal")]
|
||||
private static extern void _stopObservingTransactions();
|
||||
[DllImport("__Internal")]
|
||||
private static extern void _setIsSandbox(bool isSandbox);
|
||||
[DllImport("__Internal")]
|
||||
private static extern void _setPurchaseRevenueDelegate();
|
||||
[DllImport("__Internal")]
|
||||
private static extern void _setPurchaseRevenueDataSource(string dataSourceName);
|
||||
[DllImport("__Internal")]
|
||||
private static extern void _setAutoLogPurchaseRevenue(int option);
|
||||
[DllImport("__Internal")]
|
||||
private static extern void _initPurchaseConnector(string objectName);
|
||||
[DllImport("__Internal")]
|
||||
private static extern void _setStoreKitVersion(int storeKitVersion);
|
||||
[DllImport("__Internal")]
|
||||
private static extern void _logConsumableTransaction(string transactionJson);
|
||||
|
||||
#endif
|
||||
}
|
||||
public enum Store {
|
||||
GOOGLE = 0
|
||||
}
|
||||
public enum AppsFlyerAutoLogPurchaseRevenueOptions
|
||||
{
|
||||
AppsFlyerAutoLogPurchaseRevenueOptionsDisabled = 0,
|
||||
AppsFlyerAutoLogPurchaseRevenueOptionsAutoRenewableSubscriptions = 1 << 0,
|
||||
AppsFlyerAutoLogPurchaseRevenueOptionsInAppPurchases = 1 << 1
|
||||
}
|
||||
|
||||
public enum StoreKitVersion {
|
||||
SK1 = 0,
|
||||
SK2 = 1
|
||||
}
|
||||
}
|
||||
11
Assets/AppsFlyer/AppsFlyerPurchaseConnector.cs.meta
Normal file
11
Assets/AppsFlyer/AppsFlyerPurchaseConnector.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0636ea07d370d437183f3762280c08ce
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1021
Assets/AppsFlyer/AppsFlyeriOS.cs
Normal file
1021
Assets/AppsFlyer/AppsFlyeriOS.cs
Normal file
File diff suppressed because it is too large
Load Diff
11
Assets/AppsFlyer/AppsFlyeriOS.cs.meta
Normal file
11
Assets/AppsFlyer/AppsFlyeriOS.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b34371b3cc09641ebb007ffc4e9500f0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/AppsFlyer/Editor.meta
Normal file
8
Assets/AppsFlyer/Editor.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9f84c02aa78da4ac9b444d98d97f7cc4
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
17
Assets/AppsFlyer/Editor/AppsFlyer.Editor.asmdef
Normal file
17
Assets/AppsFlyer/Editor/AppsFlyer.Editor.asmdef
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "AppsFlyer.Editor",
|
||||
"references": [
|
||||
"AppsFlyer"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
7
Assets/AppsFlyer/Editor/AppsFlyer.Editor.asmdef.meta
Normal file
7
Assets/AppsFlyer/Editor/AppsFlyer.Editor.asmdef.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d008146f00dea44d38752b4289e5f65b
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
16
Assets/AppsFlyer/Editor/AppsFlyerDependencies.xml
Normal file
16
Assets/AppsFlyer/Editor/AppsFlyerDependencies.xml
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<dependencies>
|
||||
|
||||
<androidPackages>
|
||||
<androidPackage spec="com.appsflyer:af-android-sdk:6.17.6"></androidPackage>
|
||||
<androidPackage spec="com.appsflyer:unity-wrapper:6.17.91"></androidPackage>
|
||||
<androidPackage spec="com.android.installreferrer:installreferrer:2.1"></androidPackage>
|
||||
<androidPackage spec="com.appsflyer:purchase-connector:2.2.0"></androidPackage>
|
||||
</androidPackages>
|
||||
|
||||
<iosPods>
|
||||
<iosPod name="AppsFlyerFramework/Strict" version="6.17.9" minTargetSdk="12.0"></iosPod>
|
||||
<iosPod name="PurchaseConnector/Strict" version="6.17.9" minTargetSdk="12.0"></iosPod>
|
||||
</iosPods>
|
||||
|
||||
</dependencies>
|
||||
7
Assets/AppsFlyer/Editor/AppsFlyerDependencies.xml.meta
Normal file
7
Assets/AppsFlyer/Editor/AppsFlyerDependencies.xml.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a03558dbbfeac45db9afe9e9c2df5a85
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
104
Assets/AppsFlyer/Editor/AppsFlyerObjectEditor.cs
Normal file
104
Assets/AppsFlyer/Editor/AppsFlyerObjectEditor.cs
Normal file
@@ -0,0 +1,104 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
[CustomEditor(typeof(AppsFlyerObjectScript))]
|
||||
[CanEditMultipleObjects]
|
||||
public class AppsFlyerObjectEditor : Editor
|
||||
{
|
||||
|
||||
SerializedProperty devKey;
|
||||
SerializedProperty appID;
|
||||
SerializedProperty UWPAppID;
|
||||
SerializedProperty macOSAppID;
|
||||
SerializedProperty isDebug;
|
||||
SerializedProperty getConversionData;
|
||||
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
devKey = serializedObject.FindProperty("devKey");
|
||||
appID = serializedObject.FindProperty("appID");
|
||||
UWPAppID = serializedObject.FindProperty("UWPAppID");
|
||||
macOSAppID = serializedObject.FindProperty("macOSAppID");
|
||||
isDebug = serializedObject.FindProperty("isDebug");
|
||||
getConversionData = serializedObject.FindProperty("getConversionData");
|
||||
}
|
||||
|
||||
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
serializedObject.Update();
|
||||
|
||||
DrawLogo();
|
||||
|
||||
EditorGUILayout.Separator();
|
||||
EditorGUILayout.HelpBox("Set your devKey and appID to init the AppsFlyer SDK and start tracking. You must modify these fields and provide:\ndevKey - Your application devKey provided by AppsFlyer.\nappId - For iOS only. Your iTunes Application ID.\nUWP app id - For UWP only. Your application app id \nMac OS app id - For MacOS app only.", MessageType.Info);
|
||||
|
||||
EditorGUILayout.PropertyField(devKey);
|
||||
EditorGUILayout.PropertyField(appID);
|
||||
EditorGUILayout.PropertyField(UWPAppID);
|
||||
EditorGUILayout.PropertyField(macOSAppID);
|
||||
EditorGUILayout.Separator();
|
||||
EditorGUILayout.HelpBox("Enable get conversion data to allow your app to recive deeplinking callbacks", MessageType.None);
|
||||
EditorGUILayout.PropertyField(getConversionData);
|
||||
EditorGUILayout.Separator();
|
||||
EditorGUILayout.HelpBox("Debugging should be restricted to development phase only.\n Do not distribute the app to app stores with debugging enabled", MessageType.Warning);
|
||||
EditorGUILayout.PropertyField(isDebug);
|
||||
EditorGUILayout.Separator();
|
||||
|
||||
EditorGUILayout.HelpBox("For more information on setting up AppsFlyer check out our relevant docs.", MessageType.None);
|
||||
|
||||
|
||||
if (GUILayout.Button("AppsFlyer Unity Docs", new GUILayoutOption[] { GUILayout.Width(200) }))
|
||||
{
|
||||
Application.OpenURL("https://support.appsflyer.com/hc/en-us/articles/213766183-Unity-SDK-integration-for-developers");
|
||||
}
|
||||
|
||||
if (GUILayout.Button("AppsFlyer Android Docs", new GUILayoutOption[] { GUILayout.Width(200) }))
|
||||
{
|
||||
Application.OpenURL("https://support.appsflyer.com/hc/en-us/articles/207032126-Android-SDK-integration-for-developers");
|
||||
}
|
||||
|
||||
if (GUILayout.Button("AppsFlyer iOS Docs", new GUILayoutOption[] { GUILayout.Width(200) }))
|
||||
{
|
||||
Application.OpenURL("https://support.appsflyer.com/hc/en-us/articles/207032066-AppsFlyer-SDK-Integration-iOS");
|
||||
}
|
||||
|
||||
if (GUILayout.Button("AppsFlyer Deeplinking Docs", new GUILayoutOption[] { GUILayout.Width(200) }))
|
||||
{
|
||||
Application.OpenURL("https://support.appsflyer.com/hc/en-us/articles/208874366-OneLink-deep-linking-guide#Setups");
|
||||
}
|
||||
|
||||
if (GUILayout.Button("AppsFlyer Windows Docs", new GUILayoutOption[] { GUILayout.Width(200) }))
|
||||
{
|
||||
Application.OpenURL("https://support.appsflyer.com/hc/en-us/articles/207032026-Windows-and-Xbox-SDK-integration-for-developers");
|
||||
}
|
||||
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
private void DrawLogo()
|
||||
{
|
||||
var guids = AssetDatabase.FindAssets("appsflyer_logo");
|
||||
if (guids.Length == 0) return;
|
||||
|
||||
Texture logo = (Texture)AssetDatabase.LoadAssetAtPath(
|
||||
AssetDatabase.GUIDToAssetPath(guids[0]),
|
||||
typeof(Texture));
|
||||
|
||||
if (logo == null) return;
|
||||
|
||||
float maxWidth = Mathf.Min(200, EditorGUIUtility.currentViewWidth - 40);
|
||||
float aspect = (float)logo.height / logo.width;
|
||||
float height = maxWidth * aspect;
|
||||
|
||||
Rect rect = GUILayoutUtility.GetRect(maxWidth, height, GUILayout.ExpandWidth(false));
|
||||
rect.x = (EditorGUIUtility.currentViewWidth - maxWidth) * 0.5f;
|
||||
rect.width = maxWidth;
|
||||
GUI.DrawTexture(rect, logo, ScaleMode.ScaleToFit);
|
||||
}
|
||||
|
||||
}
|
||||
11
Assets/AppsFlyer/Editor/AppsFlyerObjectEditor.cs.meta
Normal file
11
Assets/AppsFlyer/Editor/AppsFlyerObjectEditor.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d248a134cf494486fb1d6a2e95a05d87
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/AppsFlyer/Editor/appsflyer_logo.png
Normal file
BIN
Assets/AppsFlyer/Editor/appsflyer_logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.0 KiB |
92
Assets/AppsFlyer/Editor/appsflyer_logo.png.meta
Normal file
92
Assets/AppsFlyer/Editor/appsflyer_logo.png.meta
Normal file
@@ -0,0 +1,92 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bc7fa5a6b64b944a4b2900fd877acb8b
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 11
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: -1
|
||||
aniso: -1
|
||||
mipBias: -100
|
||||
wrapU: -1
|
||||
wrapV: -1
|
||||
wrapW: -1
|
||||
nPOTScale: 1
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 0
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 0
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
applyGammaDecoding: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
31
Assets/AppsFlyer/IAppsFlyerAndroidBridge.cs
Normal file
31
Assets/AppsFlyer/IAppsFlyerAndroidBridge.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AppsFlyerSDK
|
||||
{
|
||||
|
||||
public interface IAppsFlyerAndroidBridge : IAppsFlyerNativeBridge
|
||||
{
|
||||
void updateServerUninstallToken(string token);
|
||||
void setImeiData(string imei);
|
||||
void setAndroidIdData(string androidId);
|
||||
void waitForCustomerUserId(bool wait);
|
||||
void setCustomerIdAndStartSDK(string id);
|
||||
string getOutOfStore();
|
||||
void setOutOfStore(string sourceName);
|
||||
void setCollectAndroidID(bool isCollect);
|
||||
void setCollectIMEI(bool isCollect);
|
||||
void setIsUpdate(bool isUpdate);
|
||||
void setPreinstallAttribution(string mediaSource, string campaign, string siteId);
|
||||
bool isPreInstalledApp();
|
||||
string getAttributionId();
|
||||
void handlePushNotifications();
|
||||
void validateAndSendInAppPurchase(string publicKey, string signature, string purchaseData, string price, string currency, Dictionary<string, string> additionalParameters, MonoBehaviour gameObject);
|
||||
void validateAndSendInAppPurchase(AFPurchaseDetailsAndroid details, Dictionary<string, string> purchaseAdditionalDetails, MonoBehaviour gameObject);
|
||||
void setCollectOaid(bool isCollect);
|
||||
void setDisableAdvertisingIdentifiers(bool disable);
|
||||
void setDisableNetworkData(bool disable);
|
||||
|
||||
}
|
||||
}
|
||||
11
Assets/AppsFlyer/IAppsFlyerAndroidBridge.cs.meta
Normal file
11
Assets/AppsFlyer/IAppsFlyerAndroidBridge.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cdf9d1bc41a8244b3bc2d249fb6cd7aa
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
31
Assets/AppsFlyer/IAppsFlyerConversionData.cs
Normal file
31
Assets/AppsFlyer/IAppsFlyerConversionData.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
namespace AppsFlyerSDK
|
||||
{
|
||||
public interface IAppsFlyerConversionData
|
||||
{
|
||||
/// <summary>
|
||||
/// `conversionData` contains information about install. Organic/non-organic, etc.
|
||||
/// <see>https://support.appsflyer.com/hc/en-us/articles/360000726098-Conversion-Data-Scenarios#Introduction</see>
|
||||
/// </summary>
|
||||
/// <param name="conversionData">JSON string of the returned conversion data.</param>
|
||||
void onConversionDataSuccess(string conversionData);
|
||||
|
||||
/// <summary>
|
||||
/// Any errors that occurred during the conversion request.
|
||||
/// </summary>
|
||||
/// <param name="error">A string describing the error.</param>
|
||||
void onConversionDataFail(string error);
|
||||
|
||||
/// <summary>
|
||||
/// `attributionData` contains information about OneLink, deeplink.
|
||||
/// <see>https://support.appsflyer.com/hc/en-us/articles/208874366-OneLink-Deep-Linking-Guide#Intro</see>
|
||||
/// </summary>
|
||||
/// <param name="attributionData">JSON string of the returned deeplink data.</param>
|
||||
void onAppOpenAttribution(string attributionData);
|
||||
|
||||
/// <summary>
|
||||
/// Any errors that occurred during the attribution request.
|
||||
/// </summary>
|
||||
/// <param name="error">A string describing the error.</param>
|
||||
void onAppOpenAttributionFailure(string error);
|
||||
}
|
||||
}
|
||||
11
Assets/AppsFlyer/IAppsFlyerConversionData.cs.meta
Normal file
11
Assets/AppsFlyer/IAppsFlyerConversionData.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d2f1d4dadb7cb44628f25f1ffd8fc104
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
26
Assets/AppsFlyer/IAppsFlyerIOSBridge.cs
Normal file
26
Assets/AppsFlyer/IAppsFlyerIOSBridge.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace AppsFlyerSDK
|
||||
{
|
||||
|
||||
public interface IAppsFlyerIOSBridge : IAppsFlyerNativeBridge
|
||||
{
|
||||
void setDisableCollectAppleAdSupport(bool disable);
|
||||
void setShouldCollectDeviceName(bool shouldCollectDeviceName);
|
||||
void setDisableCollectIAd(bool disableCollectIAd);
|
||||
void setUseReceiptValidationSandbox(bool useReceiptValidationSandbox);
|
||||
void setUseUninstallSandbox(bool useUninstallSandbox);
|
||||
void validateAndSendInAppPurchase(string productIdentifier, string price, string currency, string transactionId, Dictionary<string, string> additionalParameters, MonoBehaviour gameObject);
|
||||
void validateAndSendInAppPurchase(AFSDKPurchaseDetailsIOS details, Dictionary<string, string> purchaseAdditionalDetails, MonoBehaviour gameObject);
|
||||
void registerUninstall(byte[] deviceToken);
|
||||
void handleOpenUrl(string url, string sourceApplication, string annotation);
|
||||
void waitForATTUserAuthorizationWithTimeoutInterval(int timeoutInterval);
|
||||
void setCurrentDeviceLanguage(string language);
|
||||
void disableSKAdNetwork(bool isDisabled);
|
||||
void disableIDFVCollection(bool isDisabled);
|
||||
|
||||
}
|
||||
}
|
||||
11
Assets/AppsFlyer/IAppsFlyerIOSBridge.cs.meta
Normal file
11
Assets/AppsFlyer/IAppsFlyerIOSBridge.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6847fb337898040288c165e3667101a3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
76
Assets/AppsFlyer/IAppsFlyerNativeBridge.cs
Normal file
76
Assets/AppsFlyer/IAppsFlyerNativeBridge.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AppsFlyerSDK
|
||||
{
|
||||
|
||||
public interface IAppsFlyerNativeBridge
|
||||
{
|
||||
bool isInit { get; set; }
|
||||
|
||||
void startSDK(bool onRequestResponse, string CallBackObjectName);
|
||||
|
||||
void sendEvent(string eventName, Dictionary<string, string> eventValues, bool onInAppResponse, string CallBackObjectName);
|
||||
|
||||
void stopSDK(bool isSDKStopped);
|
||||
|
||||
bool isSDKStopped();
|
||||
|
||||
string getSdkVersion();
|
||||
|
||||
void setCustomerUserId(string id);
|
||||
|
||||
void setAppInviteOneLinkID(string oneLinkId);
|
||||
|
||||
void setAdditionalData(Dictionary<string, string> customData);
|
||||
|
||||
void setDeepLinkTimeout(long deepLinkTimeout);
|
||||
|
||||
void setResolveDeepLinkURLs(params string[] urls);
|
||||
|
||||
void setOneLinkCustomDomain(params string[] domains);
|
||||
|
||||
void setCurrencyCode(string currencyCode);
|
||||
|
||||
void recordLocation(double latitude, double longitude);
|
||||
|
||||
void anonymizeUser(bool shouldAnonymizeUser);
|
||||
|
||||
string getAppsFlyerId();
|
||||
|
||||
void enableTCFDataCollection(bool shouldCollectTcfData);
|
||||
|
||||
void setConsentData(AppsFlyerConsent appsFlyerConsent);
|
||||
|
||||
void logAdRevenue(AFAdRevenueData adRevenueData, Dictionary<string, string> additionalParameters);
|
||||
|
||||
void setMinTimeBetweenSessions(int seconds);
|
||||
|
||||
void setHost(string hostPrefixName, string hostName);
|
||||
|
||||
void setPhoneNumber(string phoneNumber);
|
||||
|
||||
void setSharingFilterForAllPartners();
|
||||
|
||||
void setSharingFilter(params string[] partners);
|
||||
|
||||
void getConversionData(string objectName);
|
||||
|
||||
void attributeAndOpenStore(string appID, string campaign, Dictionary<string, string> userParams, MonoBehaviour gameObject);
|
||||
|
||||
void recordCrossPromoteImpression(string appID, string campaign, Dictionary<string, string> parameters);
|
||||
|
||||
void generateUserInviteLink(Dictionary<string, string> parameters, MonoBehaviour gameObject);
|
||||
|
||||
void addPushNotificationDeepLinkPath(params string[] paths);
|
||||
|
||||
void setUserEmails(EmailCryptType cryptType, params string[] userEmails);
|
||||
|
||||
void subscribeForDeepLink(string objectName);
|
||||
|
||||
void setIsDebug(bool shouldEnable);
|
||||
|
||||
void setPartnerData(string partnerId, Dictionary<string, string> partnerInfo);
|
||||
}
|
||||
}
|
||||
11
Assets/AppsFlyer/IAppsFlyerNativeBridge.cs.meta
Normal file
11
Assets/AppsFlyer/IAppsFlyerNativeBridge.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 409b8302434664a3785ce55d075e7f58
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/AppsFlyer/IAppsFlyerPurchaseValidation.cs
Normal file
8
Assets/AppsFlyer/IAppsFlyerPurchaseValidation.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace AppsFlyerSDK
|
||||
{
|
||||
public interface IAppsFlyerPurchaseValidation
|
||||
{
|
||||
void didReceivePurchaseRevenueValidationInfo(string validationInfo);
|
||||
void didReceivePurchaseRevenueError(string error);
|
||||
}
|
||||
}
|
||||
11
Assets/AppsFlyer/IAppsFlyerPurchaseValidation.cs.meta
Normal file
11
Assets/AppsFlyer/IAppsFlyerPurchaseValidation.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7c60f499ae0d048b1be8ffd6878a184c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
26
Assets/AppsFlyer/IAppsFlyerUserInvite.cs
Normal file
26
Assets/AppsFlyer/IAppsFlyerUserInvite.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
namespace AppsFlyerSDK
|
||||
{
|
||||
public interface IAppsFlyerUserInvite
|
||||
{
|
||||
/// <summary>
|
||||
/// The success callback for generating OneLink URLs.
|
||||
/// </summary>
|
||||
/// <param name="link">A string of the newly created url.</param>
|
||||
void onInviteLinkGenerated(string link);
|
||||
|
||||
/// <summary>
|
||||
/// The error callback for generating OneLink URLs
|
||||
/// </summary>
|
||||
/// <param name="error">A string describing the error.</param>
|
||||
void onInviteLinkGeneratedFailure(string error);
|
||||
|
||||
/// <summary>
|
||||
/// (ios only) iOS allows you to utilize the StoreKit component to open
|
||||
/// the App Store while remaining in the context of your app.
|
||||
/// More details at <see>https://support.appsflyer.com/hc/en-us/articles/115004481946-Cross-Promotion-Tracking#tracking-cross-promotion-impressions</see>
|
||||
/// </summary>
|
||||
/// <param name="link">openStore callback Contains promoted `clickURL`</param>
|
||||
void onOpenStoreLinkGenerated(string link);
|
||||
|
||||
}
|
||||
}
|
||||
11
Assets/AppsFlyer/IAppsFlyerUserInvite.cs.meta
Normal file
11
Assets/AppsFlyer/IAppsFlyerUserInvite.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5a4cdfa023cb8497b94bb39720052fef
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
19
Assets/AppsFlyer/IAppsFlyerValidateAndLog.cs
Normal file
19
Assets/AppsFlyer/IAppsFlyerValidateAndLog.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
namespace AppsFlyerSDK
|
||||
{
|
||||
public interface IAppsFlyerValidateAndLog
|
||||
{
|
||||
/// <summary>
|
||||
/// The success callback for validateAndSendInAppPurchase API.
|
||||
/// For Android : the callback will return JSON string.
|
||||
/// For iOS : the callback will return a JSON string from apples verifyReceipt API.
|
||||
/// </summary>
|
||||
/// <param name="result"></param>
|
||||
void onValidateAndLogComplete(string result);
|
||||
|
||||
/// <summary>
|
||||
/// The error callback for validateAndSendInAppPurchase API.
|
||||
/// </summary>
|
||||
/// <param name="error">A string describing the error.</param>
|
||||
void onValidateAndLogFailure(string error);
|
||||
}
|
||||
}
|
||||
11
Assets/AppsFlyer/IAppsFlyerValidateAndLog.cs.meta
Normal file
11
Assets/AppsFlyer/IAppsFlyerValidateAndLog.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1a5adb7eab3284dd39a76ec56c06457c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
19
Assets/AppsFlyer/IAppsFlyerValidateReceipt.cs
Normal file
19
Assets/AppsFlyer/IAppsFlyerValidateReceipt.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
namespace AppsFlyerSDK
|
||||
{
|
||||
public interface IAppsFlyerValidateReceipt
|
||||
{
|
||||
/// <summary>
|
||||
/// The success callback for validateAndSendInAppPurchase API.
|
||||
/// For Android : the callback will return "Validate success".
|
||||
/// For iOS : the callback will return a JSON string from apples verifyReceipt API.
|
||||
/// </summary>
|
||||
/// <param name="result"></param>
|
||||
void didFinishValidateReceipt(string result);
|
||||
|
||||
/// <summary>
|
||||
/// The error callback for validateAndSendInAppPurchase API.
|
||||
/// </summary>
|
||||
/// <param name="error">A string describing the error.</param>
|
||||
void didFinishValidateReceiptWithError(string error);
|
||||
}
|
||||
}
|
||||
11
Assets/AppsFlyer/IAppsFlyerValidateReceipt.cs.meta
Normal file
11
Assets/AppsFlyer/IAppsFlyerValidateReceipt.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6385b1d184efa400a98515735e1f17bc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/AppsFlyer/Mac.meta
Normal file
8
Assets/AppsFlyer/Mac.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 96a328019e42349aabc478b546b8605e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
33
Assets/AppsFlyer/Mac/AppsFlyerBundle.bundle.meta
Normal file
33
Assets/AppsFlyer/Mac/AppsFlyerBundle.bundle.meta
Normal file
@@ -0,0 +1,33 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 682114f7790724ab3b9410e89bbc076c
|
||||
folderAsset: yes
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
- first:
|
||||
Standalone: OSXUniversal
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,48 @@
|
||||
<?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 version="1.0">
|
||||
<dict>
|
||||
<key>BuildMachineOSBuild</key>
|
||||
<string>20G417</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>AppsFlyerBundle</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.appsflyer.support.two.AppsFlyerBundle</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>AppsFlyerBundle</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSupportedPlatforms</key>
|
||||
<array>
|
||||
<string>MacOSX</string>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>DTCompiler</key>
|
||||
<string>com.apple.compilers.llvm.clang.1_0</string>
|
||||
<key>DTPlatformBuild</key>
|
||||
<string>13A1030d</string>
|
||||
<key>DTPlatformName</key>
|
||||
<string>macosx</string>
|
||||
<key>DTPlatformVersion</key>
|
||||
<string>12.0</string>
|
||||
<key>DTSDKBuild</key>
|
||||
<string>21A344</string>
|
||||
<key>DTSDKName</key>
|
||||
<string>macosx12.0</string>
|
||||
<key>DTXcode</key>
|
||||
<string>1310</string>
|
||||
<key>DTXcodeBuild</key>
|
||||
<string>13A1030d</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>11.6</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string></string>
|
||||
</dict>
|
||||
</plist>
|
||||
BIN
Assets/AppsFlyer/Mac/AppsFlyerBundle.bundle/Contents/MacOS/AppsFlyerBundle
Executable file
BIN
Assets/AppsFlyer/Mac/AppsFlyerBundle.bundle/Contents/MacOS/AppsFlyerBundle
Executable file
Binary file not shown.
@@ -0,0 +1,115 @@
|
||||
<?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 version="1.0">
|
||||
<dict>
|
||||
<key>files</key>
|
||||
<dict/>
|
||||
<key>files2</key>
|
||||
<dict/>
|
||||
<key>rules</key>
|
||||
<dict>
|
||||
<key>^Resources/</key>
|
||||
<true/>
|
||||
<key>^Resources/.*\.lproj/</key>
|
||||
<dict>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1000</real>
|
||||
</dict>
|
||||
<key>^Resources/.*\.lproj/locversion.plist$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1100</real>
|
||||
</dict>
|
||||
<key>^Resources/Base\.lproj/</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>1010</real>
|
||||
</dict>
|
||||
<key>^version.plist$</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>rules2</key>
|
||||
<dict>
|
||||
<key>.*\.dSYM($|/)</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>11</real>
|
||||
</dict>
|
||||
<key>^(.*/)?\.DS_Store$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>2000</real>
|
||||
</dict>
|
||||
<key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>
|
||||
<dict>
|
||||
<key>nested</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>10</real>
|
||||
</dict>
|
||||
<key>^.*</key>
|
||||
<true/>
|
||||
<key>^Info\.plist$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^PkgInfo$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^Resources/</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^Resources/.*\.lproj/</key>
|
||||
<dict>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1000</real>
|
||||
</dict>
|
||||
<key>^Resources/.*\.lproj/locversion.plist$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1100</real>
|
||||
</dict>
|
||||
<key>^Resources/Base\.lproj/</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>1010</real>
|
||||
</dict>
|
||||
<key>^[^/]+$</key>
|
||||
<dict>
|
||||
<key>nested</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>10</real>
|
||||
</dict>
|
||||
<key>^embedded\.provisionprofile$</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^version\.plist$</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
8
Assets/AppsFlyer/Plugins.meta
Normal file
8
Assets/AppsFlyer/Plugins.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 66297743248ab4e47abdc371a59f1111
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/AppsFlyer/Plugins/iOS.meta
Normal file
8
Assets/AppsFlyer/Plugins/iOS.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d8325c12a80ff4323b82e2833a8fc287
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
79
Assets/AppsFlyer/Plugins/iOS/AFUnityStoreKit2Bridge.swift
Normal file
79
Assets/AppsFlyer/Plugins/iOS/AFUnityStoreKit2Bridge.swift
Normal file
@@ -0,0 +1,79 @@
|
||||
import Foundation
|
||||
import StoreKit
|
||||
|
||||
#if canImport(PurchaseConnector)
|
||||
import PurchaseConnector
|
||||
|
||||
@available(iOS 15.0, *)
|
||||
@objc
|
||||
public class AFUnityStoreKit2Bridge: NSObject {
|
||||
@objc
|
||||
public static func fetchAFSDKTransactionSK2(withTransactionId transactionId: String, completion: @escaping (AFSDKTransactionSK2?) -> Void) {
|
||||
guard let transactionIdUInt64 = UInt64(transactionId) else {
|
||||
print("Invalid transaction ID format.")
|
||||
completion(nil)
|
||||
return
|
||||
}
|
||||
Task {
|
||||
for await result in StoreKit.Transaction.all {
|
||||
if case .verified(let transaction) = result, transaction.id == transactionIdUInt64 {
|
||||
let afTransaction = AFSDKTransactionSK2(transaction: transaction)
|
||||
DispatchQueue.main.async {
|
||||
completion(afTransaction)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
DispatchQueue.main.async {
|
||||
completion(nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
public static func extractSK2ProductInfo(_ products: [AFSDKProductSK2]) -> NSArray {
|
||||
var result: [[String: Any]] = []
|
||||
|
||||
for product in products {
|
||||
if let swiftProduct = Mirror(reflecting: product).children.first(where: { $0.label == "product" })?.value {
|
||||
let productId = (swiftProduct as? NSObject)?.value(forKey: "id") as? String ?? ""
|
||||
let title = (swiftProduct as? NSObject)?.value(forKey: "displayName") as? String ?? ""
|
||||
let desc = (swiftProduct as? NSObject)?.value(forKey: "description") as? String ?? ""
|
||||
let price = (swiftProduct as? NSObject)?.value(forKey: "price") as? NSDecimalNumber ?? 0
|
||||
|
||||
result.append([
|
||||
"productIdentifier": productId,
|
||||
"localizedTitle": title,
|
||||
"localizedDescription": desc,
|
||||
"price": price
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
return result as NSArray
|
||||
}
|
||||
|
||||
@objc
|
||||
public static func extractSK2TransactionInfo(_ transactions: [AFSDKTransactionSK2]) -> NSArray {
|
||||
var result: [[String: Any]] = []
|
||||
|
||||
for txn in transactions {
|
||||
guard let mirrorChild = Mirror(reflecting: txn).children.first(where: { $0.label == "transaction" }),
|
||||
let swiftTxn = mirrorChild.value as? StoreKit.Transaction else {
|
||||
continue
|
||||
}
|
||||
|
||||
let transactionId = "\(swiftTxn.id)"
|
||||
let date = NSNumber(value: swiftTxn.purchaseDate.timeIntervalSince1970)
|
||||
|
||||
result.append([
|
||||
"transactionIdentifier": transactionId,
|
||||
"transactionState": "verified", // or skip this line
|
||||
"transactionDate": date
|
||||
])
|
||||
}
|
||||
|
||||
return result as NSArray
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5652805602a6b4273a6e527b00aea272
|
||||
24
Assets/AppsFlyer/Plugins/iOS/AFUnityUtils.h
Normal file
24
Assets/AppsFlyer/Plugins/iOS/AFUnityUtils.h
Normal file
@@ -0,0 +1,24 @@
|
||||
//
|
||||
// AFUnityUtils.h
|
||||
//
|
||||
// Created by Andrii H. and Dmitry O. on 16 Oct 2023
|
||||
//
|
||||
|
||||
#if __has_include(<AppsFlyerLib/AppsFlyerLib.h>)
|
||||
#import <AppsFlyerLib/AppsFlyerLib.h>
|
||||
#else
|
||||
#import "AppsFlyerLib.h"
|
||||
#endif
|
||||
|
||||
static NSString* stringFromChar(const char *str);
|
||||
static NSDictionary* dictionaryFromJson(const char *jsonString);
|
||||
static const char* stringFromdictionary(NSDictionary* dictionary);
|
||||
static NSArray<NSString*> *NSArrayFromCArray(int length, const char **arr);
|
||||
static char* getCString(const char* string);
|
||||
static AppsFlyerLinkGenerator* generatorFromDictionary(NSDictionary* dictionary, AppsFlyerLinkGenerator* generator);
|
||||
static EmailCryptType emailCryptTypeFromInt(int emailCryptTypeInt);
|
||||
static AppsFlyerAdRevenueMediationNetworkType mediationNetworkTypeFromInt(int mediationNetwork);
|
||||
static NSNumber *intFromNullableBool(const char *cStr);
|
||||
static NSString* stringFromDeepLinkResultStatus(AFSDKDeepLinkResultStatus deepLinkResult);
|
||||
static NSString* stringFromDeepLinkResultError(AppsFlyerDeepLinkResult *result);
|
||||
|
||||
27
Assets/AppsFlyer/Plugins/iOS/AFUnityUtils.h.meta
Normal file
27
Assets/AppsFlyer/Plugins/iOS/AFUnityUtils.h.meta
Normal file
@@ -0,0 +1,27 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4b0609ff467554f2088aee1c52bf54a2
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
219
Assets/AppsFlyer/Plugins/iOS/AFUnityUtils.mm
Normal file
219
Assets/AppsFlyer/Plugins/iOS/AFUnityUtils.mm
Normal file
@@ -0,0 +1,219 @@
|
||||
//
|
||||
// AFUnityUtils.mm
|
||||
// Unity-iPhone
|
||||
//
|
||||
// Created by Jonathan Wesfield on 24/07/2019.
|
||||
//
|
||||
|
||||
#import "AFUnityUtils.h"
|
||||
|
||||
static NSString* stringFromChar(const char *str) {
|
||||
return str ? [NSString stringWithUTF8String:str] : nil;
|
||||
}
|
||||
|
||||
static NSDictionary* dictionaryFromJson(const char *jsonString) {
|
||||
if(jsonString){
|
||||
NSData *jsonData = [[NSData alloc] initWithBytes:jsonString length:strlen(jsonString)];
|
||||
NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:nil];
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
static const char* stringFromdictionary(NSDictionary* dictionary) {
|
||||
if(dictionary){
|
||||
NSError * err;
|
||||
NSData * jsonData = [NSJSONSerialization dataWithJSONObject:dictionary options:0 error:&err];
|
||||
NSString * myString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
|
||||
return [myString UTF8String];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
static NSDictionary* dictionaryFromNSError(NSError* error) {
|
||||
if(error){
|
||||
NSMutableDictionary *errorDictionary = [NSMutableDictionary dictionary];
|
||||
errorDictionary[@"code"] = @(error.code);
|
||||
errorDictionary[@"localizedDescription"] = error.localizedDescription ?: @"";
|
||||
|
||||
// Include userInfo fields for enhanced error reporting (iOS SDK 6.17.8+)
|
||||
if (error.userInfo[@"error_code"]) {
|
||||
errorDictionary[@"error_code"] = error.userInfo[@"error_code"];
|
||||
}
|
||||
if (error.userInfo[@"error_message"]) {
|
||||
errorDictionary[@"error_message"] = error.userInfo[@"error_message"];
|
||||
}
|
||||
if (error.userInfo[@"invalid_fields"]) {
|
||||
errorDictionary[@"invalid_fields"] = error.userInfo[@"invalid_fields"];
|
||||
}
|
||||
|
||||
return errorDictionary;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
static NSArray<NSString*> *NSArrayFromCArray(int length, const char **arr) {
|
||||
NSMutableArray<NSString *> *res = [[NSMutableArray alloc] init];
|
||||
for(int i = 0; i < length; i++) {
|
||||
if (arr[i]) {
|
||||
[res addObject:[NSString stringWithUTF8String:arr[i]]];
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static char* getCString(const char* string){
|
||||
if (string == NULL){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* res = (char*)malloc(strlen(string) + 1);
|
||||
strcpy(res, string);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static AppsFlyerLinkGenerator* generatorFromDictionary(NSDictionary* dictionary, AppsFlyerLinkGenerator* generator) {
|
||||
|
||||
NSArray* generatorKeys = @[@"channel", @"customerID", @"campaign", @"referrerName", @"referrerImageUrl", @"deeplinkPath", @"baseDeeplink", @"brandDomain"];
|
||||
|
||||
NSMutableDictionary* mutableDictionary = [dictionary mutableCopy];
|
||||
|
||||
[generator setChannel:[dictionary objectForKey: @"channel"]];
|
||||
[generator setReferrerCustomerId:[dictionary objectForKey: @"customerID"]];
|
||||
[generator setCampaign:[dictionary objectForKey: @"campaign"]];
|
||||
[generator setReferrerName:[dictionary objectForKey: @"referrerName"]];
|
||||
[generator setReferrerImageURL:[dictionary objectForKey: @"referrerImageUrl"]];
|
||||
[generator setDeeplinkPath:[dictionary objectForKey: @"deeplinkPath"]];
|
||||
[generator setBaseDeeplink:[dictionary objectForKey: @"baseDeeplink"]];
|
||||
[generator setBrandDomain:[dictionary objectForKey: @"brandDomain"]];
|
||||
|
||||
|
||||
[mutableDictionary removeObjectsForKeys:generatorKeys];
|
||||
|
||||
[generator addParameters:mutableDictionary];
|
||||
|
||||
return generator;
|
||||
}
|
||||
|
||||
static EmailCryptType emailCryptTypeFromInt(int emailCryptTypeInt){
|
||||
|
||||
EmailCryptType emailCryptType;
|
||||
switch (emailCryptTypeInt){
|
||||
case 1:
|
||||
emailCryptType = EmailCryptTypeSHA256;
|
||||
break;
|
||||
default:
|
||||
emailCryptType = EmailCryptTypeNone;
|
||||
break;
|
||||
}
|
||||
|
||||
return emailCryptType;
|
||||
}
|
||||
|
||||
static NSNumber *intFromNullableBool(const char *cStr) {
|
||||
if (!cStr) return nil;
|
||||
NSString *str = [NSString stringWithUTF8String:cStr];
|
||||
|
||||
if ([str caseInsensitiveCompare:@"true"] == NSOrderedSame) {
|
||||
return @YES;
|
||||
} else if ([str caseInsensitiveCompare:@"false"] == NSOrderedSame) {
|
||||
return @NO;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
static AppsFlyerAdRevenueMediationNetworkType mediationNetworkTypeFromInt(int mediationNetworkInt){
|
||||
|
||||
AppsFlyerAdRevenueMediationNetworkType mediationNetworkType;
|
||||
switch (mediationNetworkInt){
|
||||
case 1:
|
||||
mediationNetworkType = AppsFlyerAdRevenueMediationNetworkTypeGoogleAdMob;
|
||||
break;
|
||||
case 2:
|
||||
mediationNetworkType = AppsFlyerAdRevenueMediationNetworkTypeIronSource;
|
||||
break;
|
||||
case 3:
|
||||
mediationNetworkType = AppsFlyerAdRevenueMediationNetworkTypeApplovinMax;
|
||||
break;
|
||||
case 4:
|
||||
mediationNetworkType = AppsFlyerAdRevenueMediationNetworkTypeFyber;
|
||||
break;
|
||||
case 5:
|
||||
mediationNetworkType = AppsFlyerAdRevenueMediationNetworkTypeAppodeal;
|
||||
break;
|
||||
case 6:
|
||||
mediationNetworkType = AppsFlyerAdRevenueMediationNetworkTypeAdmost;
|
||||
break;
|
||||
case 7:
|
||||
mediationNetworkType = AppsFlyerAdRevenueMediationNetworkTypeTopon;
|
||||
break;
|
||||
case 8:
|
||||
mediationNetworkType = AppsFlyerAdRevenueMediationNetworkTypeTradplus;
|
||||
break;
|
||||
case 9:
|
||||
mediationNetworkType = AppsFlyerAdRevenueMediationNetworkTypeYandex;
|
||||
break;
|
||||
case 10:
|
||||
mediationNetworkType = AppsFlyerAdRevenueMediationNetworkTypeChartBoost;
|
||||
break;
|
||||
case 11:
|
||||
mediationNetworkType = AppsFlyerAdRevenueMediationNetworkTypeUnity;
|
||||
break;
|
||||
case 12:
|
||||
mediationNetworkType = AppsFlyerAdRevenueMediationNetworkTypeToponPte;
|
||||
break;
|
||||
case 13:
|
||||
mediationNetworkType = AppsFlyerAdRevenueMediationNetworkTypeCustom;
|
||||
break;
|
||||
case 14:
|
||||
mediationNetworkType = AppsFlyerAdRevenueMediationNetworkTypeDirectMonetization;
|
||||
break;
|
||||
default:
|
||||
mediationNetworkType = AppsFlyerAdRevenueMediationNetworkTypeCustom;
|
||||
break;
|
||||
}
|
||||
|
||||
return mediationNetworkType;
|
||||
}
|
||||
|
||||
static NSString* stringFromDeepLinkResultStatus(AFSDKDeepLinkResultStatus deepLinkResult){
|
||||
NSString* result;
|
||||
switch (deepLinkResult){
|
||||
case AFSDKDeepLinkResultStatusFound:
|
||||
result = @"FOUND";
|
||||
break;
|
||||
case AFSDKDeepLinkResultStatusFailure:
|
||||
result = @"ERROR";
|
||||
break;
|
||||
case AFSDKDeepLinkResultStatusNotFound:
|
||||
result = @"NOT_FOUND";
|
||||
break;
|
||||
default:
|
||||
result = @"ERROR";
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static NSString* stringFromDeepLinkResultError(AppsFlyerDeepLinkResult *result){
|
||||
NSString* res;
|
||||
|
||||
if (result && result.error){
|
||||
if ([[result.error userInfo][NSUnderlyingErrorKey] code] == -1001) {
|
||||
res = @"TIMEOUT";
|
||||
} else if ([[result.error userInfo][NSUnderlyingErrorKey] code] == -1009) {
|
||||
res = @"NETWORK";
|
||||
}
|
||||
}
|
||||
|
||||
res = @"UNKNOWN";
|
||||
|
||||
return res;
|
||||
}
|
||||
37
Assets/AppsFlyer/Plugins/iOS/AFUnityUtils.mm.meta
Normal file
37
Assets/AppsFlyer/Plugins/iOS/AFUnityUtils.mm.meta
Normal file
@@ -0,0 +1,37 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 18a03931864e84d86bedcc99c440e060
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
- first:
|
||||
iPhone: iOS
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
tvOS: tvOS
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
164
Assets/AppsFlyer/Plugins/iOS/AppsFlyer+AppController.m
Normal file
164
Assets/AppsFlyer/Plugins/iOS/AppsFlyer+AppController.m
Normal file
@@ -0,0 +1,164 @@
|
||||
//
|
||||
// AppsFlyer+AppController.m
|
||||
// Unity-iPhone
|
||||
//
|
||||
// Created by Jonathan Wesfield on 24/07/2019.
|
||||
//
|
||||
|
||||
#import <objc/runtime.h>
|
||||
#import "UnityAppController.h"
|
||||
#import "AppsFlyeriOSWrapper.h"
|
||||
#if __has_include(<AppsFlyerLib/AppsFlyerLib.h>)
|
||||
#import <AppsFlyerLib/AppsFlyerLib.h>
|
||||
#else
|
||||
#import "AppsFlyerLib.h"
|
||||
#endif
|
||||
|
||||
|
||||
@implementation UnityAppController (AppsFlyerSwizzledAppController)
|
||||
|
||||
static BOOL didEnteredBackGround __unused;
|
||||
static IMP __original_applicationDidBecomeActive_Imp __unused;
|
||||
static IMP __original_applicationDidEnterBackground_Imp __unused;
|
||||
static IMP __original_didReceiveRemoteNotification_Imp __unused;
|
||||
static IMP __original_continueUserActivity_Imp __unused;
|
||||
static IMP __original_openUrl_Imp __unused;
|
||||
|
||||
|
||||
+ (void)load {
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
|
||||
#if !AFSDK_SHOULD_SWIZZLE
|
||||
|
||||
id swizzleFlag = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"AppsFlyerShouldSwizzle"];
|
||||
BOOL shouldSwizzle = swizzleFlag ? [swizzleFlag boolValue] : NO;
|
||||
|
||||
if(shouldSwizzle){
|
||||
|
||||
Method method1 = class_getInstanceMethod([self class], @selector(applicationDidBecomeActive:));
|
||||
__original_applicationDidBecomeActive_Imp = method_setImplementation(method1, (IMP)__swizzled_applicationDidBecomeActive);
|
||||
|
||||
Method method2 = class_getInstanceMethod([self class], @selector(applicationDidEnterBackground:));
|
||||
__original_applicationDidEnterBackground_Imp = method_setImplementation(method2, (IMP)__swizzled_applicationDidEnterBackground);
|
||||
|
||||
|
||||
Method method3 = class_getInstanceMethod([self class], @selector(didReceiveRemoteNotification:));
|
||||
__original_didReceiveRemoteNotification_Imp = method_setImplementation(method3, (IMP)__swizzled_didReceiveRemoteNotification);
|
||||
|
||||
|
||||
Method method4 = class_getInstanceMethod([self class], @selector(application:openURL:options:));
|
||||
__original_openUrl_Imp = method_setImplementation(method4, (IMP)__swizzled_openURL);
|
||||
|
||||
if (_AppsFlyerdelegate == nil) {
|
||||
_AppsFlyerdelegate = [[AppsFlyeriOSWarpper alloc] init];
|
||||
}
|
||||
|
||||
[self swizzleContinueUserActivity:[self class]];
|
||||
}
|
||||
#elif AFSDK_SHOULD_SWIZZLE
|
||||
Method method1 = class_getInstanceMethod([self class], @selector(applicationDidBecomeActive:));
|
||||
__original_applicationDidBecomeActive_Imp = method_setImplementation(method1, (IMP)__swizzled_applicationDidBecomeActive);
|
||||
|
||||
Method method2 = class_getInstanceMethod([self class], @selector(applicationDidEnterBackground:));
|
||||
__original_applicationDidEnterBackground_Imp = method_setImplementation(method2, (IMP)__swizzled_applicationDidEnterBackground);
|
||||
|
||||
|
||||
Method method3 = class_getInstanceMethod([self class], @selector(didReceiveRemoteNotification:));
|
||||
__original_didReceiveRemoteNotification_Imp = method_setImplementation(method3, (IMP)__swizzled_didReceiveRemoteNotification);
|
||||
|
||||
|
||||
Method method4 = class_getInstanceMethod([self class], @selector(application:openURL:options:));
|
||||
__original_openUrl_Imp = method_setImplementation(method4, (IMP)__swizzled_openURL);
|
||||
|
||||
if (_AppsFlyerdelegate == nil) {
|
||||
_AppsFlyerdelegate = [[AppsFlyeriOSWarpper alloc] init];
|
||||
}
|
||||
|
||||
[self swizzleContinueUserActivity:[self class]];
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
+(void)swizzleContinueUserActivity:(Class)class {
|
||||
|
||||
SEL originalSelector = @selector(application:continueUserActivity:restorationHandler:);
|
||||
|
||||
Method defaultMethod = class_getInstanceMethod(class, originalSelector);
|
||||
Method swizzledMethod = class_getInstanceMethod(class, @selector(__swizzled_continueUserActivity));
|
||||
|
||||
BOOL isMethodExists = !class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
|
||||
|
||||
if (isMethodExists) {
|
||||
__original_continueUserActivity_Imp = method_setImplementation(defaultMethod, (IMP)__swizzled_continueUserActivity);
|
||||
} else {
|
||||
class_replaceMethod(class, originalSelector, (IMP)__swizzled_continueUserActivity, method_getTypeEncoding(swizzledMethod));
|
||||
}
|
||||
}
|
||||
|
||||
BOOL __swizzled_continueUserActivity(id self, SEL _cmd, UIApplication* application, NSUserActivity* userActivity, void (^restorationHandler)(NSArray*)) {
|
||||
NSLog(@"swizzled continueUserActivity");
|
||||
[[AppsFlyerAttribution shared] continueUserActivity:userActivity restorationHandler:restorationHandler];
|
||||
|
||||
if(__original_continueUserActivity_Imp){
|
||||
return ((BOOL(*)(id, SEL, UIApplication*, NSUserActivity*, void (^)(NSArray*)))__original_continueUserActivity_Imp)(self, _cmd, application, userActivity, NULL);
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void __swizzled_applicationDidBecomeActive(id self, SEL _cmd, UIApplication* launchOptions) {
|
||||
NSLog(@"swizzled applicationDidBecomeActive");
|
||||
[[AppsFlyerLib shared] setDelegate:_AppsFlyerdelegate];
|
||||
|
||||
if(didEnteredBackGround && AppsFlyeriOSWarpper.didCallStart == YES){
|
||||
[[AppsFlyerLib shared] start];
|
||||
}
|
||||
|
||||
if(__original_applicationDidBecomeActive_Imp){
|
||||
((void(*)(id,SEL, UIApplication*))__original_applicationDidBecomeActive_Imp)(self, _cmd, launchOptions);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void __swizzled_applicationDidEnterBackground(id self, SEL _cmd, UIApplication* application) {
|
||||
NSLog(@"swizzled applicationDidEnterBackground");
|
||||
didEnteredBackGround = YES;
|
||||
if(__original_applicationDidEnterBackground_Imp){
|
||||
((void(*)(id,SEL, UIApplication*))__original_applicationDidEnterBackground_Imp)(self, _cmd, application);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BOOL __swizzled_didReceiveRemoteNotification(id self, SEL _cmd, UIApplication* application, NSDictionary* userInfo,void (^UIBackgroundFetchResult)(void) ) {
|
||||
NSLog(@"swizzled didReceiveRemoteNotification");
|
||||
|
||||
[[AppsFlyerLib shared] handlePushNotification:userInfo];
|
||||
|
||||
if(__original_didReceiveRemoteNotification_Imp){
|
||||
return ((BOOL(*)(id, SEL, UIApplication*, NSDictionary*, int(UIBackgroundFetchResult)))__original_didReceiveRemoteNotification_Imp)(self, _cmd, application, userInfo, nil);
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOL __swizzled_openURL(id self, SEL _cmd, UIApplication* application, NSURL* url, NSDictionary * options) {
|
||||
NSLog(@"swizzled openURL");
|
||||
[[AppsFlyerAttribution shared] handleOpenUrl:url options:options];
|
||||
if(__original_openUrl_Imp){
|
||||
return ((BOOL(*)(id, SEL, UIApplication*, NSURL*, NSDictionary*))__original_openUrl_Imp)(self, _cmd, application, url, options);
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
37
Assets/AppsFlyer/Plugins/iOS/AppsFlyer+AppController.m.meta
Normal file
37
Assets/AppsFlyer/Plugins/iOS/AppsFlyer+AppController.m.meta
Normal file
@@ -0,0 +1,37 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6ae9e1f7daef2427588fab2fbf8d35d5
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
- first:
|
||||
iPhone: iOS
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
tvOS: tvOS
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
131
Assets/AppsFlyer/Plugins/iOS/AppsFlyerAppController.mm
Normal file
131
Assets/AppsFlyer/Plugins/iOS/AppsFlyerAppController.mm
Normal file
@@ -0,0 +1,131 @@
|
||||
//
|
||||
// AppsFlyerAppController.mm
|
||||
// Unity-iPhone
|
||||
//
|
||||
// Created by Jonathan Wesfield on 30/07/2019.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "UnityAppController.h"
|
||||
#import "AppDelegateListener.h"
|
||||
#import "AppsFlyeriOSWrapper.h"
|
||||
#if __has_include(<AppsFlyerLib/AppsFlyerLib.h>)
|
||||
#import <AppsFlyerLib/AppsFlyerLib.h>
|
||||
#else
|
||||
#import "AppsFlyerLib.h"
|
||||
#endif
|
||||
#import <objc/message.h>
|
||||
|
||||
/**
|
||||
Note if you would like to use method swizzeling see AppsFlyer+AppController.m
|
||||
If you are using swizzeling then comment out the method that is being swizzeled in AppsFlyerAppController.mm
|
||||
Only use swizzeling if there are conflicts with other plugins that needs to be resolved.
|
||||
*/
|
||||
|
||||
|
||||
@interface AppsFlyerAppController : UnityAppController <AppDelegateListener>
|
||||
{
|
||||
BOOL didEnteredBackGround;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation AppsFlyerAppController
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
|
||||
id swizzleFlag = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"AppsFlyerShouldSwizzle"];
|
||||
BOOL shouldSwizzle = swizzleFlag ? [swizzleFlag boolValue] : NO;
|
||||
|
||||
if(!shouldSwizzle){
|
||||
UnityRegisterAppDelegateListener(self);
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)didFinishLaunching:(NSNotification*)notification {
|
||||
NSLog(@"got didFinishLaunching = %@",notification.userInfo);
|
||||
|
||||
|
||||
if (_AppsFlyerdelegate == nil) {
|
||||
_AppsFlyerdelegate = [[AppsFlyeriOSWarpper alloc] init];
|
||||
}
|
||||
[[AppsFlyerLib shared] setDelegate:_AppsFlyerdelegate];
|
||||
|
||||
if (notification.userInfo[@"url"]) {
|
||||
[self onOpenURL:notification];
|
||||
}
|
||||
}
|
||||
|
||||
-(void)didBecomeActive:(NSNotification*)notification {
|
||||
NSLog(@"got didBecomeActive(out) = %@", notification.userInfo);
|
||||
if (didEnteredBackGround == YES && AppsFlyeriOSWarpper.didCallStart == YES) {
|
||||
[[AppsFlyerLib shared] start];
|
||||
didEnteredBackGround = NO;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)didEnterBackground:(NSNotification*)notification {
|
||||
NSLog(@"got didEnterBackground = %@", notification.userInfo);
|
||||
didEnteredBackGround = YES;
|
||||
}
|
||||
|
||||
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray *))restorationHandler {
|
||||
[[AppsFlyerAttribution shared] continueUserActivity:userActivity restorationHandler:restorationHandler];
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
- (void)onOpenURL:(NSNotification*)notification {
|
||||
NSLog(@"got onOpenURL = %@", notification.userInfo);
|
||||
NSURL *url = notification.userInfo[@"url"];
|
||||
NSString *sourceApplication = notification.userInfo[@"sourceApplication"];
|
||||
|
||||
if (sourceApplication == nil) {
|
||||
sourceApplication = @"";
|
||||
}
|
||||
|
||||
if (url != nil) {
|
||||
[[AppsFlyerAttribution shared] handleOpenUrl:url sourceApplication:sourceApplication annotation:nil];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
- (void)didReceiveRemoteNotification:(NSNotification*)notification {
|
||||
NSLog(@"got didReceiveRemoteNotification = %@", notification.userInfo);
|
||||
[[AppsFlyerLib shared] handlePushNotification:notification.userInfo];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#if !(AFSDK_SHOULD_SWIZZLE)
|
||||
|
||||
IMPL_APP_CONTROLLER_SUBCLASS(AppsFlyerAppController)
|
||||
|
||||
#endif
|
||||
/**
|
||||
Note if you would not like to use IMPL_APP_CONTROLLER_SUBCLASS you can replace it with the code below.
|
||||
<code>
|
||||
+(void)load
|
||||
{
|
||||
[AppsFlyerAppController plugin];
|
||||
}
|
||||
|
||||
// Singleton accessor.
|
||||
+ (AppsFlyerAppController *)plugin
|
||||
{
|
||||
static AppsFlyerAppController *sharedInstance = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
|
||||
dispatch_once(&onceToken, ^{
|
||||
|
||||
sharedInstance = [[AppsFlyerAppController alloc] init];
|
||||
});
|
||||
|
||||
return sharedInstance;
|
||||
}
|
||||
</code>
|
||||
**/
|
||||
37
Assets/AppsFlyer/Plugins/iOS/AppsFlyerAppController.mm.meta
Normal file
37
Assets/AppsFlyer/Plugins/iOS/AppsFlyerAppController.mm.meta
Normal file
@@ -0,0 +1,37 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2d1497a1493b24fecaa58bd3a7b707f9
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
- first:
|
||||
iPhone: iOS
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
tvOS: tvOS
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
34
Assets/AppsFlyer/Plugins/iOS/AppsFlyerAttribution.h
Normal file
34
Assets/AppsFlyer/Plugins/iOS/AppsFlyerAttribution.h
Normal file
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// AppsFlyerAttribution.h
|
||||
// UnityFramework
|
||||
//
|
||||
// Created by Margot Guetta on 11/04/2021.
|
||||
//
|
||||
|
||||
#ifndef AppsFlyerAttribution_h
|
||||
#define AppsFlyerAttribution_h
|
||||
#endif /* AppsFlyerAttribution_h */
|
||||
#if __has_include(<AppsFlyerLib/AppsFlyerLib.h>)
|
||||
#import <AppsFlyerLib/AppsFlyerLib.h>
|
||||
#else
|
||||
#import "AppsFlyerLib.h"
|
||||
#endif
|
||||
|
||||
|
||||
@interface AppsFlyerAttribution : NSObject
|
||||
@property NSUserActivity*_Nullable userActivity;
|
||||
@property (nonatomic, copy) void (^ _Nullable restorationHandler)(NSArray *_Nullable );
|
||||
@property NSURL * _Nullable url;
|
||||
@property NSDictionary * _Nullable options;
|
||||
@property NSString* _Nullable sourceApplication;
|
||||
@property id _Nullable annotation;
|
||||
@property BOOL isBridgeReady;
|
||||
|
||||
+ (AppsFlyerAttribution *_Nullable)shared;
|
||||
- (void) continueUserActivity: (NSUserActivity*_Nullable) userActivity restorationHandler: (void (^_Nullable)(NSArray * _Nullable))restorationHandler;
|
||||
- (void) handleOpenUrl:(NSURL*_Nullable)url options:(NSDictionary*_Nullable) options;
|
||||
- (void) handleOpenUrl: (NSURL *_Nonnull)url sourceApplication:(NSString*)sourceApplication annotation:(id)annotation;
|
||||
|
||||
@end
|
||||
|
||||
static NSString * _Nullable const AF_BRIDGE_SET = @"bridge is set";
|
||||
27
Assets/AppsFlyer/Plugins/iOS/AppsFlyerAttribution.h.meta
Normal file
27
Assets/AppsFlyer/Plugins/iOS/AppsFlyerAttribution.h.meta
Normal file
@@ -0,0 +1,27 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8544dc3b3c7bb40d397b2de568df1058
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
86
Assets/AppsFlyer/Plugins/iOS/AppsFlyerAttribution.m
Normal file
86
Assets/AppsFlyer/Plugins/iOS/AppsFlyerAttribution.m
Normal file
@@ -0,0 +1,86 @@
|
||||
//
|
||||
// NSObject+AppsFlyerAttribution.m
|
||||
// UnityFramework
|
||||
//
|
||||
// Created by Margot Guetta on 11/04/2021.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "AppsFlyerAttribution.h"
|
||||
|
||||
@implementation AppsFlyerAttribution
|
||||
|
||||
+ (id)shared {
|
||||
static AppsFlyerAttribution *shared = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
shared = [[self alloc] init];
|
||||
});
|
||||
return shared;
|
||||
}
|
||||
|
||||
- (id)init {
|
||||
if (self = [super init]) {
|
||||
self.options = nil;
|
||||
self.restorationHandler = nil;
|
||||
self.url = nil;
|
||||
self.userActivity = nil;
|
||||
self.annotation = nil;
|
||||
self.sourceApplication = nil;
|
||||
self.isBridgeReady = NO;
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(receiveBridgeReadyNotification:)
|
||||
name:AF_BRIDGE_SET
|
||||
object:nil];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) continueUserActivity: (NSUserActivity*_Nullable) userActivity restorationHandler: (void (^_Nullable)(NSArray * _Nullable))restorationHandler{
|
||||
if(self.isBridgeReady == YES){
|
||||
[[AppsFlyerLib shared] continueUserActivity:userActivity restorationHandler:restorationHandler];
|
||||
}else{
|
||||
[AppsFlyerAttribution shared].userActivity = userActivity;
|
||||
[AppsFlyerAttribution shared].restorationHandler = restorationHandler;
|
||||
}
|
||||
}
|
||||
|
||||
- (void) handleOpenUrl:(NSURL *)url options:(NSDictionary *)options{
|
||||
if(self.isBridgeReady == YES){
|
||||
[[AppsFlyerLib shared] handleOpenUrl:url options:options];
|
||||
}else{
|
||||
[AppsFlyerAttribution shared].url = url;
|
||||
[AppsFlyerAttribution shared].options = options;
|
||||
}
|
||||
}
|
||||
|
||||
- (void) handleOpenUrl:(NSURL *)url sourceApplication:(NSString*)sourceApplication annotation:(id)annotation{
|
||||
if(self.isBridgeReady == YES){
|
||||
[[AppsFlyerLib shared] handleOpenURL:url sourceApplication:sourceApplication withAnnotation:annotation];
|
||||
}else{
|
||||
[AppsFlyerAttribution shared].url = url;
|
||||
[AppsFlyerAttribution shared].sourceApplication = sourceApplication;
|
||||
[AppsFlyerAttribution shared].annotation = annotation;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
- (void) receiveBridgeReadyNotification:(NSNotification *) notification
|
||||
{
|
||||
NSLog (@"AppsFlyer Debug: handle deep link");
|
||||
if(self.url && self.sourceApplication){
|
||||
[[AppsFlyerLib shared] handleOpenURL:self.url sourceApplication:self.sourceApplication withAnnotation:self.annotation];
|
||||
self.url = nil;
|
||||
self.sourceApplication = nil;
|
||||
self.annotation = nil;
|
||||
}else if(self.options && self.url){
|
||||
[[AppsFlyerLib shared] handleOpenUrl:self.url options:self.options];
|
||||
self.options = nil;
|
||||
self.url = nil;
|
||||
}else if(self.userActivity){
|
||||
[[AppsFlyerLib shared] continueUserActivity:self.userActivity restorationHandler:nil];
|
||||
self.userActivity = nil;
|
||||
self.restorationHandler = nil;
|
||||
}
|
||||
}
|
||||
@end
|
||||
37
Assets/AppsFlyer/Plugins/iOS/AppsFlyerAttribution.m.meta
Normal file
37
Assets/AppsFlyer/Plugins/iOS/AppsFlyerAttribution.m.meta
Normal file
@@ -0,0 +1,37 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1060e47d7b9e2453ba575f0b455b2bf8
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
- first:
|
||||
iPhone: iOS
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
tvOS: tvOS
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
71
Assets/AppsFlyer/Plugins/iOS/AppsFlyeriOSWrapper.h
Normal file
71
Assets/AppsFlyer/Plugins/iOS/AppsFlyeriOSWrapper.h
Normal file
@@ -0,0 +1,71 @@
|
||||
//
|
||||
// AppsFlyeriOSWarpper.h
|
||||
// Unity-iPhone
|
||||
//
|
||||
// Created by Jonathan Wesfield on 24/07/2019.
|
||||
//
|
||||
|
||||
#import "AFUnityUtils.mm"
|
||||
#import "UnityAppController.h"
|
||||
#import "AppsFlyerAttribution.h"
|
||||
#if __has_include(<AppsFlyerLib/AppsFlyerLib.h>)
|
||||
#import <AppsFlyerLib/AppsFlyerLib.h>
|
||||
#else
|
||||
#import "AppsFlyerLib.h"
|
||||
#endif
|
||||
#if __has_include(<PurchaseConnector/PurchaseConnector.h>)
|
||||
#import <PurchaseConnector/PurchaseConnector.h>
|
||||
#else
|
||||
#import "PurchaseConnector.h"
|
||||
#endif
|
||||
#import <PurchaseConnector/PurchaseConnector-Swift.h>
|
||||
|
||||
// Add StoreKit 2 support
|
||||
#if __has_include(<StoreKit/StoreKit.h>)
|
||||
#import <StoreKit/StoreKit.h>
|
||||
#endif
|
||||
|
||||
@interface AppsFlyeriOSWarpper : NSObject <AppsFlyerLibDelegate, AppsFlyerDeepLinkDelegate, AppsFlyerPurchaseRevenueDelegate, AppsFlyerPurchaseRevenueDataSource, AppsFlyerPurchaseRevenueDataSourceStoreKit2>
|
||||
|
||||
+ (BOOL) didCallStart;
|
||||
+ (void) setDidCallStart:(BOOL)val;
|
||||
|
||||
// Add StoreKit 2 methods
|
||||
- (void)setStoreKitVersion:(int)storeKitVersion;
|
||||
- (void)logConsumableTransaction:(id)transaction;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
static AppsFlyeriOSWarpper *_AppsFlyerdelegate;
|
||||
static const int kPushNotificationSize = 32;
|
||||
|
||||
static NSString* ConversionDataCallbackObject = @"AppsFlyerObject";
|
||||
|
||||
static const char* VALIDATE_CALLBACK = "didFinishValidateReceipt";
|
||||
static const char* VALIDATE_ERROR_CALLBACK = "didFinishValidateReceiptWithError";
|
||||
static const char* GCD_CALLBACK = "onConversionDataSuccess";
|
||||
static const char* GCD_ERROR_CALLBACK = "onConversionDataFail";
|
||||
static const char* OAOA_CALLBACK = "onAppOpenAttribution";
|
||||
static const char* OAOA_ERROR_CALLBACK = "onAppOpenAttributionFailure";
|
||||
static const char* GENERATE_LINK_CALLBACK = "onInviteLinkGenerated";
|
||||
static const char* OPEN_STORE_LINK_CALLBACK = "onOpenStoreLinkGenerated";
|
||||
static const char* START_REQUEST_CALLBACK = "requestResponseReceived";
|
||||
static const char* IN_APP_RESPONSE_CALLBACK = "inAppResponseReceived";
|
||||
static const char* ON_DEEPLINKING = "onDeepLinking";
|
||||
static const char* VALIDATE_AND_LOG_V2_CALLBACK = "onValidateAndLogComplete";
|
||||
static const char* VALIDATE_AND_LOG_V2_ERROR_CALLBACK = "onValidateAndLogFailure";
|
||||
|
||||
|
||||
static NSString* validateObjectName = @"";
|
||||
static NSString* openStoreObjectName = @"";
|
||||
static NSString* generateInviteObjectName = @"";
|
||||
static NSString* validateAndLogObjectName = @"";
|
||||
static NSString* startRequestObjectName = @"";
|
||||
static NSString* inAppRequestObjectName = @"";
|
||||
static NSString* onDeeplinkingObjectName = @"";
|
||||
|
||||
static const char* PURCHASE_REVENUE_VALIDATION_CALLBACK = "didReceivePurchaseRevenueValidationInfo";
|
||||
static const char* PURCHASE_REVENUE_ERROR_CALLBACK = "didReceivePurchaseRevenueError";
|
||||
|
||||
static NSString* onPurchaseValidationObjectName = @"";
|
||||
27
Assets/AppsFlyer/Plugins/iOS/AppsFlyeriOSWrapper.h.meta
Normal file
27
Assets/AppsFlyer/Plugins/iOS/AppsFlyeriOSWrapper.h.meta
Normal file
@@ -0,0 +1,27 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 147104b04b5794eaa92b4195cc328e13
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
601
Assets/AppsFlyer/Plugins/iOS/AppsFlyeriOSWrapper.mm
Normal file
601
Assets/AppsFlyer/Plugins/iOS/AppsFlyeriOSWrapper.mm
Normal file
@@ -0,0 +1,601 @@
|
||||
//
|
||||
// AppsFlyeriOSWarpper.mm
|
||||
// Unity-iPhone
|
||||
//
|
||||
// Created by Jonathan Wesfield on 24/07/2019.
|
||||
//
|
||||
|
||||
#import "AppsFlyeriOSWrapper.h"
|
||||
#import <objc/runtime.h>
|
||||
|
||||
#import <StoreKit/StoreKit.h>
|
||||
#import "UnityFramework/UnityFramework-Swift.h"
|
||||
|
||||
#if __has_include(<PurchaseConnector/PurchaseConnector-Swift.h>)
|
||||
#import <PurchaseConnector/PurchaseConnector-Swift.h>
|
||||
#elif __has_include("PurchaseConnector-Swift.h")
|
||||
#import "PurchaseConnector-Swift.h"
|
||||
#endif
|
||||
|
||||
#if __has_include(<UnityFramework/UnityFramework-Swift.h>)
|
||||
#import <UnityFramework/UnityFramework-Swift.h>
|
||||
#elif __has_include("UnityFramework-Swift.h")
|
||||
#import "UnityFramework-Swift.h"
|
||||
#endif
|
||||
|
||||
static void unityCallBack(NSString* objectName, const char* method, const char* msg) {
|
||||
if(objectName){
|
||||
UnitySendMessage([objectName UTF8String], method, msg);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
const void _startSDK(bool shouldCallback, const char* objectName) {
|
||||
[[AppsFlyerLib shared] setPluginInfoWith: AFSDKPluginUnity
|
||||
pluginVersion:@"6.17.91"
|
||||
additionalParams:nil];
|
||||
startRequestObjectName = stringFromChar(objectName);
|
||||
AppsFlyeriOSWarpper.didCallStart = YES;
|
||||
[AppsFlyerAttribution shared].isBridgeReady = YES;
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:AF_BRIDGE_SET object: [AppsFlyerAttribution shared]];
|
||||
[[AppsFlyerLib shared] startWithCompletionHandler:^(NSDictionary<NSString *,id> *dictionary, NSError *error) {
|
||||
if(shouldCallback){
|
||||
if (error) {
|
||||
NSDictionary *callbackDictionary = @{@"statusCode":[NSNumber numberWithLong:[error code]]};
|
||||
unityCallBack(startRequestObjectName, START_REQUEST_CALLBACK, stringFromdictionary(callbackDictionary));
|
||||
return;
|
||||
}
|
||||
if (dictionary) {
|
||||
unityCallBack(startRequestObjectName, START_REQUEST_CALLBACK, stringFromdictionary(dictionary));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
const void _setCustomerUserID (const char* customerUserID) {
|
||||
[[AppsFlyerLib shared] setCustomerUserID:stringFromChar(customerUserID)];
|
||||
}
|
||||
|
||||
const void _setAdditionalData (const char* customData) {
|
||||
[[AppsFlyerLib shared] setAdditionalData:dictionaryFromJson(customData)];
|
||||
}
|
||||
|
||||
const void _setAppsFlyerDevKey (const char* appsFlyerDevKey) {
|
||||
[AppsFlyerLib shared].appsFlyerDevKey = stringFromChar(appsFlyerDevKey);
|
||||
}
|
||||
|
||||
const void _setAppleAppID (const char* appleAppID) {
|
||||
[AppsFlyerLib shared].appleAppID = stringFromChar(appleAppID);
|
||||
}
|
||||
|
||||
const void _setCurrencyCode (const char* currencyCode) {
|
||||
[[AppsFlyerLib shared] setCurrencyCode:stringFromChar(currencyCode)];
|
||||
}
|
||||
|
||||
const void _setDisableCollectAppleAdSupport (bool disableAdvertisingIdentifier) {
|
||||
//[AppsFlyerLib shared].disableAdvertisingIdentifier = disableAdvertisingIdentifier;
|
||||
}
|
||||
|
||||
const void _setIsDebug (bool isDebug) {
|
||||
[AppsFlyerLib shared].isDebug = isDebug;
|
||||
}
|
||||
|
||||
const void _setShouldCollectDeviceName (bool shouldCollectDeviceName) {
|
||||
[AppsFlyerLib shared].shouldCollectDeviceName = shouldCollectDeviceName;
|
||||
}
|
||||
|
||||
const void _setAppInviteOneLinkID (const char* appInviteOneLinkID) {
|
||||
[[AppsFlyerLib shared] setAppInviteOneLink:stringFromChar(appInviteOneLinkID)];
|
||||
}
|
||||
|
||||
const void _setDeepLinkTimeout (long deepLinkTimeout) {
|
||||
[AppsFlyerLib shared].deepLinkTimeout = deepLinkTimeout;
|
||||
}
|
||||
|
||||
const void _anonymizeUser (bool anonymizeUser) {
|
||||
[AppsFlyerLib shared].anonymizeUser = anonymizeUser;
|
||||
}
|
||||
|
||||
const void _enableTCFDataCollection (bool shouldCollectTcfData) {
|
||||
[[AppsFlyerLib shared] enableTCFDataCollection:shouldCollectTcfData];
|
||||
}
|
||||
|
||||
const void _setConsentData(const char* isUserSubjectToGDPR, const char* hasConsentForDataUsage, const char* hasConsentForAdsPersonalization, const char* hasConsentForAdStorage) {
|
||||
|
||||
NSNumber *gdpr = intFromNullableBool(isUserSubjectToGDPR);
|
||||
NSNumber *dataUsage = intFromNullableBool(hasConsentForDataUsage);
|
||||
NSNumber *adsPersonalization = intFromNullableBool(hasConsentForAdsPersonalization);
|
||||
NSNumber *adStorage = intFromNullableBool(hasConsentForAdStorage);
|
||||
|
||||
AppsFlyerConsent *consentData = [[AppsFlyerConsent alloc] initWithIsUserSubjectToGDPR:gdpr
|
||||
hasConsentForDataUsage:dataUsage
|
||||
hasConsentForAdsPersonalization:adsPersonalization
|
||||
hasConsentForAdStorage:adStorage];
|
||||
|
||||
[[AppsFlyerLib shared] setConsentData:consentData];
|
||||
}
|
||||
|
||||
const void _logAdRevenue(const char* monetizationNetwork, int mediationNetworkInt, const char* currencyIso4217Code, double eventRevenue, const char* additionalParameters) {
|
||||
AppsFlyerAdRevenueMediationNetworkType mediationNetwork = mediationNetworkTypeFromInt(mediationNetworkInt);
|
||||
NSNumber *number = [NSNumber numberWithDouble:eventRevenue];
|
||||
AFAdRevenueData *adRevenue = [[AFAdRevenueData alloc] initWithMonetizationNetwork:stringFromChar(monetizationNetwork) mediationNetwork:mediationNetwork currencyIso4217Code:stringFromChar(currencyIso4217Code) eventRevenue:number];
|
||||
[[AppsFlyerLib shared] logAdRevenue: adRevenue additionalParameters:dictionaryFromJson(additionalParameters)];
|
||||
}
|
||||
|
||||
const void _setDisableCollectIAd (bool disableCollectASA) {
|
||||
[AppsFlyerLib shared].disableCollectASA = disableCollectASA;
|
||||
}
|
||||
|
||||
const void _setUseReceiptValidationSandbox (bool useReceiptValidationSandbox) {
|
||||
[AppsFlyerLib shared].useReceiptValidationSandbox = useReceiptValidationSandbox;
|
||||
}
|
||||
|
||||
const void _setUseUninstallSandbox (bool useUninstallSandbox) {
|
||||
[AppsFlyerLib shared].useUninstallSandbox = useUninstallSandbox;
|
||||
}
|
||||
|
||||
const void _setResolveDeepLinkURLs (int length, const char **resolveDeepLinkURLs) {
|
||||
if(length > 0 && resolveDeepLinkURLs) {
|
||||
[[AppsFlyerLib shared] setResolveDeepLinkURLs:NSArrayFromCArray(length, resolveDeepLinkURLs)];
|
||||
}
|
||||
}
|
||||
|
||||
const void _setOneLinkCustomDomains (int length, const char **oneLinkCustomDomains) {
|
||||
if(length > 0 && oneLinkCustomDomains) {
|
||||
[[AppsFlyerLib shared] setOneLinkCustomDomains:NSArrayFromCArray(length, oneLinkCustomDomains)];
|
||||
}
|
||||
}
|
||||
|
||||
const void _afSendEvent (const char* eventName, const char* eventValues, bool shouldCallback, const char* objectName) {
|
||||
inAppRequestObjectName = stringFromChar(objectName);
|
||||
[[AppsFlyerLib shared] logEventWithEventName:stringFromChar(eventName) eventValues:dictionaryFromJson(eventValues) completionHandler:^(NSDictionary<NSString *,id> *dictionary, NSError *error) {
|
||||
if(shouldCallback){
|
||||
if (error) {
|
||||
NSDictionary *callbackDictionary = @{@"statusCode":[NSNumber numberWithLong:[error code]]};
|
||||
unityCallBack(inAppRequestObjectName, IN_APP_RESPONSE_CALLBACK, stringFromdictionary(callbackDictionary));
|
||||
return;
|
||||
}
|
||||
if (dictionary) {
|
||||
unityCallBack(inAppRequestObjectName, IN_APP_RESPONSE_CALLBACK, stringFromdictionary(dictionary));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
const void _recordLocation (double longitude, double latitude) {
|
||||
[[AppsFlyerLib shared] logLocation:longitude latitude:latitude];
|
||||
}
|
||||
|
||||
const char* _getAppsFlyerId () {
|
||||
return getCString([[[AppsFlyerLib shared] getAppsFlyerUID] UTF8String]);
|
||||
}
|
||||
|
||||
const void _registerUninstall (unsigned char* deviceToken) {
|
||||
if(deviceToken){
|
||||
NSData* tokenData = [NSData dataWithBytes:(const void *)deviceToken length:sizeof(unsigned char)*kPushNotificationSize];
|
||||
[[AppsFlyerLib shared] registerUninstall:tokenData];
|
||||
}
|
||||
}
|
||||
|
||||
const void _handlePushNotification (const char* pushPayload) {
|
||||
[[AppsFlyerLib shared] handlePushNotification:dictionaryFromJson(pushPayload)];
|
||||
}
|
||||
|
||||
const char* _getSDKVersion () {
|
||||
return getCString([[[AppsFlyerLib shared] getSDKVersion] UTF8String]);
|
||||
}
|
||||
|
||||
const void _setHost (const char* host, const char* hostPrefix) {
|
||||
[[AppsFlyerLib shared] setHost:stringFromChar(host) withHostPrefix:stringFromChar(hostPrefix)];
|
||||
}
|
||||
|
||||
const void _setMinTimeBetweenSessions (int minTimeBetweenSessions) {
|
||||
[AppsFlyerLib shared].minTimeBetweenSessions = minTimeBetweenSessions;
|
||||
}
|
||||
|
||||
const void _stopSDK (bool isStopped) {
|
||||
[AppsFlyerLib shared].isStopped = isStopped;
|
||||
}
|
||||
|
||||
const BOOL _isSDKStopped () {
|
||||
return [AppsFlyerLib shared].isStopped;
|
||||
}
|
||||
|
||||
const void _handleOpenUrl(const char *url, const char *sourceApplication, const char *annotation) {
|
||||
[[AppsFlyerLib shared] handleOpenURL:[NSURL URLWithString:stringFromChar(url)] sourceApplication:stringFromChar(sourceApplication) withAnnotation:stringFromChar(annotation)]; }
|
||||
|
||||
const void _recordCrossPromoteImpression (const char* appID, const char* campaign, const char* parameters) {
|
||||
[AppsFlyerCrossPromotionHelper logCrossPromoteImpression:stringFromChar(appID) campaign:stringFromChar(campaign) parameters:dictionaryFromJson(parameters)]; }
|
||||
|
||||
const void _attributeAndOpenStore (const char* appID, const char* campaign, const char* parameters, const char* objectName) {
|
||||
|
||||
openStoreObjectName = stringFromChar(objectName);
|
||||
|
||||
[AppsFlyerCrossPromotionHelper
|
||||
logAndOpenStore:stringFromChar(appID)
|
||||
campaign:stringFromChar(campaign)
|
||||
parameters:dictionaryFromJson(parameters)
|
||||
openStore:^(NSURLSession * _Nonnull urlSession, NSURL * _Nonnull clickURL) {
|
||||
unityCallBack(openStoreObjectName, OPEN_STORE_LINK_CALLBACK, [clickURL.absoluteString UTF8String]);
|
||||
}];
|
||||
}
|
||||
|
||||
const void _generateUserInviteLink (const char* parameters, const char* objectName) {
|
||||
|
||||
generateInviteObjectName = stringFromChar(objectName);
|
||||
|
||||
[AppsFlyerShareInviteHelper generateInviteUrlWithLinkGenerator:^AppsFlyerLinkGenerator * _Nonnull(AppsFlyerLinkGenerator * _Nonnull generator) {
|
||||
return generatorFromDictionary(dictionaryFromJson(parameters), generator);
|
||||
} completionHandler:^(NSURL * _Nullable url) {
|
||||
unityCallBack(generateInviteObjectName, GENERATE_LINK_CALLBACK, [url.absoluteString UTF8String]);
|
||||
}];
|
||||
}
|
||||
|
||||
const void _recordInvite (const char* channel, const char* parameters) {
|
||||
[AppsFlyerShareInviteHelper logInvite:stringFromChar(channel) parameters:dictionaryFromJson(parameters)];
|
||||
}
|
||||
|
||||
const void _setUserEmails (int emailCryptTypeInt , int length, const char **userEmails) {
|
||||
if(length > 0 && userEmails) {
|
||||
[[AppsFlyerLib shared] setUserEmails:NSArrayFromCArray(length, userEmails) withCryptType:emailCryptTypeFromInt(emailCryptTypeInt)];
|
||||
}
|
||||
}
|
||||
|
||||
const void _setPhoneNumber (const char* phoneNumber) {
|
||||
[[AppsFlyerLib shared] setPhoneNumber:stringFromChar(phoneNumber)];
|
||||
}
|
||||
|
||||
const void _setSharingFilterForAllPartners () {
|
||||
[[AppsFlyerLib shared] setSharingFilterForAllPartners];
|
||||
}
|
||||
|
||||
const void _setSharingFilter (int length, const char **partners) {
|
||||
if(length > 0 && partners) {
|
||||
[[AppsFlyerLib shared] setSharingFilter:NSArrayFromCArray(length, partners)];
|
||||
}
|
||||
}
|
||||
|
||||
const void _setSharingFilterForPartners (int length, const char **partners) {
|
||||
if(length > 0 && partners) {
|
||||
[[AppsFlyerLib shared] setSharingFilterForPartners:NSArrayFromCArray(length, partners)];
|
||||
} else {
|
||||
[[AppsFlyerLib shared] setSharingFilterForPartners:nil];
|
||||
}
|
||||
}
|
||||
|
||||
const void _validateAndSendInAppPurchase (const char* productIdentifier, const char* price, const char* currency, const char* transactionId, const char* additionalParameters, const char* objectName) {
|
||||
|
||||
validateObjectName = stringFromChar(objectName);
|
||||
|
||||
[[AppsFlyerLib shared]
|
||||
validateAndLogInAppPurchase:stringFromChar(productIdentifier)
|
||||
price:stringFromChar(price)
|
||||
currency:stringFromChar(currency)
|
||||
transactionId:stringFromChar(transactionId)
|
||||
additionalParameters:dictionaryFromJson(additionalParameters)
|
||||
success:^(NSDictionary *result){
|
||||
unityCallBack(validateObjectName, VALIDATE_CALLBACK, stringFromdictionary(result));
|
||||
} failure:^(NSError *error, id response) {
|
||||
if(response && [response isKindOfClass:[NSDictionary class]]) {
|
||||
NSDictionary* value = (NSDictionary*)response;
|
||||
unityCallBack(validateObjectName, VALIDATE_ERROR_CALLBACK, stringFromdictionary(value));
|
||||
} else {
|
||||
unityCallBack(validateObjectName, VALIDATE_ERROR_CALLBACK, error ? [[error localizedDescription] UTF8String] : "error");
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
const void _validateAndSendInAppPurchaseV2 (const char* product, const char* transactionId, int purchaseType, const char* purchaseAdditionalDetails, const char* objectName) {
|
||||
|
||||
validateAndLogObjectName = stringFromChar(objectName);
|
||||
AFSDKPurchaseDetails *details = [[AFSDKPurchaseDetails alloc] initWithProductId:stringFromChar(product) transactionId:stringFromChar(transactionId) purchaseType:(AFSDKPurchaseType)purchaseType];
|
||||
|
||||
[[AppsFlyerLib shared]
|
||||
validateAndLogInAppPurchase:details
|
||||
purchaseAdditionalDetails:dictionaryFromJson(purchaseAdditionalDetails)
|
||||
completion:^(NSDictionary * _Nullable response, NSError * _Nullable error) {
|
||||
if (error) {
|
||||
unityCallBack(validateAndLogObjectName, VALIDATE_AND_LOG_V2_ERROR_CALLBACK, stringFromdictionary(dictionaryFromNSError(error)));
|
||||
} else {
|
||||
unityCallBack(validateAndLogObjectName, VALIDATE_AND_LOG_V2_CALLBACK, stringFromdictionary(response));
|
||||
}
|
||||
}];
|
||||
|
||||
}
|
||||
|
||||
const void _getConversionData(const char* objectName) {
|
||||
if (_AppsFlyerdelegate == nil) {
|
||||
_AppsFlyerdelegate = [[AppsFlyeriOSWarpper alloc] init];
|
||||
}
|
||||
ConversionDataCallbackObject = stringFromChar(objectName);
|
||||
[[AppsFlyerLib shared] setDelegate:_AppsFlyerdelegate];
|
||||
}
|
||||
|
||||
const void _waitForATTUserAuthorizationWithTimeoutInterval (int timeoutInterval) {
|
||||
//[[AppsFlyerLib shared] waitForATTUserAuthorizationWithTimeoutInterval:timeoutInterval];
|
||||
}
|
||||
|
||||
const void _disableSKAdNetwork (bool isDisabled) {
|
||||
[AppsFlyerLib shared].disableSKAdNetwork = isDisabled;
|
||||
}
|
||||
|
||||
const void _addPushNotificationDeepLinkPath (int length, const char **paths) {
|
||||
if(length > 0 && paths) {
|
||||
[[AppsFlyerLib shared] addPushNotificationDeepLinkPath:NSArrayFromCArray(length, paths)];
|
||||
}
|
||||
}
|
||||
|
||||
const void _subscribeForDeepLink (const char* objectName) {
|
||||
|
||||
onDeeplinkingObjectName = stringFromChar(objectName);
|
||||
|
||||
if (_AppsFlyerdelegate == nil) {
|
||||
_AppsFlyerdelegate = [[AppsFlyeriOSWarpper alloc] init];
|
||||
}
|
||||
[[AppsFlyerLib shared] setDeepLinkDelegate:_AppsFlyerdelegate];
|
||||
}
|
||||
|
||||
const void _setCurrentDeviceLanguage(const char* language) {
|
||||
[[AppsFlyerLib shared] setCurrentDeviceLanguage:stringFromChar(language)];
|
||||
}
|
||||
|
||||
const void _setPartnerData(const char* partnerId, const char* partnerInfo) {
|
||||
[[AppsFlyerLib shared] setPartnerDataWithPartnerId: stringFromChar(partnerId) partnerInfo:dictionaryFromJson(partnerInfo)];
|
||||
}
|
||||
|
||||
const void _disableIDFVCollection(bool isDisabled) {
|
||||
[AppsFlyerLib shared].disableIDFVCollection = isDisabled;
|
||||
}
|
||||
|
||||
// Purchase connector
|
||||
const void _startObservingTransactions() {
|
||||
[[PurchaseConnector shared] startObservingTransactions];
|
||||
}
|
||||
|
||||
const void _stopObservingTransactions() {
|
||||
[[PurchaseConnector shared] stopObservingTransactions];
|
||||
}
|
||||
|
||||
const void _setIsSandbox(bool isSandBox) {
|
||||
[[PurchaseConnector shared] setIsSandbox:isSandBox];
|
||||
}
|
||||
|
||||
const void _setPurchaseRevenueDelegate() {
|
||||
if (_AppsFlyerdelegate== nil) {
|
||||
_AppsFlyerdelegate = [[AppsFlyeriOSWarpper alloc] init];
|
||||
}
|
||||
[[PurchaseConnector shared] setPurchaseRevenueDelegate:_AppsFlyerdelegate];
|
||||
}
|
||||
|
||||
const void _setAutoLogPurchaseRevenue(int option) {
|
||||
[[PurchaseConnector shared] setAutoLogPurchaseRevenue:option];
|
||||
|
||||
}
|
||||
|
||||
const void _initPurchaseConnector(const char* objectName) {
|
||||
if (_AppsFlyerdelegate == nil) {
|
||||
_AppsFlyerdelegate = [[AppsFlyeriOSWarpper alloc] init];
|
||||
}
|
||||
onPurchaseValidationObjectName = stringFromChar(objectName);
|
||||
}
|
||||
|
||||
const void _setPurchaseRevenueDataSource(const char* objectName) {
|
||||
if (_AppsFlyerdelegate == nil) {
|
||||
_AppsFlyerdelegate = [[AppsFlyeriOSWarpper alloc] init];
|
||||
}
|
||||
|
||||
if (strstr(objectName, "StoreKit2") != NULL) {
|
||||
|
||||
// Force protocol conformance
|
||||
Protocol *sk2Protocol = @protocol(AppsFlyerPurchaseRevenueDataSourceStoreKit2);
|
||||
class_addProtocol([_AppsFlyerdelegate class], sk2Protocol);
|
||||
|
||||
if (![_AppsFlyerdelegate conformsToProtocol:@protocol(AppsFlyerPurchaseRevenueDataSourceStoreKit2)]) {
|
||||
NSLog(@"[AppsFlyer] Warning: SK2 protocol not conformed!");
|
||||
}
|
||||
}
|
||||
|
||||
[PurchaseConnector shared].purchaseRevenueDataSource = _AppsFlyerdelegate;
|
||||
}
|
||||
|
||||
const void _setStoreKitVersion(int storeKitVersion) {
|
||||
[[PurchaseConnector shared] setStoreKitVersion:(AFSDKStoreKitVersion)storeKitVersion];
|
||||
}
|
||||
|
||||
const void _logConsumableTransaction(const char* transactionId) {
|
||||
if (@available(iOS 15.0, *)) {
|
||||
NSString *transactionIdStr = [NSString stringWithUTF8String:transactionId];
|
||||
[AFUnityStoreKit2Bridge fetchAFSDKTransactionSK2WithTransactionId:transactionIdStr completion:^(AFSDKTransactionSK2 *afTransaction) {
|
||||
if (afTransaction) {
|
||||
[[PurchaseConnector shared] logConsumableTransaction:afTransaction];
|
||||
} else {
|
||||
NSLog(@"No AFSDKTransactionSK2 found for id %@", transactionIdStr);
|
||||
}
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef const char *(*UnityPurchaseCallback)(const char *, const char *);
|
||||
|
||||
UnityPurchaseCallback UnityPurchasesGetAdditionalParamsCallback = NULL;
|
||||
UnityPurchaseCallback UnityPurchasesGetAdditionalParamsCallbackSK2 = NULL;
|
||||
|
||||
__attribute__((visibility("default")))
|
||||
void RegisterUnityPurchaseRevenueParamsCallback(UnityPurchaseCallback callback) {
|
||||
UnityPurchasesGetAdditionalParamsCallback = callback;
|
||||
}
|
||||
|
||||
__attribute__((visibility("default")))
|
||||
void RegisterUnityPurchaseRevenueParamsCallbackSK2(UnityPurchaseCallback callback) {
|
||||
UnityPurchasesGetAdditionalParamsCallbackSK2 = callback;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@implementation AppsFlyeriOSWarpper
|
||||
|
||||
static BOOL didCallStart;
|
||||
+ (BOOL) didCallStart
|
||||
{ @synchronized(self) { return didCallStart; } }
|
||||
+ (void) setDidCallStart:(BOOL)val
|
||||
{ @synchronized(self) { didCallStart = val; } }
|
||||
|
||||
- (void)onConversionDataSuccess:(NSDictionary *)installData {
|
||||
unityCallBack(ConversionDataCallbackObject, GCD_CALLBACK, stringFromdictionary(installData));
|
||||
}
|
||||
|
||||
- (void)onConversionDataFail:(NSError *)error {
|
||||
unityCallBack(ConversionDataCallbackObject, GCD_ERROR_CALLBACK, [[error localizedDescription] UTF8String]);
|
||||
}
|
||||
|
||||
- (void)onAppOpenAttribution:(NSDictionary *)attributionData {
|
||||
unityCallBack(ConversionDataCallbackObject, OAOA_CALLBACK, stringFromdictionary(attributionData));
|
||||
}
|
||||
|
||||
- (void)onAppOpenAttributionFailure:(NSError *)error {
|
||||
unityCallBack(ConversionDataCallbackObject, OAOA_ERROR_CALLBACK, [[error localizedDescription] UTF8String]);
|
||||
}
|
||||
|
||||
- (void)didResolveDeepLink:(AppsFlyerDeepLinkResult *)result{
|
||||
|
||||
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
|
||||
|
||||
[dict setValue:stringFromDeepLinkResultError(result) forKey:@"error"];
|
||||
[dict setValue:stringFromDeepLinkResultStatus(result.status) forKey:@"status"];
|
||||
|
||||
if(result && result.deepLink){
|
||||
[dict setValue:result.deepLink.description forKey:@"deepLink"];
|
||||
[dict setValue:@(result.deepLink.isDeferred) forKey:@"is_deferred"];
|
||||
}
|
||||
|
||||
unityCallBack(onDeeplinkingObjectName, ON_DEEPLINKING, stringFromdictionary(dict));
|
||||
}
|
||||
|
||||
// Purchase Connector
|
||||
- (void)didReceivePurchaseRevenueValidationInfo:(NSDictionary *)validationInfo error:(NSError *)error {
|
||||
if (error != nil) {
|
||||
unityCallBack(onPurchaseValidationObjectName, PURCHASE_REVENUE_ERROR_CALLBACK, [[error localizedDescription] UTF8String]);
|
||||
} else {
|
||||
unityCallBack(onPurchaseValidationObjectName, PURCHASE_REVENUE_VALIDATION_CALLBACK, stringFromdictionary(validationInfo));
|
||||
}
|
||||
}
|
||||
|
||||
- (NSDictionary *)purchaseRevenueAdditionalParametersForProducts:(NSSet<SKProduct *> *)products
|
||||
transactions:(NSSet<SKPaymentTransaction *> *)transactions {
|
||||
|
||||
NSMutableArray *productsArray = [NSMutableArray array];
|
||||
for (SKProduct *product in products) {
|
||||
[productsArray addObject:@{
|
||||
@"productIdentifier": product.productIdentifier ?: @"",
|
||||
@"localizedTitle": product.localizedTitle ?: @"",
|
||||
@"localizedDescription": product.localizedDescription ?: @"",
|
||||
@"price": [product.price stringValue] ?: @""
|
||||
}];
|
||||
}
|
||||
|
||||
NSMutableArray *transactionsArray = [NSMutableArray array];
|
||||
for (SKPaymentTransaction *txn in transactions) {
|
||||
[transactionsArray addObject:@{
|
||||
@"transactionIdentifier": txn.transactionIdentifier ?: @"",
|
||||
@"transactionState": @(txn.transactionState),
|
||||
@"transactionDate": txn.transactionDate ? [@(txn.transactionDate.timeIntervalSince1970) stringValue] : @""
|
||||
}];
|
||||
}
|
||||
|
||||
NSDictionary *input = @{
|
||||
@"products": productsArray,
|
||||
@"transactions": transactionsArray
|
||||
};
|
||||
|
||||
NSError *error = nil;
|
||||
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:input options:0 error:&error];
|
||||
if (error || !jsonData) {
|
||||
NSLog(@"[AppsFlyer] Failed to serialize Unity purchase data: %@", error);
|
||||
return @{};
|
||||
}
|
||||
|
||||
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
|
||||
if (!jsonString || !UnityPurchasesGetAdditionalParamsCallback) {
|
||||
NSLog(@"[AppsFlyer] Unity callback not registered");
|
||||
return @{};
|
||||
}
|
||||
|
||||
const char *resultCStr = UnityPurchasesGetAdditionalParamsCallback([jsonString UTF8String], "");
|
||||
if (!resultCStr) {
|
||||
NSLog(@"[AppsFlyer] Unity callback returned null");
|
||||
return @{};
|
||||
}
|
||||
|
||||
NSString *resultJson = [NSString stringWithUTF8String:resultCStr];
|
||||
NSData *resultData = [resultJson dataUsingEncoding:NSUTF8StringEncoding];
|
||||
NSDictionary *parsedResult = [NSJSONSerialization JSONObjectWithData:resultData options:0 error:&error];
|
||||
|
||||
if (error || ![parsedResult isKindOfClass:[NSDictionary class]]) {
|
||||
NSLog(@"[AppsFlyer] Failed to parse Unity response: %@", error);
|
||||
return @{};
|
||||
}
|
||||
|
||||
return parsedResult;
|
||||
}
|
||||
|
||||
#pragma mark - AppsFlyerPurchaseRevenueDataSourceStoreKit2
|
||||
- (NSDictionary *)purchaseRevenueAdditionalParametersStoreKit2ForProducts:(NSSet<AFSDKProductSK2 *> *)products transactions:(NSSet<AFSDKTransactionSK2 *> *)transactions {
|
||||
if (@available(iOS 15.0, *)) {
|
||||
NSArray *productInfoArray = [AFUnityStoreKit2Bridge extractSK2ProductInfo:[products allObjects]];
|
||||
NSArray *transactionInfoArray = [AFUnityStoreKit2Bridge extractSK2TransactionInfo:[transactions allObjects]];
|
||||
|
||||
NSDictionary *input = @{
|
||||
@"products": productInfoArray,
|
||||
@"transactions": transactionInfoArray
|
||||
};
|
||||
|
||||
if (UnityPurchasesGetAdditionalParamsCallbackSK2) {
|
||||
NSError *error = nil;
|
||||
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:input options:0 error:&error];
|
||||
if (error || !jsonData) {
|
||||
NSLog(@"[AppsFlyer] Failed to serialize Unity purchase data: %@", error);
|
||||
return @{};
|
||||
}
|
||||
|
||||
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
|
||||
|
||||
const char *resultCStr = UnityPurchasesGetAdditionalParamsCallbackSK2([jsonString UTF8String], "");
|
||||
if (!resultCStr) {
|
||||
NSLog(@"[AppsFlyer] Unity callback returned null");
|
||||
return @{};
|
||||
}
|
||||
|
||||
NSString *resultJson = [NSString stringWithUTF8String:resultCStr];
|
||||
|
||||
NSData *resultData = [resultJson dataUsingEncoding:NSUTF8StringEncoding];
|
||||
NSDictionary *parsedResult = [NSJSONSerialization JSONObjectWithData:resultData options:0 error:&error];
|
||||
|
||||
if (error || ![parsedResult isKindOfClass:[NSDictionary class]]) {
|
||||
NSLog(@"[AppsFlyer] Failed to parse Unity response: %@", error);
|
||||
return @{};
|
||||
}
|
||||
|
||||
return parsedResult;
|
||||
} else {
|
||||
NSLog(@"[AppsFlyer] SK2 - Unity callback is NOT registered");
|
||||
}
|
||||
} else {
|
||||
NSLog(@"[AppsFlyer] SK2 - iOS version not supported");
|
||||
}
|
||||
return @{};
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
37
Assets/AppsFlyer/Plugins/iOS/AppsFlyeriOSWrapper.mm.meta
Normal file
37
Assets/AppsFlyer/Plugins/iOS/AppsFlyeriOSWrapper.mm.meta
Normal file
@@ -0,0 +1,37 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2bff3788f3d8747fe9679bd3818e1d76
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
- first:
|
||||
iPhone: iOS
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
tvOS: tvOS
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
184
Assets/AppsFlyer/ProductPurchase.cs
Normal file
184
Assets/AppsFlyer/ProductPurchase.cs
Normal file
@@ -0,0 +1,184 @@
|
||||
#nullable enable
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
[System.Serializable]
|
||||
public class InAppPurchaseValidationResult : EventArgs
|
||||
{
|
||||
public bool success;
|
||||
public ProductPurchase? productPurchase;
|
||||
public ValidationFailureData? failureData;
|
||||
public string? token;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class ProductPurchase
|
||||
{
|
||||
public string? kind;
|
||||
public string? purchaseTimeMillis;
|
||||
public int purchaseState;
|
||||
public int consumptionState;
|
||||
public string? developerPayload;
|
||||
public string? orderId;
|
||||
public int purchaseType;
|
||||
public int acknowledgementState;
|
||||
public string? purchaseToken;
|
||||
public string? productId;
|
||||
public int quantity;
|
||||
public string? obfuscatedExternalAccountId;
|
||||
public string? obfuscatedExternalProfil;
|
||||
public string? regionCode;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class ValidationFailureData
|
||||
{
|
||||
public int status;
|
||||
public string? description;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class SubscriptionValidationResult
|
||||
{
|
||||
public bool success;
|
||||
public SubscriptionPurchase? subscriptionPurchase;
|
||||
public ValidationFailureData? failureData;
|
||||
public string? token;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class SubscriptionPurchase
|
||||
{
|
||||
public string? acknowledgementState;
|
||||
public CanceledStateContext? canceledStateContext;
|
||||
public ExternalAccountIdentifiers? externalAccountIdentifiers;
|
||||
public string? kind;
|
||||
public string? latestOrderId;
|
||||
public List<SubscriptionPurchaseLineItem>? lineItems;
|
||||
public string? linkedPurchaseToken;
|
||||
public PausedStateContext? pausedStateContext;
|
||||
public string? regionCode;
|
||||
public string? startTime;
|
||||
public SubscribeWithGoogleInfo? subscribeWithGoogleInfo;
|
||||
public string? subscriptionState;
|
||||
public TestPurchase? testPurchase;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class CanceledStateContext
|
||||
{
|
||||
public DeveloperInitiatedCancellation? developerInitiatedCancellation;
|
||||
public ReplacementCancellation? replacementCancellation;
|
||||
public SystemInitiatedCancellation? systemInitiatedCancellation;
|
||||
public UserInitiatedCancellation? userInitiatedCancellation;
|
||||
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class ExternalAccountIdentifiers
|
||||
{
|
||||
public string? externalAccountId;
|
||||
public string? obfuscatedExternalAccountId;
|
||||
public string? obfuscatedExternalProfileId;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class SubscriptionPurchaseLineItem
|
||||
{
|
||||
public AutoRenewingPlan? autoRenewingPlan;
|
||||
public DeferredItemReplacement? deferredItemReplacement;
|
||||
public string? expiryTime;
|
||||
public OfferDetails? offerDetails;
|
||||
public PrepaidPlan? prepaidPlan;
|
||||
public string? productId;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class PausedStateContext
|
||||
{
|
||||
public string? autoResumeTime;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class SubscribeWithGoogleInfo
|
||||
{
|
||||
public string? emailAddress;
|
||||
public string? familyName;
|
||||
public string? givenName;
|
||||
public string? profileId;
|
||||
public string? profileName;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class TestPurchase{}
|
||||
|
||||
[System.Serializable]
|
||||
public class DeveloperInitiatedCancellation{}
|
||||
|
||||
[System.Serializable]
|
||||
public class ReplacementCancellation{}
|
||||
|
||||
[System.Serializable]
|
||||
public class SystemInitiatedCancellation{}
|
||||
|
||||
[System.Serializable]
|
||||
public class UserInitiatedCancellation
|
||||
{
|
||||
public CancelSurveyResult? cancelSurveyResult;
|
||||
public string? cancelTime;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class AutoRenewingPlan
|
||||
{
|
||||
public string? autoRenewEnabled;
|
||||
public SubscriptionItemPriceChangeDetails? priceChangeDetails;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class DeferredItemReplacement
|
||||
{
|
||||
public string? productId;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class OfferDetails
|
||||
{
|
||||
public List<string>? offerTags;
|
||||
public string? basePlanId;
|
||||
public string? offerId;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class PrepaidPlan
|
||||
{
|
||||
public string? allowExtendAfterTime;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class CancelSurveyResult
|
||||
{
|
||||
public string? reason;
|
||||
public string? reasonUserInput;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class SubscriptionItemPriceChangeDetails
|
||||
{
|
||||
public string? expectedNewPriceChargeTime;
|
||||
public Money? newPrice;
|
||||
public string? priceChangeMode;
|
||||
public string? priceChangeState;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class Money
|
||||
{
|
||||
public string? currencyCode;
|
||||
public long nanos;
|
||||
public long units;
|
||||
}
|
||||
|
||||
11
Assets/AppsFlyer/ProductPurchase.cs.meta
Normal file
11
Assets/AppsFlyer/ProductPurchase.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9a1435104a69d4c8ebcc6f237cc29a54
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/AppsFlyer/Windows.meta
Normal file
8
Assets/AppsFlyer/Windows.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1fbfcb6aeaa7f40e69a0daff450a2450
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/AppsFlyer/Windows/AppsFlyerLib.pri
Normal file
BIN
Assets/AppsFlyer/Windows/AppsFlyerLib.pri
Normal file
Binary file not shown.
7
Assets/AppsFlyer/Windows/AppsFlyerLib.pri.meta
Normal file
7
Assets/AppsFlyer/Windows/AppsFlyerLib.pri.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c621896ec81267f478e98555031271ef
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/AppsFlyer/Windows/AppsFlyerLib.winmd
Normal file
BIN
Assets/AppsFlyer/Windows/AppsFlyerLib.winmd
Normal file
Binary file not shown.
38
Assets/AppsFlyer/Windows/AppsFlyerLib.winmd.meta
Normal file
38
Assets/AppsFlyer/Windows/AppsFlyerLib.winmd.meta
Normal file
@@ -0,0 +1,38 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5186898c6f4665f438e46763d4cff3ae
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
- first:
|
||||
Windows Store Apps: WindowsStoreApps
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
XboxOne: XboxOne
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
145
Assets/AppsFlyer/Windows/AppsFlyerWindows.cs
Normal file
145
Assets/AppsFlyer/Windows/AppsFlyerWindows.cs
Normal file
@@ -0,0 +1,145 @@
|
||||
//#define AFSDK_WIN_DEBUG
|
||||
//#define UNITY_WSA_10_0
|
||||
//#define ENABLE_WINMD_SUPPORT
|
||||
|
||||
#if UNITY_WSA_10_0
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.ComponentModel;
|
||||
using UnityEngine;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#if ENABLE_WINMD_SUPPORT
|
||||
using AppsFlyerLib;
|
||||
#endif
|
||||
|
||||
namespace AppsFlyerSDK
|
||||
{
|
||||
public class AppsFlyerWindows
|
||||
{
|
||||
#if ENABLE_WINMD_SUPPORT
|
||||
static private MonoBehaviour _gameObject = null;
|
||||
#endif
|
||||
|
||||
public static void InitSDK(string devKey, string appId, MonoBehaviour gameObject)
|
||||
{
|
||||
#if ENABLE_WINMD_SUPPORT
|
||||
|
||||
#if AFSDK_WIN_DEBUG
|
||||
// Remove callstack
|
||||
Application.SetStackTraceLogType(LogType.Log, StackTraceLogType.None);
|
||||
#endif
|
||||
Log("[InitSDK]: devKey: {0}, appId: {1}, gameObject: {2}", devKey, appId, gameObject == null ? "null" : gameObject.ToString());
|
||||
AppsFlyerTracker tracker = AppsFlyerTracker.GetAppsFlyerTracker();
|
||||
tracker.devKey = devKey;
|
||||
tracker.appId = appId;
|
||||
// Interface
|
||||
_gameObject = gameObject;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static string GetAppsFlyerId()
|
||||
{
|
||||
#if ENABLE_WINMD_SUPPORT
|
||||
Log("[GetAppsFlyerId]");
|
||||
return AppsFlyerTracker.GetAppsFlyerTracker().GetAppsFlyerUID();
|
||||
#else
|
||||
return "";
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void SetCustomerUserId(string customerUserId)
|
||||
{
|
||||
#if ENABLE_WINMD_SUPPORT
|
||||
Log("[SetCustomerUserId] customerUserId: {0}", customerUserId);
|
||||
if (customerUserId.Contains("test_device:"))
|
||||
{
|
||||
string testDeviceId = customerUserId.Substring(12);
|
||||
AppsFlyerTracker.GetAppsFlyerTracker().testDeviceId = testDeviceId;
|
||||
}
|
||||
AppsFlyerTracker.GetAppsFlyerTracker().customerUserId = customerUserId;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void Start()
|
||||
{
|
||||
#if ENABLE_WINMD_SUPPORT
|
||||
Log("[Start]");
|
||||
AppsFlyerTracker.GetAppsFlyerTracker().TrackAppLaunchAsync(Callback);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ENABLE_WINMD_SUPPORT
|
||||
public static void Callback(AppsFlyerLib.ServerStatusCode code)
|
||||
{
|
||||
Log("[Callback]: {0}", code.ToString());
|
||||
|
||||
AppsFlyerRequestEventArgs eventArgs = new AppsFlyerRequestEventArgs((int)code, code.ToString());
|
||||
if (_gameObject != null) {
|
||||
var method = _gameObject.GetType().GetMethod("AppsFlyerOnRequestResponse");
|
||||
if (method != null) {
|
||||
method.Invoke(_gameObject, new object[] { AppsFlyerTracker.GetAppsFlyerTracker(), eventArgs });
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public static void LogEvent(string eventName, Dictionary<string, string> eventValues)
|
||||
{
|
||||
#if ENABLE_WINMD_SUPPORT
|
||||
if (eventValues == null)
|
||||
{
|
||||
eventValues = new Dictionary<string, string>();
|
||||
}
|
||||
IDictionary<string, object> result = new Dictionary<string, object>();
|
||||
foreach (KeyValuePair<string, string> kvp in eventValues)
|
||||
{
|
||||
result.Add(kvp.Key.ToString(), kvp.Value);
|
||||
}
|
||||
|
||||
Log("[LogEvent]: eventName: {0} result: {1}", eventName, result.ToString());
|
||||
|
||||
AppsFlyerTracker tracker = AppsFlyerTracker.GetAppsFlyerTracker();
|
||||
tracker.TrackEvent(eventName, result);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
public static void GetConversionData(string _reserved)
|
||||
{
|
||||
#if ENABLE_WINMD_SUPPORT
|
||||
Task.Run(async () =>
|
||||
{
|
||||
AppsFlyerLib.AppsFlyerTracker tracker = AppsFlyerLib.AppsFlyerTracker.GetAppsFlyerTracker();
|
||||
string conversionData = await tracker.GetConversionDataAsync();
|
||||
|
||||
IAppsFlyerConversionData conversionDataHandler = _gameObject as IAppsFlyerConversionData;
|
||||
|
||||
if (conversionDataHandler != null)
|
||||
{
|
||||
Log("[GetConversionData] Will call `onConversionDataSuccess` with: {0}", conversionData);
|
||||
conversionDataHandler.onConversionDataSuccess(conversionData);
|
||||
} else {
|
||||
Log("[GetConversionData] Object with `IAppsFlyerConversionData` interface not found! Check `InitSDK` implementation");
|
||||
}
|
||||
// _gameObject.GetType().GetMethod("onConversionDataSuccess").Invoke(_gameObject, new[] { conversionData });
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
private static void Log(string format, params string[] args)
|
||||
{
|
||||
#if AFSDK_WIN_DEBUG
|
||||
#if ENABLE_WINMD_SUPPORT
|
||||
Debug.Log("AF_UNITY_WSA_10_0" + String.Format(format, args));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
11
Assets/AppsFlyer/Windows/AppsFlyerWindows.cs.meta
Normal file
11
Assets/AppsFlyer/Windows/AppsFlyerWindows.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 034d11e52b599954181d7f08c0d89ca8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/AppsFlyer/package.json
Normal file
8
Assets/AppsFlyer/package.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "appsflyer-unity-plugin",
|
||||
"displayName": "AppsFlyer",
|
||||
"description": "AppsFlyer Unity plugin",
|
||||
"version": "6.17.91",
|
||||
"unity": "2019.4",
|
||||
"license": "MIT"
|
||||
}
|
||||
7
Assets/AppsFlyer/package.json.meta
Normal file
7
Assets/AppsFlyer/package.json.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a2b3ab5da7dda473b8791503604647b4
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
10
Assets/CrystalFramework.meta
Normal file
10
Assets/CrystalFramework.meta
Normal file
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6880507913a57f545843f7e5b2412e6a
|
||||
folderAsset: yes
|
||||
timeCreated: 1541820628
|
||||
licenseType: Store
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/CrystalFramework/Utility.meta
Normal file
8
Assets/CrystalFramework/Utility.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b45c7b45c9256a745978ed0eb3cf5663
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
233
Assets/CrystalFramework/Utility/SafeArea.cs
Normal file
233
Assets/CrystalFramework/Utility/SafeArea.cs
Normal file
@@ -0,0 +1,233 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Crystal
|
||||
{
|
||||
/// <summary>
|
||||
/// Safe area implementation for notched mobile devices. Usage:
|
||||
/// (1) Add this component to the top level of any GUI panel.
|
||||
/// (2) If the panel uses a full screen background image, then create an immediate child and put the component on that instead, with all other elements childed below it.
|
||||
/// This will allow the background image to stretch to the full extents of the screen behind the notch, which looks nicer.
|
||||
/// (3) For other cases that use a mixture of full horizontal and vertical background stripes, use the Conform X & Y controls on separate elements as needed.
|
||||
/// </summary>
|
||||
public class SafeArea : MonoBehaviour
|
||||
{
|
||||
#region Simulations
|
||||
/// <summary>
|
||||
/// Simulation device that uses safe area due to a physical notch or software home bar. For use in Editor only.
|
||||
/// </summary>
|
||||
public enum SimDevice
|
||||
{
|
||||
/// <summary>
|
||||
/// Don't use a simulated safe area - GUI will be full screen as normal.
|
||||
/// </summary>
|
||||
None,
|
||||
/// <summary>
|
||||
/// Simulate the iPhone X and Xs (identical safe areas).
|
||||
/// </summary>
|
||||
iPhoneX,
|
||||
/// <summary>
|
||||
/// Simulate the iPhone Xs Max and XR (identical safe areas).
|
||||
/// </summary>
|
||||
iPhoneXsMax,
|
||||
/// <summary>
|
||||
/// Simulate the Google Pixel 3 XL using landscape left.
|
||||
/// </summary>
|
||||
Pixel3XL_LSL,
|
||||
/// <summary>
|
||||
/// Simulate the Google Pixel 3 XL using landscape right.
|
||||
/// </summary>
|
||||
Pixel3XL_LSR
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simulation mode for use in editor only. This can be edited at runtime to toggle between different safe areas.
|
||||
/// </summary>
|
||||
public static SimDevice Sim = SimDevice.None;
|
||||
|
||||
/// <summary>
|
||||
/// Normalised safe areas for iPhone X with Home indicator (ratios are identical to Xs, 11 Pro). Absolute values:
|
||||
/// PortraitU x=0, y=102, w=1125, h=2202 on full extents w=1125, h=2436;
|
||||
/// PortraitD x=0, y=102, w=1125, h=2202 on full extents w=1125, h=2436 (not supported, remains in Portrait Up);
|
||||
/// LandscapeL x=132, y=63, w=2172, h=1062 on full extents w=2436, h=1125;
|
||||
/// LandscapeR x=132, y=63, w=2172, h=1062 on full extents w=2436, h=1125.
|
||||
/// Aspect Ratio: ~19.5:9.
|
||||
/// </summary>
|
||||
Rect[] NSA_iPhoneX = new Rect[]
|
||||
{
|
||||
new Rect (0f, 102f / 2436f, 1f, 2202f / 2436f), // Portrait
|
||||
new Rect (132f / 2436f, 63f / 1125f, 2172f / 2436f, 1062f / 1125f) // Landscape
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Normalised safe areas for iPhone Xs Max with Home indicator (ratios are identical to XR, 11, 11 Pro Max). Absolute values:
|
||||
/// PortraitU x=0, y=102, w=1242, h=2454 on full extents w=1242, h=2688;
|
||||
/// PortraitD x=0, y=102, w=1242, h=2454 on full extents w=1242, h=2688 (not supported, remains in Portrait Up);
|
||||
/// LandscapeL x=132, y=63, w=2424, h=1179 on full extents w=2688, h=1242;
|
||||
/// LandscapeR x=132, y=63, w=2424, h=1179 on full extents w=2688, h=1242.
|
||||
/// Aspect Ratio: ~19.5:9.
|
||||
/// </summary>
|
||||
Rect[] NSA_iPhoneXsMax = new Rect[]
|
||||
{
|
||||
new Rect (0f, 102f / 2688f, 1f, 2454f / 2688f), // Portrait
|
||||
new Rect (132f / 2688f, 63f / 1242f, 2424f / 2688f, 1179f / 1242f) // Landscape
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Normalised safe areas for Pixel 3 XL using landscape left. Absolute values:
|
||||
/// PortraitU x=0, y=0, w=1440, h=2789 on full extents w=1440, h=2960;
|
||||
/// PortraitD x=0, y=0, w=1440, h=2789 on full extents w=1440, h=2960;
|
||||
/// LandscapeL x=171, y=0, w=2789, h=1440 on full extents w=2960, h=1440;
|
||||
/// LandscapeR x=0, y=0, w=2789, h=1440 on full extents w=2960, h=1440.
|
||||
/// Aspect Ratio: 18.5:9.
|
||||
/// </summary>
|
||||
Rect[] NSA_Pixel3XL_LSL = new Rect[]
|
||||
{
|
||||
new Rect (0f, 0f, 1f, 2789f / 2960f), // Portrait
|
||||
new Rect (0f, 0f, 2789f / 2960f, 1f) // Landscape
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Normalised safe areas for Pixel 3 XL using landscape right. Absolute values and aspect ratio same as above.
|
||||
/// </summary>
|
||||
Rect[] NSA_Pixel3XL_LSR = new Rect[]
|
||||
{
|
||||
new Rect (0f, 0f, 1f, 2789f / 2960f), // Portrait
|
||||
new Rect (171f / 2960f, 0f, 2789f / 2960f, 1f) // Landscape
|
||||
};
|
||||
#endregion
|
||||
|
||||
RectTransform Panel;
|
||||
Rect LastSafeArea = new Rect (0, 0, 0, 0);
|
||||
Vector2Int LastScreenSize = new Vector2Int (0, 0);
|
||||
ScreenOrientation LastOrientation = ScreenOrientation.AutoRotation;
|
||||
[SerializeField] bool ConformX = true; // Conform to screen safe area on X-axis (default true, disable to ignore)
|
||||
[SerializeField] bool ConformY = true; // Conform to screen safe area on Y-axis (default true, disable to ignore)
|
||||
[SerializeField] bool Logging = false; // Conform to screen safe area on Y-axis (default true, disable to ignore)
|
||||
|
||||
void Awake ()
|
||||
{
|
||||
Panel = GetComponent<RectTransform> ();
|
||||
|
||||
if (Panel == null)
|
||||
{
|
||||
Debug.LogError ("Cannot apply safe area - no RectTransform found on " + name);
|
||||
Destroy (gameObject);
|
||||
}
|
||||
|
||||
Refresh ();
|
||||
}
|
||||
|
||||
void Update ()
|
||||
{
|
||||
Refresh ();
|
||||
}
|
||||
|
||||
void Refresh ()
|
||||
{
|
||||
Rect safeArea = GetSafeArea ();
|
||||
|
||||
if (safeArea != LastSafeArea
|
||||
|| Screen.width != LastScreenSize.x
|
||||
|| Screen.height != LastScreenSize.y
|
||||
|| Screen.orientation != LastOrientation)
|
||||
{
|
||||
// Fix for having auto-rotate off and manually forcing a screen orientation.
|
||||
// See https://forum.unity.com/threads/569236/#post-4473253 and https://forum.unity.com/threads/569236/page-2#post-5166467
|
||||
LastScreenSize.x = Screen.width;
|
||||
LastScreenSize.y = Screen.height;
|
||||
LastOrientation = Screen.orientation;
|
||||
|
||||
ApplySafeArea (safeArea);
|
||||
}
|
||||
}
|
||||
|
||||
Rect GetSafeArea ()
|
||||
{
|
||||
Rect safeArea = Screen.safeArea;
|
||||
|
||||
if (Application.isEditor && Sim != SimDevice.None)
|
||||
{
|
||||
Rect nsa = new Rect (0, 0, Screen.width, Screen.height);
|
||||
|
||||
switch (Sim)
|
||||
{
|
||||
case SimDevice.iPhoneX:
|
||||
if (Screen.height > Screen.width) // Portrait
|
||||
nsa = NSA_iPhoneX[0];
|
||||
else // Landscape
|
||||
nsa = NSA_iPhoneX[1];
|
||||
break;
|
||||
case SimDevice.iPhoneXsMax:
|
||||
if (Screen.height > Screen.width) // Portrait
|
||||
nsa = NSA_iPhoneXsMax[0];
|
||||
else // Landscape
|
||||
nsa = NSA_iPhoneXsMax[1];
|
||||
break;
|
||||
case SimDevice.Pixel3XL_LSL:
|
||||
if (Screen.height > Screen.width) // Portrait
|
||||
nsa = NSA_Pixel3XL_LSL[0];
|
||||
else // Landscape
|
||||
nsa = NSA_Pixel3XL_LSL[1];
|
||||
break;
|
||||
case SimDevice.Pixel3XL_LSR:
|
||||
if (Screen.height > Screen.width) // Portrait
|
||||
nsa = NSA_Pixel3XL_LSR[0];
|
||||
else // Landscape
|
||||
nsa = NSA_Pixel3XL_LSR[1];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
safeArea = new Rect (Screen.width * nsa.x, Screen.height * nsa.y, Screen.width * nsa.width, Screen.height * nsa.height);
|
||||
}
|
||||
|
||||
return safeArea;
|
||||
}
|
||||
|
||||
void ApplySafeArea (Rect r)
|
||||
{
|
||||
LastSafeArea = r;
|
||||
|
||||
// Ignore x-axis?
|
||||
if (!ConformX)
|
||||
{
|
||||
r.x = 0;
|
||||
r.width = Screen.width;
|
||||
}
|
||||
|
||||
// Ignore y-axis?
|
||||
if (!ConformY)
|
||||
{
|
||||
r.y = 0;
|
||||
r.height = Screen.height;
|
||||
}
|
||||
|
||||
// Check for invalid screen startup state on some Samsung devices (see below)
|
||||
if (Screen.width > 0 && Screen.height > 0)
|
||||
{
|
||||
// Convert safe area rectangle from absolute pixels to normalised anchor coordinates
|
||||
Vector2 anchorMin = r.position;
|
||||
Vector2 anchorMax = r.position + r.size;
|
||||
anchorMin.x /= Screen.width;
|
||||
anchorMin.y /= Screen.height;
|
||||
anchorMax.x /= Screen.width;
|
||||
anchorMax.y /= Screen.height;
|
||||
|
||||
// Fix for some Samsung devices (e.g. Note 10+, A71, S20) where Refresh gets called twice and the first time returns NaN anchor coordinates
|
||||
// See https://forum.unity.com/threads/569236/page-2#post-6199352
|
||||
if (anchorMin.x >= 0 && anchorMin.y >= 0 && anchorMax.x >= 0 && anchorMax.y >= 0)
|
||||
{
|
||||
Panel.anchorMin = anchorMin;
|
||||
Panel.anchorMax = anchorMax;
|
||||
}
|
||||
}
|
||||
|
||||
if (Logging)
|
||||
{
|
||||
Debug.LogFormat ("New safe area applied to {0}: x={1}, y={2}, w={3}, h={4} on full extents w={5}, h={6}",
|
||||
name, r.x, r.y, r.width, r.height, Screen.width, Screen.height);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
18
Assets/CrystalFramework/Utility/SafeArea.cs.meta
Normal file
18
Assets/CrystalFramework/Utility/SafeArea.cs.meta
Normal file
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c97afc556caea1c44969477eb7ddec74
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 130488
|
||||
packageName: Safe Area Helper
|
||||
packageVersion: 1.0.6
|
||||
assetPath: Assets/CrystalFramework/Utility/SafeArea.cs
|
||||
uploadId: 898916
|
||||
390
Assets/CrystalFramework/Utility/SafeArea.rtf
Normal file
390
Assets/CrystalFramework/Utility/SafeArea.rtf
Normal file
@@ -0,0 +1,390 @@
|
||||
{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff0\deff0\stshfdbch31505\stshfloch31506\stshfhich31506\stshfbi0\deflang3081\deflangfe1041\themelang3081\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f34\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria Math;}
|
||||
{\f37\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\f38\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0302020204030204}Calibri Light;}{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
|
||||
{\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhimajor\f31502\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0302020204030204}Calibri Light;}
|
||||
{\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
|
||||
{\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}
|
||||
{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f49\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f50\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
|
||||
{\f52\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f53\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f54\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f55\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
|
||||
{\f56\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f57\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f59\fbidi \froman\fcharset238\fprq2 Cambria Math CE;}{\f60\fbidi \froman\fcharset204\fprq2 Cambria Math Cyr;}
|
||||
{\f62\fbidi \froman\fcharset161\fprq2 Cambria Math Greek;}{\f63\fbidi \froman\fcharset162\fprq2 Cambria Math Tur;}{\f66\fbidi \froman\fcharset186\fprq2 Cambria Math Baltic;}{\f67\fbidi \froman\fcharset163\fprq2 Cambria Math (Vietnamese);}
|
||||
{\f69\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\f70\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\f72\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f73\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}
|
||||
{\f74\fbidi \fswiss\fcharset177\fprq2 Calibri (Hebrew);}{\f75\fbidi \fswiss\fcharset178\fprq2 Calibri (Arabic);}{\f76\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\f77\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}
|
||||
{\f79\fbidi \fswiss\fcharset238\fprq2 Calibri Light CE;}{\f80\fbidi \fswiss\fcharset204\fprq2 Calibri Light Cyr;}{\f82\fbidi \fswiss\fcharset161\fprq2 Calibri Light Greek;}{\f83\fbidi \fswiss\fcharset162\fprq2 Calibri Light Tur;}
|
||||
{\f84\fbidi \fswiss\fcharset177\fprq2 Calibri Light (Hebrew);}{\f85\fbidi \fswiss\fcharset178\fprq2 Calibri Light (Arabic);}{\f86\fbidi \fswiss\fcharset186\fprq2 Calibri Light Baltic;}{\f87\fbidi \fswiss\fcharset163\fprq2 Calibri Light (Vietnamese);}
|
||||
{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}
|
||||
{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
|
||||
{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}
|
||||
{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}
|
||||
{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}
|
||||
{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhimajor\f31528\fbidi \fswiss\fcharset238\fprq2 Calibri Light CE;}{\fhimajor\f31529\fbidi \fswiss\fcharset204\fprq2 Calibri Light Cyr;}
|
||||
{\fhimajor\f31531\fbidi \fswiss\fcharset161\fprq2 Calibri Light Greek;}{\fhimajor\f31532\fbidi \fswiss\fcharset162\fprq2 Calibri Light Tur;}{\fhimajor\f31533\fbidi \fswiss\fcharset177\fprq2 Calibri Light (Hebrew);}
|
||||
{\fhimajor\f31534\fbidi \fswiss\fcharset178\fprq2 Calibri Light (Arabic);}{\fhimajor\f31535\fbidi \fswiss\fcharset186\fprq2 Calibri Light Baltic;}{\fhimajor\f31536\fbidi \fswiss\fcharset163\fprq2 Calibri Light (Vietnamese);}
|
||||
{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}
|
||||
{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
|
||||
{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}
|
||||
{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}
|
||||
{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}
|
||||
{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
|
||||
{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
|
||||
{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}
|
||||
{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}
|
||||
{\fhiminor\f31573\fbidi \fswiss\fcharset177\fprq2 Calibri (Hebrew);}{\fhiminor\f31574\fbidi \fswiss\fcharset178\fprq2 Calibri (Arabic);}{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}
|
||||
{\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
|
||||
{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
|
||||
{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}}
|
||||
{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;
|
||||
\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;\red0\green0\blue0;\red0\green0\blue0;\red47\green84\blue150;\red5\green99\blue193;}{\*\defchp
|
||||
\fs24\kerning2\loch\af31506\hich\af31506\dbch\af31505 }{\*\defpap \ql \li0\ri0\sa160\sl278\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{\ql \li0\ri0\sa160\sl278\slmult1
|
||||
\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang3081\langfe1041\kerning2\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp3081\langfenp1041 \snext0 \sqformat \spriority0
|
||||
Normal;}{\s1\ql \li0\ri0\sb240\sa60\sl278\slmult1\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel0\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \ab\af0\afs32\alang1025 \ltrch\fcs0
|
||||
\b\fs32\lang3081\langfe1041\kerning32\loch\f31502\hich\af31502\dbch\af31501\cgrid\langnp3081\langfenp1041 \sbasedon0 \snext0 \slink15 \sqformat \spriority9 \styrsid2914631 heading 1;}{\s2\ql \li0\ri0\sb240\sa60\sl278\slmult1
|
||||
\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel1\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \ab\ai\af0\afs28\alang1025 \ltrch\fcs0 \b\i\fs28\lang3081\langfe1041\kerning2\loch\f31502\hich\af31502\dbch\af31501\cgrid\langnp3081\langfenp1041
|
||||
\sbasedon0 \snext0 \slink16 \sunhideused \sqformat \spriority9 \styrsid2914631 heading 2;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\*
|
||||
\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\sa160\sl278\slmult1
|
||||
\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang3081\langfe1041\kerning2\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp3081\langfenp1041
|
||||
\snext11 \ssemihidden \sunhideused Normal Table;}{\*\cs15 \additive \rtlch\fcs1 \ab\af0\afs32 \ltrch\fcs0 \b\fs32\kerning32\loch\f31502\hich\af31502\dbch\af31501 \sbasedon10 \slink1 \spriority9 \styrsid2914631 Heading 1 Char;}{\*\cs16 \additive
|
||||
\rtlch\fcs1 \ab\ai\af0\afs28 \ltrch\fcs0 \b\i\fs28\loch\f31502\hich\af31502\dbch\af31501 \sbasedon10 \slink2 \spriority9 \styrsid2914631 Heading 2 Char;}{\s17\ql \li0\ri0\sb240\sl259\slmult1
|
||||
\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs32\alang1025 \ltrch\fcs0 \fs32\cf19\lang1033\langfe1033\loch\f31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033
|
||||
\sbasedon1 \snext0 \sunhideused \sqformat \spriority39 \styrsid2914631 TOC Heading;}{\s18\ql \li0\ri0\sa160\sl278\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0
|
||||
\fs24\lang3081\langfe1041\kerning2\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp3081\langfenp1041 \sbasedon0 \snext0 \sautoupd \sunhideused \spriority39 \styrsid16206562 toc 1;}{\s19\ql \li240\ri0\sa160\sl278\slmult1
|
||||
\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin240\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang3081\langfe1041\kerning2\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp3081\langfenp1041
|
||||
\sbasedon0 \snext0 \sautoupd \sunhideused \spriority39 \styrsid16206562 toc 2;}{\*\cs20 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \ul\cf20 \sbasedon10 \sunhideused \styrsid16206562 Hyperlink;}}{\*\listtable{\list\listtemplateid-1\listhybrid{\listlevel
|
||||
\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\leveltemplateid201916431\'02\'00.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li720\lin720 }{\listlevel\levelnfc4\levelnfcn4\leveljc0
|
||||
\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid201916441\'02\'01.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li1440\lin1440 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2
|
||||
\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid201916443\'02\'02.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li2160\lin2160 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0
|
||||
\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid201916431\'02\'03.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li2880\lin2880 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1
|
||||
\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid201916441\'02\'04.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li3600\lin3600 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative
|
||||
\levelspace0\levelindent0{\leveltext\leveltemplateid201916443\'02\'05.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li4320\lin4320 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0
|
||||
\levelindent0{\leveltext\leveltemplateid201916431\'02\'06.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li5040\lin5040 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0
|
||||
{\leveltext\leveltemplateid201916441\'02\'07.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li5760\lin5760 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext
|
||||
\leveltemplateid201916443\'02\'08.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li6480\lin6480 }{\listname ;}\listid491986554}{\list\listtemplateid-1\listhybrid{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1
|
||||
\levelspace0\levelindent0{\leveltext\leveltemplateid201916431\'02\'00.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fbias0 \fi-360\li720\lin720 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0
|
||||
\levelindent0{\leveltext\leveltemplateid201916441\'02\'01.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li1440\lin1440 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0
|
||||
{\leveltext\leveltemplateid201916443\'02\'02.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li2160\lin2160 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext
|
||||
\leveltemplateid201916431\'02\'03.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li2880\lin2880 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext
|
||||
\leveltemplateid201916441\'02\'04.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li3600\lin3600 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext
|
||||
\leveltemplateid201916443\'02\'05.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li4320\lin4320 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext
|
||||
\leveltemplateid201916431\'02\'06.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li5040\lin5040 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext
|
||||
\leveltemplateid201916441\'02\'07.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li5760\lin5760 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext
|
||||
\leveltemplateid201916443\'02\'08.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li6480\lin6480 }{\listname ;}\listid622276423}{\list\listtemplateid-1\listhybrid{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1
|
||||
\levelspace0\levelindent0{\leveltext\leveltemplateid201916431\'02\'00.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fbias0 \fi-360\li720\lin720 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0
|
||||
\levelindent0{\leveltext\leveltemplateid201916441\'02\'01.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li1440\lin1440 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0
|
||||
{\leveltext\leveltemplateid201916443\'02\'02.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li2160\lin2160 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext
|
||||
\leveltemplateid201916431\'02\'03.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li2880\lin2880 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext
|
||||
\leveltemplateid201916441\'02\'04.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li3600\lin3600 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext
|
||||
\leveltemplateid201916443\'02\'05.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li4320\lin4320 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext
|
||||
\leveltemplateid201916431\'02\'06.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li5040\lin5040 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext
|
||||
\leveltemplateid201916441\'02\'07.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li5760\lin5760 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext
|
||||
\leveltemplateid201916443\'02\'08.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li6480\lin6480 }{\listname ;}\listid764233946}{\list\listtemplateid-1\listhybrid{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1
|
||||
\levelspace0\levelindent0{\leveltext\leveltemplateid201916431\'02\'00.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li720\lin720 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0
|
||||
\levelindent0{\leveltext\leveltemplateid201916441\'02\'01.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li1440\lin1440 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0
|
||||
{\leveltext\leveltemplateid201916443\'02\'02.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li2160\lin2160 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext
|
||||
\leveltemplateid201916431\'02\'03.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li2880\lin2880 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext
|
||||
\leveltemplateid201916441\'02\'04.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li3600\lin3600 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext
|
||||
\leveltemplateid201916443\'02\'05.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li4320\lin4320 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext
|
||||
\leveltemplateid201916431\'02\'06.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li5040\lin5040 }{\listlevel\levelnfc4\levelnfcn4\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext
|
||||
\leveltemplateid201916441\'02\'07.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-360\li5760\lin5760 }{\listlevel\levelnfc2\levelnfcn2\leveljc2\leveljcn2\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext
|
||||
\leveltemplateid201916443\'02\'08.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fi-180\li6480\lin6480 }{\listname ;}\listid1044137377}}{\*\listoverridetable{\listoverride\listid1044137377\listoverridecount0\ls1}{\listoverride\listid622276423
|
||||
\listoverridecount0\ls2}{\listoverride\listid491986554\listoverridecount0\ls3}{\listoverride\listid764233946\listoverridecount0\ls4}}{\*\rsidtbl \rsid1858992\rsid2914631\rsid4129176\rsid4542871\rsid5571476\rsid12976886\rsid16206562}{\mmathPr\mmathFont34
|
||||
\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\operator Matthew Ota}{\creatim\yr2026\mo4\dy12\hr21\min50}{\revtim\yr2026\mo4\dy12\hr21\min55}{\version5}{\edmins4}{\nofpages2}
|
||||
{\nofwords312}{\nofchars1780}{\nofcharsws2088}{\vern13}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}\paperw12240\paperh15840\margl1440\margr1440\margt1440\margb1440\gutter0\ltrsect
|
||||
\widowctrl\ftnbj\aenddoc\trackmoves0\trackformatting1\donotembedsysfont0\relyonvml0\donotembedlingdata1\grfdocevents0\validatexml0\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors0\horzdoc\dghspace120\dgvspace120\dghorigin1701
|
||||
\dgvorigin1984\dghshow0\dgvshow3\jcompress\viewkind1\viewscale100\rsidroot2914631 \fet0{\*\wgrffmtfilter 2450}\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2
|
||||
\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6
|
||||
\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang
|
||||
{\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\s17\ql \li0\ri0\sb240\sl259\slmult1\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs32\alang1025 \ltrch\fcs0
|
||||
\fs32\cf19\lang1033\langfe1033\loch\af31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid2914631 \hich\af31502\dbch\af31501\loch\f31502 Table of Contents
|
||||
\par }\pard\plain \ltrpar\s18\ql \li0\ri0\sa160\sl278\slmult1\widctlpar\tqr\tldot\tx9350\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0
|
||||
\fs24\lang3081\langfe1041\kerning2\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp3081\langfenp1041 {\field\fldedit{\*\fldinst {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid2914631 \hich\af31506\dbch\af31505\loch\f31506 TOC \\o "1-3" \\h \\z \\u }}{\fldrslt
|
||||
{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af0 \ltrch\fcs0 \cs20\ul\cf20\lang1024\langfe1024\noproof\insrsid1858992\charrsid283681 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1024\langfe1024\noproof\insrsid1858992
|
||||
\hich\af31506\dbch\af31505\loch\f31506 HYPERLINK \\l "_Toc226923347"}{\rtlch\fcs1 \af0 \ltrch\fcs0 \cs20\ul\cf20\lang1024\langfe1024\noproof\insrsid1858992\charrsid283681 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af0 \ltrch\fcs0
|
||||
\cs20\ul\cf20\lang1024\langfe1024\noproof\insrsid1858992\charrsid283681 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e0000005f0054006f0063003200320036003900320033003300340037000000}}}{\fldrslt {\rtlch\fcs1 \af0 \ltrch\fcs0
|
||||
\cs20\ul\cf20\lang1024\langfe1024\noproof\insrsid1858992\charrsid283681 \hich\af31506\dbch\af31505\loch\f31506 Safe Area Helper}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1024\langfe1024\noproof\webhidden\insrsid1858992 \tab }{\field{\*\fldinst {\rtlch\fcs1 \af0
|
||||
\ltrch\fcs0 \lang1024\langfe1024\noproof\webhidden\insrsid1858992 \hich\af31506\dbch\af31505\loch\f31506 \hich\af31506\dbch\af31505\loch\f31506 PAGEREF \hich\af31506\dbch\af31505\loch\f31506 _Toc226923347 \\h\hich\af31506\dbch\af31505\loch\f31506 }{
|
||||
\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1024\langfe1024\noproof\webhidden\insrsid1858992 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e0000005f0054006f0063003200320036003900320033003300340037000000}}}{\fldrslt {\rtlch\fcs1 \af0 \ltrch\fcs0
|
||||
\lang1024\langfe1024\noproof\webhidden\insrsid1858992 \hich\af31506\dbch\af31505\loch\f31506 1}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj }}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af31507 \ltrch\fcs0
|
||||
\lang1024\langfe1024\noproof\insrsid1858992
|
||||
\par }\pard\plain \ltrpar\s19\ql \li240\ri0\sa160\sl278\slmult1\widctlpar\tqr\tldot\tx9350\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin240\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0
|
||||
\fs24\lang3081\langfe1041\kerning2\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp3081\langfenp1041 {\field\fldedit{\*\fldinst {\rtlch\fcs1 \af0 \ltrch\fcs0 \cs20\ul\cf20\lang1024\langfe1024\noproof\insrsid1858992\charrsid283681
|
||||
\hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1024\langfe1024\noproof\insrsid1858992 \hich\af31506\dbch\af31505\loch\f31506 HYPERLINK \\l "_Toc226923348"}{\rtlch\fcs1 \af0 \ltrch\fcs0
|
||||
\cs20\ul\cf20\lang1024\langfe1024\noproof\insrsid1858992\charrsid283681 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af0 \ltrch\fcs0 \cs20\ul\cf20\lang1024\langfe1024\noproof\insrsid1858992\charrsid283681 {\*\datafield
|
||||
08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e0000005f0054006f0063003200320036003900320033003300340038000000}}}{\fldrslt {\rtlch\fcs1 \af0 \ltrch\fcs0 \cs20\ul\cf20\lang1024\langfe1024\noproof\insrsid1858992\charrsid283681
|
||||
\hich\af31506\dbch\af31505\loch\f31506 Usage}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1024\langfe1024\noproof\webhidden\insrsid1858992 \tab }{\field{\*\fldinst {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1024\langfe1024\noproof\webhidden\insrsid1858992
|
||||
\hich\af31506\dbch\af31505\loch\f31506 \hich\af31506\dbch\af31505\loch\f31506 PAGEREF \hich\af31506\dbch\af31505\loch\f31506 _Toc226923348 \\h\hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af0 \ltrch\fcs0
|
||||
\lang1024\langfe1024\noproof\webhidden\insrsid1858992 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e0000005f0054006f0063003200320036003900320033003300340038000000}}}{\fldrslt {\rtlch\fcs1 \af0 \ltrch\fcs0
|
||||
\lang1024\langfe1024\noproof\webhidden\insrsid1858992 \hich\af31506\dbch\af31505\loch\f31506 1}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj }}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af31507 \ltrch\fcs0
|
||||
\lang1024\langfe1024\noproof\insrsid1858992
|
||||
\par }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af0 \ltrch\fcs0 \cs20\ul\cf20\lang1024\langfe1024\noproof\insrsid1858992\charrsid283681 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1024\langfe1024\noproof\insrsid1858992
|
||||
\hich\af31506\dbch\af31505\loch\f31506 HYPERLINK \\l "_Toc226923349"}{\rtlch\fcs1 \af0 \ltrch\fcs0 \cs20\ul\cf20\lang1024\langfe1024\noproof\insrsid1858992\charrsid283681 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af0 \ltrch\fcs0
|
||||
\cs20\ul\cf20\lang1024\langfe1024\noproof\insrsid1858992\charrsid283681 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e0000005f0054006f0063003200320036003900320033003300340039000000}}}{\fldrslt {\rtlch\fcs1 \af0 \ltrch\fcs0
|
||||
\cs20\ul\cf20\lang1024\langfe1024\noproof\insrsid1858992\charrsid283681 \hich\af31506\dbch\af31505\loch\f31506 Add your own simulated devices}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1024\langfe1024\noproof\webhidden\insrsid1858992 \tab }{\field{\*\fldinst {
|
||||
\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1024\langfe1024\noproof\webhidden\insrsid1858992 \hich\af31506\dbch\af31505\loch\f31506 \hich\af31506\dbch\af31505\loch\f31506 PAGEREF \hich\af31506\dbch\af31505\loch\f31506 _Toc226923349 \\h
|
||||
\hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1024\langfe1024\noproof\webhidden\insrsid1858992 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e0000005f0054006f0063003200320036003900320033003300340039000000}}
|
||||
}{\fldrslt {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1024\langfe1024\noproof\webhidden\insrsid1858992 \hich\af31506\dbch\af31505\loch\f31506 1}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj }}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af31507
|
||||
\ltrch\fcs0 \lang1024\langfe1024\noproof\insrsid1858992
|
||||
\par }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af0 \ltrch\fcs0 \cs20\ul\cf20\lang1024\langfe1024\noproof\insrsid1858992\charrsid283681 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1024\langfe1024\noproof\insrsid1858992
|
||||
\hich\af31506\dbch\af31505\loch\f31506 HYPERLINK \\l "_Toc226923350"}{\rtlch\fcs1 \af0 \ltrch\fcs0 \cs20\ul\cf20\lang1024\langfe1024\noproof\insrsid1858992\charrsid283681 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af0 \ltrch\fcs0
|
||||
\cs20\ul\cf20\lang1024\langfe1024\noproof\insrsid1858992\charrsid283681 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e0000005f0054006f0063003200320036003900320033003300350030000000}}}{\fldrslt {\rtlch\fcs1 \af0 \ltrch\fcs0
|
||||
\cs20\ul\cf20\lang1024\langfe1024\noproof\insrsid1858992\charrsid283681 \hich\af31506\dbch\af31505\loch\f31506 Other notes and suggestions}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1024\langfe1024\noproof\webhidden\insrsid1858992 \tab }{\field{\*\fldinst {
|
||||
\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1024\langfe1024\noproof\webhidden\insrsid1858992 \hich\af31506\dbch\af31505\loch\f31506 \hich\af31506\dbch\af31505\loch\f31506 PAGEREF \hich\af31506\dbch\af31505\loch\f31506 _Toc226923350 \\h
|
||||
\hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1024\langfe1024\noproof\webhidden\insrsid1858992 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e0000005f0054006f0063003200320036003900320033003300350030000000}}
|
||||
}{\fldrslt {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1024\langfe1024\noproof\webhidden\insrsid1858992 \hich\af31506\dbch\af31505\loch\f31506 2}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj }}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af31507
|
||||
\ltrch\fcs0 \lang1024\langfe1024\noproof\insrsid1858992
|
||||
\par }\pard\plain \ltrpar\s18\ql \li0\ri0\sa160\sl278\slmult1\widctlpar\tqr\tldot\tx9350\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0
|
||||
\fs24\lang3081\langfe1041\kerning2\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp3081\langfenp1041 {\field\fldedit{\*\fldinst {\rtlch\fcs1 \af0 \ltrch\fcs0 \cs20\ul\cf20\lang1024\langfe1024\noproof\insrsid1858992\charrsid283681
|
||||
\hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1024\langfe1024\noproof\insrsid1858992 \hich\af31506\dbch\af31505\loch\f31506 HYPERLINK \\l "_Toc226923351"}{\rtlch\fcs1 \af0 \ltrch\fcs0
|
||||
\cs20\ul\cf20\lang1024\langfe1024\noproof\insrsid1858992\charrsid283681 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af0 \ltrch\fcs0 \cs20\ul\cf20\lang1024\langfe1024\noproof\insrsid1858992\charrsid283681 {\*\datafield
|
||||
08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e0000005f0054006f0063003200320036003900320033003300350031000000}}}{\fldrslt {\rtlch\fcs1 \af0 \ltrch\fcs0 \cs20\ul\cf20\lang1024\langfe1024\noproof\insrsid1858992\charrsid283681
|
||||
\hich\af31506\dbch\af31505\loch\f31506 Version History}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1024\langfe1024\noproof\webhidden\insrsid1858992 \tab }{\field{\*\fldinst {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1024\langfe1024\noproof\webhidden\insrsid1858992
|
||||
\hich\af31506\dbch\af31505\loch\f31506 \hich\af31506\dbch\af31505\loch\f31506 PAGEREF \hich\af31506\dbch\af31505\loch\f31506 _Toc226923351 \\h\hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af0 \ltrch\fcs0
|
||||
\lang1024\langfe1024\noproof\webhidden\insrsid1858992 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e0000005f0054006f0063003200320036003900320033003300350031000000}}}{\fldrslt {\rtlch\fcs1 \af0 \ltrch\fcs0
|
||||
\lang1024\langfe1024\noproof\webhidden\insrsid1858992 \hich\af31506\dbch\af31505\loch\f31506 2}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj }}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af31507 \ltrch\fcs0
|
||||
\lang1024\langfe1024\noproof\insrsid1858992
|
||||
\par }\pard\plain \ltrpar\s19\ql \li240\ri0\sa160\sl278\slmult1\widctlpar\tqr\tldot\tx9350\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin240\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0
|
||||
\fs24\lang3081\langfe1041\kerning2\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp3081\langfenp1041 {\field\fldedit{\*\fldinst {\rtlch\fcs1 \af0 \ltrch\fcs0 \cs20\ul\cf20\lang1024\langfe1024\noproof\insrsid1858992\charrsid283681
|
||||
\hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1024\langfe1024\noproof\insrsid1858992 \hich\af31506\dbch\af31505\loch\f31506 HYPERLINK \\l "_Toc226923352"}{\rtlch\fcs1 \af0 \ltrch\fcs0
|
||||
\cs20\ul\cf20\lang1024\langfe1024\noproof\insrsid1858992\charrsid283681 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af0 \ltrch\fcs0 \cs20\ul\cf20\lang1024\langfe1024\noproof\insrsid1858992\charrsid283681 {\*\datafield
|
||||
08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e0000005f0054006f0063003200320036003900320033003300350032000000}}}{\fldrslt {\rtlch\fcs1 \af0 \ltrch\fcs0 \cs20\ul\cf20\lang1024\langfe1024\noproof\insrsid1858992\charrsid283681
|
||||
\hich\af31506\dbch\af31505\loch\f31506 v1.0.8}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1024\langfe1024\noproof\webhidden\insrsid1858992 \tab }{\field{\*\fldinst {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1024\langfe1024\noproof\webhidden\insrsid1858992
|
||||
\hich\af31506\dbch\af31505\loch\f31506 \hich\af31506\dbch\af31505\loch\f31506 PAGEREF \hich\af31506\dbch\af31505\loch\f31506 _Toc226923352 \\h\hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af0 \ltrch\fcs0
|
||||
\lang1024\langfe1024\noproof\webhidden\insrsid1858992 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e0000005f0054006f0063003200320036003900320033003300350032000000}}}{\fldrslt {\rtlch\fcs1 \af0 \ltrch\fcs0
|
||||
\lang1024\langfe1024\noproof\webhidden\insrsid1858992 \hich\af31506\dbch\af31505\loch\f31506 2}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj }}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af31507 \ltrch\fcs0
|
||||
\lang1024\langfe1024\noproof\insrsid1858992
|
||||
\par }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af0 \ltrch\fcs0 \cs20\ul\cf20\lang1024\langfe1024\noproof\insrsid1858992\charrsid283681 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1024\langfe1024\noproof\insrsid1858992
|
||||
\hich\af31506\dbch\af31505\loch\f31506 HYPERLINK \\l "_Toc226923353"}{\rtlch\fcs1 \af0 \ltrch\fcs0 \cs20\ul\cf20\lang1024\langfe1024\noproof\insrsid1858992\charrsid283681 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af0 \ltrch\fcs0
|
||||
\cs20\ul\cf20\lang1024\langfe1024\noproof\insrsid1858992\charrsid283681 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e0000005f0054006f0063003200320036003900320033003300350033000000}}}{\fldrslt {\rtlch\fcs1 \af0 \ltrch\fcs0
|
||||
\cs20\ul\cf20\lang1024\langfe1024\noproof\insrsid1858992\charrsid283681 \hich\af31506\dbch\af31505\loch\f31506 v1.0.7}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1024\langfe1024\noproof\webhidden\insrsid1858992 \tab }{\field{\*\fldinst {\rtlch\fcs1 \af0
|
||||
\ltrch\fcs0 \lang1024\langfe1024\noproof\webhidden\insrsid1858992 \hich\af31506\dbch\af31505\loch\f31506 \hich\af31506\dbch\af31505\loch\f31506 PAGEREF \hich\af31506\dbch\af31505\loch\f31506 _Toc226923353 \\h\hich\af31506\dbch\af31505\loch\f31506 }{
|
||||
\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1024\langfe1024\noproof\webhidden\insrsid1858992 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e0000005f0054006f0063003200320036003900320033003300350033000000}}}{\fldrslt {\rtlch\fcs1 \af0 \ltrch\fcs0
|
||||
\lang1024\langfe1024\noproof\webhidden\insrsid1858992 \hich\af31506\dbch\af31505\loch\f31506 2}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj }}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af31507 \ltrch\fcs0
|
||||
\lang1024\langfe1024\noproof\insrsid1858992
|
||||
\par }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af0 \ltrch\fcs0 \cs20\ul\cf20\lang1024\langfe1024\noproof\insrsid1858992\charrsid283681 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1024\langfe1024\noproof\insrsid1858992
|
||||
\hich\af31506\dbch\af31505\loch\f31506 HYPERLINK \\l "_Toc226923354"}{\rtlch\fcs1 \af0 \ltrch\fcs0 \cs20\ul\cf20\lang1024\langfe1024\noproof\insrsid1858992\charrsid283681 \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af0 \ltrch\fcs0
|
||||
\cs20\ul\cf20\lang1024\langfe1024\noproof\insrsid1858992\charrsid283681 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e0000005f0054006f0063003200320036003900320033003300350034000000}}}{\fldrslt {\rtlch\fcs1 \af0 \ltrch\fcs0
|
||||
\cs20\ul\cf20\lang1024\langfe1024\noproof\insrsid1858992\charrsid283681 \hich\af31506\dbch\af31505\loch\f31506 v1.0.6}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1024\langfe1024\noproof\webhidden\insrsid1858992 \tab }{\field{\*\fldinst {\rtlch\fcs1 \af0
|
||||
\ltrch\fcs0 \lang1024\langfe1024\noproof\webhidden\insrsid1858992 \hich\af31506\dbch\af31505\loch\f31506 \hich\af31506\dbch\af31505\loch\f31506 PAGEREF \hich\af31506\dbch\af31505\loch\f31506 _Toc226923354 \\h\hich\af31506\dbch\af31505\loch\f31506 }{
|
||||
\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1024\langfe1024\noproof\webhidden\insrsid1858992 {\*\datafield 08d0c9ea79f9bace118c8200aa004ba90b02000000080000000e0000005f0054006f0063003200320036003900320033003300350034000000}}}{\fldrslt {\rtlch\fcs1 \af0 \ltrch\fcs0
|
||||
\lang1024\langfe1024\noproof\webhidden\insrsid1858992 \hich\af31506\dbch\af31505\loch\f31506 2}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj }}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af31507 \ltrch\fcs0
|
||||
\lang1024\langfe1024\noproof\insrsid1858992
|
||||
\par }\pard\plain \ltrpar\ql \li0\ri0\sa160\sl278\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0
|
||||
\fs24\lang3081\langfe1041\kerning2\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp3081\langfenp1041 }}\pard\plain \ltrpar\ql \li0\ri0\sa160\sl278\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1
|
||||
\af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang3081\langfe1041\kerning2\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp3081\langfenp1041 \sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid2914631
|
||||
\par }\pard\plain \ltrpar\s1\ql \li0\ri0\sb240\sa60\sl278\slmult1\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel0\adjustright\rin0\lin0\itap0\pararsid2914631 \rtlch\fcs1 \ab\af0\afs32\alang1025 \ltrch\fcs0
|
||||
\b\fs32\lang3081\langfe1041\kerning32\loch\af31502\hich\af31502\dbch\af31501\cgrid\langnp3081\langfenp1041 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid2914631 {\*\bkmkstart _Toc226923347}\hich\af31502\dbch\af31501\loch\f31502 Safe Area Helper
|
||||
{\*\bkmkend _Toc226923347}
|
||||
\par }\pard\plain \ltrpar\s2\ql \li0\ri0\sb240\sa60\sl278\slmult1\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel1\adjustright\rin0\lin0\itap0\pararsid2914631 \rtlch\fcs1 \ab\ai\af0\afs28\alang1025 \ltrch\fcs0
|
||||
\b\i\fs28\lang3081\langfe1041\kerning2\loch\af31502\hich\af31502\dbch\af31501\cgrid\langnp3081\langfenp1041 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid2914631 {\*\bkmkstart _Toc226923348}\hich\af31502\dbch\af31501\loch\f31502 Usage{\*\bkmkend _Toc226923348}
|
||||
|
||||
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \f31506\kerning2\insrsid2914631 \hich\af31506\dbch\af31505\loch\f31506 1.\tab}}\pard\plain \ltrpar\ql \fi-360\li720\ri0\sa160\sl278\slmult1
|
||||
\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls2\adjustright\rin0\lin720\itap0\pararsid2914631 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang3081\langfe1041\kerning2\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp3081\langfenp1041 {
|
||||
\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid2914631 \hich\af31506\dbch\af31505\loch\f31506 Create desired aspect ratios in the Game Window, e.g. 195:90 and 90:195 for iPhone X series.
|
||||
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \f31506\kerning2\insrsid2914631 \hich\af31506\dbch\af31505\loch\f31506 2.\tab}\hich\af31506\dbch\af31505\loch\f31506 Add the SafeArea.cs component to your GUI panels.
|
||||
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \f31506\kerning2\insrsid2914631 \hich\af31506\dbch\af31505\loch\f31506 3.\tab}\hich\af31506\dbch\af31505\loch\f31506 Add the SafeAreaDemo.cs once to a component in your scene.
|
||||
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \f31506\kerning2\insrsid2914631 \hich\af31506\dbch\af31505\loch\f31506 4.\tab}\hich\af31506\dbch\af31505\loch\f31506
|
||||
Run the game and use the Toggle hotkey (default "A") to toggle between simulated devices. Be sure to match the simulated device with the correct aspect ratio in your Game Window.
|
||||
\par }\pard\plain \ltrpar\s2\ql \li0\ri0\sb240\sa60\sl278\slmult1\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel1\adjustright\rin0\lin0\itap0\pararsid2914631 \rtlch\fcs1 \ab\ai\af0\afs28\alang1025 \ltrch\fcs0
|
||||
\b\i\fs28\lang3081\langfe1041\kerning2\loch\af31502\hich\af31502\dbch\af31501\cgrid\langnp3081\langfenp1041 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid2914631 {\*\bkmkstart _Toc226923349}\hich\af31502\dbch\af31501\loch\f31502 Add your own simulated devices
|
||||
{\*\bkmkend _Toc226923349}
|
||||
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \f31506\kerning2\insrsid2914631 \hich\af31506\dbch\af31505\loch\f31506 1.\tab}}\pard\plain \ltrpar\ql \fi-360\li720\ri0\sa160\sl278\slmult1
|
||||
\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls4\adjustright\rin0\lin720\itap0\pararsid2914631 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang3081\langfe1041\kerning2\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp3081\langfenp1041 {
|
||||
\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid2914631 \hich\af31506\dbch\af31505\loch\f31506 Run an empty scene to the target mobile device with one GUI panel containing the SafeArea.cs component.
|
||||
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \f31506\kerning2\insrsid2914631 \hich\af31506\dbch\af31505\loch\f31506 2.\tab}\hich\af31506\dbch\af31505\loch\f31506
|
||||
Rotate the device to each of the four orientations. Copy the pixel coordinates for each orientation from the debug output.
|
||||
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \f31506\kerning2\insrsid2914631 \hich\af31506\dbch\af31505\loch\f31506 3.\tab}\hich\af31506\dbch\af31505\loch\f31506
|
||||
Enter the simulated device into SafeArea.cs using the same technique for the iPhone X.
|
||||
\par }\pard\plain \ltrpar\s2\ql \li0\ri0\sb240\sa60\sl278\slmult1\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel1\adjustright\rin0\lin0\itap0\pararsid1858992 \rtlch\fcs1 \ab\ai\af0\afs28\alang1025 \ltrch\fcs0
|
||||
\b\i\fs28\lang3081\langfe1041\kerning2\loch\af31502\hich\af31502\dbch\af31501\cgrid\langnp3081\langfenp1041 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid1858992 {\*\bkmkstart _Toc226923350}\hich\af31502\dbch\af31501\loch\f31502 Other notes and suggestions
|
||||
{\*\bkmkend _Toc226923350}
|
||||
\par }\pard\plain \ltrpar\ql \li0\ri0\sa160\sl278\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid2914631 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0
|
||||
\fs24\lang3081\langfe1041\kerning2\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp3081\langfenp1041 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid2914631 \hich\af31506\dbch\af31505\loch\f31506
|
||||
See notes in SafeArea.cs and read our article online for a full breakdown of how the Safe Area works}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid5571476 .}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid2914631
|
||||
\par \hich\af31506\dbch\af31505\loch\f31506 If you have a suggestion or request for a simluated device to be added to the list, please let us know in the Unity forums.
|
||||
\par \hich\af31506\dbch\af31505\loch\f31506 If this asset helped you, please rate us on the Asset Store!
|
||||
\par }\pard\plain \ltrpar\s1\ql \li0\ri0\sb240\sa60\sl278\slmult1\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel0\adjustright\rin0\lin0\itap0\pararsid2914631 \rtlch\fcs1 \ab\af0\afs32\alang1025 \ltrch\fcs0
|
||||
\b\fs32\lang3081\langfe1041\kerning32\loch\af31502\hich\af31502\dbch\af31501\cgrid\langnp3081\langfenp1041 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid2914631 {\*\bkmkstart _Toc226923351}\hich\af31502\dbch\af31501\loch\f31502 Version History
|
||||
{\*\bkmkend _Toc226923351}
|
||||
\par }\pard\plain \ltrpar\s2\ql \li0\ri0\sb240\sa60\sl278\slmult1\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel1\adjustright\rin0\lin0\itap0\pararsid2914631 \rtlch\fcs1 \ab\ai\af0\afs28\alang1025 \ltrch\fcs0
|
||||
\b\i\fs28\lang3081\langfe1041\kerning2\loch\af31502\hich\af31502\dbch\af31501\cgrid\langnp3081\langfenp1041 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid16206562 {\*\bkmkstart _Toc226923352}\hich\af31502\dbch\af31501\loch\f31502 v}{\rtlch\fcs1 \af0 \ltrch\fcs0
|
||||
\insrsid2914631 \hich\af31502\dbch\af31501\loch\f31502 1.0.8{\*\bkmkend _Toc226923352}
|
||||
\par }\pard\plain \ltrpar\ql \li0\ri0\sa160\sl278\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid2914631 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0
|
||||
\fs24\lang3081\langfe1041\kerning2\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp3081\langfenp1041 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid2914631 \hich\af31506\dbch\af31505\loch\f31506 Released: Apr 12, 2026}{\rtlch\fcs1 \af0 \ltrch\fcs0
|
||||
\insrsid2914631\charrsid2914631
|
||||
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid2914631 \hich\af31506\dbch\af31505\loch\f31506 Compatiblity with Unity 6.3 (no code changes).}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid2914631\charrsid2914631
|
||||
\par }\pard\plain \ltrpar\s2\ql \li0\ri0\sb240\sa60\sl278\slmult1\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel1\adjustright\rin0\lin0\itap0\pararsid2914631 \rtlch\fcs1 \ab\ai\af0\afs28\alang1025 \ltrch\fcs0
|
||||
\b\i\fs28\lang3081\langfe1041\kerning2\loch\af31502\hich\af31502\dbch\af31501\cgrid\langnp3081\langfenp1041 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid16206562 {\*\bkmkstart _Toc226923353}\hich\af31502\dbch\af31501\loch\f31502 v}{\rtlch\fcs1 \af0 \ltrch\fcs0
|
||||
\insrsid2914631 \hich\af31502\dbch\af31501\loch\f31502 1.0.7{\*\bkmkend _Toc226923353}
|
||||
\par }\pard\plain \ltrpar\ql \li0\ri0\sa160\sl278\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid2914631 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0
|
||||
\fs24\lang3081\langfe1041\kerning2\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp3081\langfenp1041 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid2914631 \hich\af31506\dbch\af31505\loch\f31506 Released: Aug 14, 2020
|
||||
\par \hich\af31506\dbch\af31505\loch\f31506 Added startup sim device option to SafeAreaDemo component.
|
||||
\par }\pard\plain \ltrpar\s2\ql \li0\ri0\sb240\sa60\sl278\slmult1\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel1\adjustright\rin0\lin0\itap0\pararsid2914631 \rtlch\fcs1 \ab\ai\af0\afs28\alang1025 \ltrch\fcs0
|
||||
\b\i\fs28\lang3081\langfe1041\kerning2\loch\af31502\hich\af31502\dbch\af31501\cgrid\langnp3081\langfenp1041 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid16206562 {\*\bkmkstart _Toc226923354}\hich\af31502\dbch\af31501\loch\f31502 v}{\rtlch\fcs1 \af0 \ltrch\fcs0
|
||||
\insrsid2914631 \hich\af31502\dbch\af31501\loch\f31502 1.0.6{\*\bkmkend _Toc226923354}
|
||||
\par }\pard\plain \ltrpar\ql \li0\ri0\sa160\sl278\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid2914631 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0
|
||||
\fs24\lang3081\langfe1041\kerning2\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp3081\langfenp1041 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid2914631 \hich\af31506\dbch\af31505\loch\f31506 Released: Aug 14, 2020
|
||||
\par \hich\af31506\dbch\af31505\loch\f31506 Fix for some Samsung devices (Note 10+, A71 and S20) that would startup with an error state making the SafeArea disappear.}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid4542871
|
||||
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid2914631
|
||||
\par }{\*\themedata 504b030414000600080000002100e9de0fbfff0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb4ec3301045f748fc83e52d4a
|
||||
9cb2400825e982c78ec7a27cc0c8992416c9d8b2a755fbf74cd25442a820166c2cd933f79e3be372bd1f07b5c3989ca74aaff2422b24eb1b475da5df374fd9ad
|
||||
5689811a183c61a50f98f4babebc2837878049899a52a57be670674cb23d8e90721f90a4d2fa3802cb35762680fd800ecd7551dc18eb899138e3c943d7e503b6
|
||||
b01d583deee5f99824e290b4ba3f364eac4a430883b3c092d4eca8f946c916422ecab927f52ea42b89a1cd59c254f919b0e85e6535d135a8de20f20b8c12c3b0
|
||||
0c895fcf6720192de6bf3b9e89ecdbd6596cbcdd8eb28e7c365ecc4ec1ff1460f53fe813d3cc7f5b7f020000ffff0300504b030414000600080000002100a5d6
|
||||
a7e7c0000000360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4f
|
||||
c7060abb0884a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b6309512
|
||||
0f88d94fbc52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462
|
||||
a1a82fe353bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f746865
|
||||
6d652f7468656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b
|
||||
4b0d592c9c070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b
|
||||
4757e8d3f729e245eb2b260a0238fd010000ffff0300504b030414000600080000002100b6f4679893070000c9200000160000007468656d652f7468656d652f
|
||||
7468656d65312e786d6cec59cd8b1bc915bf07f23f347d97f5d5ad8fc1f2a24fcfda33b6b164873dd648a5eef2547789aad28cc56208de532e81c026e49085bd
|
||||
ed21842cecc22eb9e48f31d8249b3f22afaa5bdd5552c99e191c3061463074977eefd5afde7bf5de53d5ddcf5e26d4bbc05c1096f6fcfa9d9aefe174ce16248d
|
||||
7afeb3d9a4d2f13d2151ba4094a5b8e76fb0f03fbbf7eb5fdd454732c609f6403e1547a8e7c752ae8eaa5531876124eeb0154ee1bb25e30992f0caa3ea82a34b
|
||||
d09bd06aa3566b55134452df4b51026a1f2f97648ebd9952e9dfdb2a1f53784da5500373caa74a35b6243476715e5708b11143cabd0b447b3eccb3609733fc52
|
||||
fa1e4542c2173dbfa6fffceabdbb5574940b517940d6909be8bf5c2e17589c37f49c3c3a2b260d823068f50bfd1a40e53e6edc1eb7c6ad429f06a0f91c569a71
|
||||
b175b61bc320c71aa0ecd1a17bd41e35eb16ded0dfdce3dc0fd5c7c26b50a63fd8c34f2643b0a285d7a00c1feee1c3417730b2f56b50866fede1dbb5fe28685b
|
||||
fa3528a6243ddf43d7c25673b85d6d0159327aec8477c360d26ee4ca4b144443115d6a8a254be5a1584bd00bc6270050408a24493db959e1259a43140f112567
|
||||
9c7827248a21f056286502866b8ddaa4d684ffea13e827ed5174849121ad780113b137a4f87862cec94af6fc07a0d537206f7ffef9cdeb1fdfbcfee9cd575fbd
|
||||
79fdf77c6eadca923b466964cafdf2dd1ffef3cd6fbd7ffff0ed2f5fff319b7a172f4cfcbbbffdeedd3ffef93ef5b0e2d2146ffff4fdbb1fbf7ffbe7dfffebaf
|
||||
5f3bb4f7393a33e1339260e13dc297de5396c0021dfcf119bf9ec42c46c494e8a791402952b338f48f656ca11f6d10450edc00db767cce21d5b880f7d72f2cc2
|
||||
d398af2571687c182716f094313a60dc6985876a2ec3ccb3751ab927e76b13f714a10bd7dc43945a5e1eaf579063894be530c616cd2714a5124538c5d253dfb1
|
||||
738c1dabfb8210cbaea764ce99604be97d41bc01224e93ccc899154da5d03149c02f1b1741f0b7659bd3e7de8051d7aa47f8c246c2de40d4417e86a965c6fb68
|
||||
2d51e252394309350d7e8264ec2239ddf0b9891b0b099e8e3065de78818570c93ce6b05ec3e90f21cdb8dd7e4a37898de4929cbb749e20c64ce4889d0f6394ac
|
||||
5cd829496313fbb938871045de13265df05366ef10f50e7e40e941773f27d872f787b3c133c8b026a53240d4376beef0e57dccacf89d6ee8126157aae9f3c44a
|
||||
b17d4e9cd131584756689f604cd1255a60ec3dfbdcc160c05696cd4bd20f62c82ac7d815580f901dabea3dc5027a25d5dcece7c91322ac909de2881de073bad9
|
||||
493c1b9426881fd2fc08bc6eda7c0ca52e7105c0633a3f37818f08f480102f4ea33c16a0c308ee835a9fc4c82a60ea5db8e375c32dff5d658fc1be7c61d1b8c2
|
||||
be04197c6d1948eca6cc7b6d3343d49aa00c9819822ec3956e41c4727f29a28aab165b3be596f6a62ddd00dd91d5f42424fd6007b4d3fb84ffbbde073a8cb77f
|
||||
f9c6b10f3e4ebfe3566c25ab6b763a8792c9f14e7f7308b7dbd50c195f904fbfa919a175fa04431dd9cf58b73dcd6d4fe3ffdff73487f6f36d2773a8dfb8ed64
|
||||
7ce8306e3b99fc70e5e3743265f3027d8d3af0c80e7af4b14f72f0d46749289dca0dc527421ffc08f83db398c0a092d3279eb838055cc5f0a8ca1c4c60e1228e
|
||||
b48cc799fc0d91f134462b381daafb4a492472d591f0564cc0a1911e76ea5678ba4e4ed9223becacd7d5c16656590592e5782d2cc6e1a04a66e856bb3cc02bd4
|
||||
6bb6913e68dd1250b2d721614c6693683a48b4b783ca48fa58178ce620a157f65158741d2c3a4afdd6557b2c805ae115f8c1edc1cff49e1f06200242701e07cd
|
||||
f942f92973f5d6bbda991fd3d3878c69450034d8db08283ddd555c0f2e4fad2e0bb52b78da2261849b4d425b46377822869fc17974aad1abd0b8aeafbba54b2d
|
||||
7aca147a3e08ad9246bbf33e1637f535c8ede6069a9a9982a6de65cf6f35430899395af5fc251c1ac363b282d811ea3717a211dcbccc25cf36fc4d32cb8a0b39
|
||||
4222ce0cae934e960d122231f728497abe5a7ee1069aea1ca2b9d51b90103e59725d482b9f1a3970baed64bc5ce2b934dd6e8c284b67af90e1b35ce1fc568bdf
|
||||
1cac24d91adc3d8d1797de195df3a708422c6cd795011744c0dd413db3e682c0655891c8caf8db294c79da356fa3740c65e388ae62945714339967709dca0b3a
|
||||
faadb081f196af190c6a98242f8467912ab0a651ad6a5a548d8cc3c1aafb6121653923699635d3ca2aaa6abab39835c3b60cecd8f26645de60b53531e434b3c2
|
||||
67a97b37e576b7b96ea74f28aa0418bcb09fa3ea5ea12018d4cac92c6a8af17e1a56393b1fb56bc776811fa07695226164fdd656ed8edd8a1ae19c0e066f54f9
|
||||
416e376a6168b9ed2bb5a5f5adb979b1cdce5e40f2184197bba6526857c2c92e47d0104d754f92a50dd8222f65be35e0c95b73d2f3bfac85fd60d80887955a27
|
||||
1c57826650ab74c27eb3d20fc3667d1cd66ba341e31514161927f530bbb19fc00506dde4f7f67a7cefee3ed9ded1dc99b3a4caf4dd7c5513d777f7f5c6e1bb7b
|
||||
8f40d2f9b2d598749bdd41abd26df627956034e854bac3d6a0326a0ddba3c9681876ba9357be77a1c141bf390c5ae34ea5551f0e2b41aba6e877ba9576d068f4
|
||||
8376bf330efaaff23606569ea58fdc16605ecdebde7f010000ffff0300504b0304140006000800000021000dd1909fb60000001b010000270000007468656d65
|
||||
2f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f78277086f6fd3ba109126dd88d0add40384e4350d36
|
||||
3f2451eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89d93b64b060828e6f37ed1567914b284d262452282e
|
||||
3198720e274a939cd08a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd5001996509affb3fd381a89672f1f165dfe514173d985
|
||||
0528a2c6cce0239baa4c04ca5bbabac4df000000ffff0300504b01022d0014000600080000002100e9de0fbfff0000001c020000130000000000000000000000
|
||||
0000000000005b436f6e74656e745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6a7e7c0000000360100000b00000000000000000000
|
||||
000000300100005f72656c732f2e72656c73504b01022d00140006000800000021006b799616830000008a0000001c0000000000000000000000000019020000
|
||||
7468656d652f7468656d652f7468656d654d616e616765722e786d6c504b01022d0014000600080000002100b6f4679893070000c92000001600000000000000
|
||||
000000000000d60200007468656d652f7468656d652f7468656d65312e786d6c504b01022d00140006000800000021000dd1909fb60000001b01000027000000
|
||||
000000000000000000009d0a00007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000980b00000000}
|
||||
{\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d
|
||||
617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169
|
||||
6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363
|
||||
656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e}
|
||||
{\*\latentstyles\lsdstimax376\lsdlockeddef0\lsdsemihiddendef0\lsdunhideuseddef0\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 1;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 5;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 9;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 1;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 2;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 3;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 4;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 5;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 6;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 7;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 8;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal Indent;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 header;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footer;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index heading;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of figures;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope return;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation reference;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 line number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 page number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote text;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of authorities;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 macro;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 toa heading;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 3;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 3;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 3;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 5;\lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Closing;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Signature;\lsdsemihidden1 \lsdunhideused1 \lsdpriority1 \lsdlocked0 Default Paragraph Font;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 4;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Message Header;\lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Salutation;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Date;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Heading;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 3;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Block Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Hyperlink;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 FollowedHyperlink;\lsdqformat1 \lsdpriority22 \lsdlocked0 Strong;
|
||||
\lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Document Map;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Plain Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 E-mail Signature;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Top of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Bottom of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal (Web);\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Acronym;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Cite;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Code;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Definition;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Keyboard;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Preformatted;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Sample;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Typewriter;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Variable;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation subject;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 No List;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 1;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Balloon Text;\lsdpriority39 \lsdlocked0 Table Grid;
|
||||
\lsdsemihidden1 \lsdlocked0 Placeholder Text;\lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing;\lsdpriority60 \lsdlocked0 Light Shading;\lsdpriority61 \lsdlocked0 Light List;\lsdpriority62 \lsdlocked0 Light Grid;
|
||||
\lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdpriority65 \lsdlocked0 Medium List 1;\lsdpriority66 \lsdlocked0 Medium List 2;\lsdpriority67 \lsdlocked0 Medium Grid 1;\lsdpriority68 \lsdlocked0 Medium Grid 2;
|
||||
\lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdpriority70 \lsdlocked0 Dark List;\lsdpriority71 \lsdlocked0 Colorful Shading;\lsdpriority72 \lsdlocked0 Colorful List;\lsdpriority73 \lsdlocked0 Colorful Grid;\lsdpriority60 \lsdlocked0 Light Shading Accent 1;
|
||||
\lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;
|
||||
\lsdsemihidden1 \lsdlocked0 Revision;\lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;
|
||||
\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdpriority70 \lsdlocked0 Dark List Accent 1;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 1;
|
||||
\lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdpriority60 \lsdlocked0 Light Shading Accent 2;\lsdpriority61 \lsdlocked0 Light List Accent 2;\lsdpriority62 \lsdlocked0 Light Grid Accent 2;
|
||||
\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 2;
|
||||
\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2;\lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 2;
|
||||
\lsdpriority72 \lsdlocked0 Colorful List Accent 2;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdpriority61 \lsdlocked0 Light List Accent 3;\lsdpriority62 \lsdlocked0 Light Grid Accent 3;
|
||||
\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 3;
|
||||
\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdpriority70 \lsdlocked0 Dark List Accent 3;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 3;
|
||||
\lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 3;\lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdpriority62 \lsdlocked0 Light Grid Accent 4;
|
||||
\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 4;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 4;
|
||||
\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 4;
|
||||
\lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdpriority60 \lsdlocked0 Light Shading Accent 5;\lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdpriority62 \lsdlocked0 Light Grid Accent 5;
|
||||
\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 5;
|
||||
\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5;\lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 5;
|
||||
\lsdpriority72 \lsdlocked0 Colorful List Accent 5;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdpriority61 \lsdlocked0 Light List Accent 6;\lsdpriority62 \lsdlocked0 Light Grid Accent 6;
|
||||
\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 6;
|
||||
\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdpriority70 \lsdlocked0 Dark List Accent 6;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 6;
|
||||
\lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 6;\lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis;
|
||||
\lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference;\lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdsemihidden1 \lsdunhideused1 \lsdpriority37 \lsdlocked0 Bibliography;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;\lsdpriority41 \lsdlocked0 Plain Table 1;\lsdpriority42 \lsdlocked0 Plain Table 2;\lsdpriority43 \lsdlocked0 Plain Table 3;\lsdpriority44 \lsdlocked0 Plain Table 4;
|
||||
\lsdpriority45 \lsdlocked0 Plain Table 5;\lsdpriority40 \lsdlocked0 Grid Table Light;\lsdpriority46 \lsdlocked0 Grid Table 1 Light;\lsdpriority47 \lsdlocked0 Grid Table 2;\lsdpriority48 \lsdlocked0 Grid Table 3;\lsdpriority49 \lsdlocked0 Grid Table 4;
|
||||
\lsdpriority50 \lsdlocked0 Grid Table 5 Dark;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 1;
|
||||
\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 1;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 1;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 1;
|
||||
\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 1;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 2;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 2;
|
||||
\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 2;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 2;
|
||||
\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 3;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 3;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 3;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 3;
|
||||
\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 3;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 4;
|
||||
\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 4;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 4;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 4;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 4;
|
||||
\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 4;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 5;
|
||||
\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 5;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 5;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 5;
|
||||
\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 5;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 6;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 6;
|
||||
\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 6;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 6;
|
||||
\lsdpriority46 \lsdlocked0 List Table 1 Light;\lsdpriority47 \lsdlocked0 List Table 2;\lsdpriority48 \lsdlocked0 List Table 3;\lsdpriority49 \lsdlocked0 List Table 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark;
|
||||
\lsdpriority51 \lsdlocked0 List Table 6 Colorful;\lsdpriority52 \lsdlocked0 List Table 7 Colorful;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 List Table 2 Accent 1;\lsdpriority48 \lsdlocked0 List Table 3 Accent 1;
|
||||
\lsdpriority49 \lsdlocked0 List Table 4 Accent 1;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 1;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 1;
|
||||
\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 List Table 2 Accent 2;\lsdpriority48 \lsdlocked0 List Table 3 Accent 2;\lsdpriority49 \lsdlocked0 List Table 4 Accent 2;
|
||||
\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 2;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 3;
|
||||
\lsdpriority47 \lsdlocked0 List Table 2 Accent 3;\lsdpriority48 \lsdlocked0 List Table 3 Accent 3;\lsdpriority49 \lsdlocked0 List Table 4 Accent 3;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 3;
|
||||
\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 4;\lsdpriority47 \lsdlocked0 List Table 2 Accent 4;
|
||||
\lsdpriority48 \lsdlocked0 List Table 3 Accent 4;\lsdpriority49 \lsdlocked0 List Table 4 Accent 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 4;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 4;
|
||||
\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 List Table 2 Accent 5;\lsdpriority48 \lsdlocked0 List Table 3 Accent 5;
|
||||
\lsdpriority49 \lsdlocked0 List Table 4 Accent 5;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 5;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 5;
|
||||
\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 List Table 2 Accent 6;\lsdpriority48 \lsdlocked0 List Table 3 Accent 6;\lsdpriority49 \lsdlocked0 List Table 4 Accent 6;
|
||||
\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Mention;
|
||||
\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Smart Hyperlink;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Hashtag;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Unresolved Mention;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Smart Link;}}{\*\datastore 01050000
|
||||
02000000180000004d73786d6c322e534158584d4c5265616465722e362e30000000000000000000000e0000
|
||||
d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff0900060000000000000000000000010000000100000000000000001000000200000001000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
fffffffffffffffffdffffff04000000feffffff05000000fefffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffff010000000c6ad98892f1d411a65f0040963251e500000000000000000000000030f3
|
||||
1c4473cadc0103000000c0020000000000004d0073006f004400610074006100530074006f0072006500000000000000000000000000000000000000000000000000000000000000000000000000000000001a000101ffffffffffffffff02000000000000000000000000000000000000000000000030f31c4473cadc01
|
||||
30f31c4473cadc01000000000000000000000000d400c4003000c40032004b0049004a00d900d400d2004a004600d700c300d8005100cb00c600c200490041003d003d000000000000000000000000000000000032000101ffffffffffffffff03000000000000000000000000000000000000000000000030f31c4473ca
|
||||
dc0130f31c4473cadc010000000000000000000000004900740065006d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000201ffffffff04000000ffffffff000000000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000210100000000000001000000020000000300000004000000feffffff060000000700000008000000090000000a000000feffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3c3f786d6c2076657273696f6e3d22312e3022207374616e64616c6f6e653d226e6f223f3e3c623a536f757263657320786d6c6e733a623d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f6f6666
|
||||
696365446f63756d656e742f323030362f6269626c696f6772617068792220786d6c6e733d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f6f6666696365446f63756d656e742f323030362f6269626c696f677261706879222053656c65637465645374796c653d225c61706173
|
||||
6978746865646974696f6e6f66666963656f6e6c696e652e78736c22205374796c654e616d653d22415041222056657273696f6e3d2236223e3c2f623a536f75726365733e000000000000000000000000000000000000000000000000000000000000003c3f786d6c2076657273696f6e3d22312e302220656e636f6469
|
||||
6e673d225554462d3822207374616e64616c6f6e653d226e6f223f3e0d0a3c64733a6461746173746f72654974656d2064733a6974656d49443d227b37304134343644322d303941322d344345372d383931372d3738463834324239413232307d2220786d6c6e733a64733d22687474703a2f2f736368656d61732e6f70
|
||||
656e786d6c666f726d6174732e6f72672f6f6666696365446f63756d656e742f323030362f637573500072006f007000650072007400690065007300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000200ffffffffffffffffffffffff000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000500000055010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000
|
||||
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000
|
||||
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff
|
||||
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000746f6d586d6c223e3c64733a736368656d61526566733e3c64733a736368656d615265662064733a7572693d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f7267
|
||||
2f6f6666696365446f63756d656e742f323030362f6269626c696f677261706879222f3e3c2f64733a736368656d61526566733e3c2f64733a6461746173746f72654974656d3e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000105000000000000}}
|
||||
14
Assets/CrystalFramework/Utility/SafeArea.rtf.meta
Normal file
14
Assets/CrystalFramework/Utility/SafeArea.rtf.meta
Normal file
@@ -0,0 +1,14 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 37fecf77038c4744683aa1ee2917ff5f
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 130488
|
||||
packageName: Safe Area Helper
|
||||
packageVersion: 1.0.6
|
||||
assetPath: Assets/CrystalFramework/Utility/SafeArea.rtf
|
||||
uploadId: 898916
|
||||
@@ -11,4 +11,11 @@ public interface IDrawingCatalogController
|
||||
event Action ListChanged;
|
||||
UniTask InitializeAsync(CancellationToken ct);
|
||||
void OnTemplateSelected(string id);
|
||||
|
||||
/// <summary>
|
||||
/// Signalled by the view layer once the catalog has finished populating after a
|
||||
/// <see cref="ListChanged"/> refresh. Lets <see cref="InitializeAsync"/> keep the loading
|
||||
/// screen up until items are on screen, instead of revealing an empty catalog that fills in later.
|
||||
/// </summary>
|
||||
void NotifyPopulated();
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user