// Created by ZhuCong on 1/1/14.
// Copyright 2014 Umeng.com . All rights reserved.
using UnityEngine;
using System;
using System.Runtime.InteropServices;
using System.Collections;
using System.Collections.Generic;
using System.Text;
namespace Umeng
{
public class Analytics
{
static string version = "2.3";
#if UNITY_ANDROID
static bool hasInit = false;
#endif
//
///
/// 开始友盟统计 默认发送策略为启动时发送
///
/// 友盟appKey
/// 渠道名称
public static void StartWithAppKeyAndChannelId(string appKey, string channelId)
{
#if UNITY_EDITOR
//Debug.LogWarning("友盟统计在iOS/Android 真机上才会向友盟后台服务器发送事件 请在真机上测试");
#elif UNITY_IPHONE
StartWithAppKeyAndReportPolicyAndChannelId(appKey, ReportPolicy.BATCH, channelId);
#elif UNITY_ANDROID
_AppKey = appKey;
_ChannelId = channelId;
UMGameAgentInit();
if(!hasInit)
{
//Debug.LogWarning("onResume");
onResume();
CreateUmengManger();
hasInit = true;
}
// EnableActivityDurationTrack(false);
#endif
}
///
/// 设置是否打印sdk的信息,默认不开启
///
/// 设置为true,Umeng SDK 会输出日志信息,记得release产品时要设置回false.
///
public static void SetLogEnabled(bool value)
{
#if UNITY_EDITOR
//Debug.Log("SetLogEnabled");
#elif UNITY_IPHONE
_SetLogEnabled(value);
#elif UNITY_ANDROID
Agent.CallStatic("setDebugMode", value);
#endif
}
//使用前,请先到友盟App管理后台的设置->编辑自定义事件 中添加相应的事件ID,然后在工程中传入相应的事件ID
//eventId、attributes中key和value都不能使用空格和特殊字符,且长度不能超过255个字符(否则将截取前255个字符)
//id, ts, du是保留字段,不能作为eventId及key的名称
///
/// 基本事件
///
/// 友盟后台设定的事件Id
public static void Event(string eventId)
{
#if UNITY_EDITOR
//Debug.Log("Event");
#elif UNITY_IPHONE
_Event(eventId);
#elif UNITY_ANDROID
Agent.CallStatic("onEvent", Context, eventId);
#endif
}
//不同的标签会分别进行统计,方便同一事件的不同标签的对比,为nil或空字符串时后台会生成和eventId同名的标签.
///
/// 基本事件
///
/// 友盟后台设定的事件Id
/// 分类标签
public static void Event(string eventId, string label)
{
#if UNITY_EDITOR
//Debug.Log("Event");
#elif UNITY_IPHONE
_EventWithLabel(eventId, label);
#elif UNITY_ANDROID
Agent.CallStatic("onEvent", Context, eventId, label);
#endif
}
///
/// 属性事件
///
/// 友盟后台设定的事件Id
/// 属性中的Key-Vaule Pair不能超过10个
public static void Event(string eventId, Dictionary attributes)
{
#if UNITY_EDITOR
//Debug.Log("Event");
#elif UNITY_IPHONE
_EventWithAttributes(eventId, DictionaryToJson(attributes));
#elif UNITY_ANDROID
Agent.CallStatic("onEvent", Context, eventId, ToJavaHashMap(attributes));
#endif
}
///
/// 页面时长统计,记录某个页面被打开多长时间
/// 与PageEnd配对使用
///
/// 被统计view名称
public static void PageBegin(string pageName)
{
#if UNITY_EDITOR
//Debug.Log("PageBegin");
#elif UNITY_IPHONE
_BeginLogPageView(pageName);
#elif UNITY_ANDROID
Agent.CallStatic("onPageStart", pageName);
#endif
}
///
/// 页面时长统计,记录某个页面被打开多长时间
/// 与PageBegin配对使用
///
/// 被统计view名称
///
public static void PageEnd(string pageName)
{
#if UNITY_EDITOR
//Debug.Log("PageEnd");
#elif UNITY_IPHONE
_EndLogPageView(pageName);
#elif UNITY_ANDROID
Agent.CallStatic("onPageEnd", pageName);
#endif
}
///
/// 自定义事件 — 计算事件数
///
public static void Event(string eventId, Dictionary attributes, int value)
{
try
{
if (attributes == null)
attributes = new System.Collections.Generic.Dictionary();
if (attributes.ContainsKey("__ct__"))
{
attributes["__ct__"] = value.ToString();
Event(eventId, attributes);
}
else
{
attributes.Add("__ct__", value.ToString());
Event(eventId, attributes);
attributes.Remove("__ct__");
}
}
catch (Exception)
{
}
}
///
/// 获取缓存的在线参数
///
/// 在线参数的Key 请在友盟后台设置
/// Key对应的在线参数值
public static string GetDeviceInfo()
{
#if UNITY_EDITOR
//Unity Editor 模式下 返回null 请在iOS/Anroid真机上测试
//Debug.Log("GetDeviceInfo return null");
return null;
#elif UNITY_IPHONE
return _GetDeviceID();
#elif UNITY_ANDROID
var util = new AndroidJavaClass("com.umeng.analytics.UnityUtil");
var info = util.CallStatic("getDeviceInfo", Context);
return info;
#else
return null;
#endif
}
//设置是否对日志信息进行加密, 默认false(不加密).
//value 设置为true, SDK会将日志信息做加密处理
public static void SetLogEncryptEnabled(bool value)
{
#if UNITY_EDITOR
//Debug.Log("SetLogEncryptEnabled");
#elif UNITY_IPHONE
_SetEncryptEnabled(value);
#elif UNITY_ANDROID
Agent.CallStatic("enableEncrypt", value);
#endif
}
public static void SetLatency(int value)
{
#if UNITY_EDITOR
//Debug.Log("SetLatency");
#elif UNITY_IPHONE
//_SetLatency(value);
#elif UNITY_ANDROID
Agent.CallStatic("setLatencyWindow", (long)value);
#endif
}
public static void Event(string[] keyPath,int value,string label)
{
#if UNITY_EDITOR
#elif UNITY_IPHONE
var listStr = String.Join(";=umengUnity=;", keyPath);
_CCEvent(listStr,value,label);
#elif UNITY_ANDROID
var listStr = String.Join(";=umengUnity=;", keyPath);
var util = new AndroidJavaClass("com.umeng.analytics.UnityUtil");
util.CallStatic("onEventForUnity", Context, listStr,value,label);
#endif
}
//Android Only
#if UNITY_ANDROID
//设置Session时长
public static void SetContinueSessionMillis(long milliseconds)
{
#if UNITY_EDITOR
//Debug.Log("setContinueSessionMillis");
#else
Agent.CallStatic("setSessionContinueMillis", milliseconds);
#endif
}
[Obsolete("Flush")]
//清空缓存
public static void Flush()
{
#if UNITY_EDITOR
//Debug.Log("flush");
#else
Agent.CallStatic("flush", Context);
#endif
}
[Obsolete("SetEnableLocation已弃用")]
//启用位置信息
public static void SetEnableLocation(bool reportLocation)
{
#if UNITY_EDITOR
//Debug.Log("setEnableLocation:"+ reportLocation);
#else
Agent.CallStatic("setAutoLocation", reportLocation);
#endif
}
//启用页面统计
public static void EnableActivityDurationTrack(bool isTraceActivity)
{
#if UNITY_EDITOR
//Debug.Log("enableActivityDurationTrack:"+isTraceActivity);
#else
Agent.CallStatic("openActivityDurationTrack", isTraceActivity);
#endif
}
/*
android6.0中采集mac方式变更,新增接口 public static void setCheckDevice(boolean enable) 该接口默认参数是true,即采集mac地址,
但如果开发者需要在googleplay发布,考虑到审核风险,可以调用该接口,参数设置为 false 就不会采集mac地址。
*/
public static void SetCheckDevice(bool value)
{
#if UNITY_EDITOR
#else
Agent.CallStatic("setCheckDevice", value);
#endif
}
#endif
//iOS Only
#if UNITY_IPHONE
/*
BATCH(启动发送)为默认发送策略
关于发送策略的调整,请参见关于发送策略及发送策略变更的说明
http://blog.umeng.com/index.php/2012/12/0601/
SEND_INTERVAL 为按最小间隔发送,默认为10秒,取值范围为10 到 86400(一天), 如果不在这个区间的话,会按10设置。
SEND_ON_EXIT 为退出或进入后台时发送,这种发送策略在App运行过程中不发送,对开发者和用户的影响最小。
不过这种发送策略只在iOS > 4.0时才会生效, iOS < 4.0 会被自动调整为BATCH。
*/
public enum ReportPolicy
{
BATCH = 1,//启动发送
SENDDAILY = 4, //每日发送
SEND_INTERVAL = 6, //按最小间隔发送
SEND_ON_EXIT = 7 //退出或进入后台时发送
}
///
/// 开启友盟统计
///
/// 友盟appKey
/// 发送策略
/// 渠道名称
///
public static void StartWithAppKeyAndReportPolicyAndChannelId(string appkey, ReportPolicy policy, string channelId)
{
#if UNITY_EDITOR
//Debug.LogWarning("友盟统计在iOS/Androi 真机上才会向友盟后台服务器发送事件 请在真机上测试");
#else
_StartWithAppKeyAndReportPolicyAndChannelId(appkey, (int)policy, channelId,version);
_AppKey = appkey;
_ChannelId = channelId;
#endif
}
///
/// 当reportPolicy 为 SEND_INTERVAL 时设定log发送间隔
///
/// 单位为秒,最小为10,最大为86400(一天).
public static void SetLogSendInterval(int seconds)
{
#if UNITY_EDITOR
//Debug.Log("SetLogSendInterval");
#else
_SetLogSendInterval((double)seconds);
#endif
}
///
/// 手动设置app版本号 此API不再建议使用 因为启动时会自动读取Unity的Pla yerSettings.bundleVersion(CFBundleVersion)作为版本
///
/// 版本号
[Obsolete("此API不再建议使用 因为启动时会自动读取Unity的PlayerSettings.bundleVersion(CFBundleVersion)作为版本")]
public static void SetAppVersion(string value)
{
#if UNITY_EDITOR
//Debug.Log("SetAppVersion");
#else
_SetAppVersion(value);
#endif
}
///
/// 开启CrashReport收集, 默认是开启状态.
///
/// 设置成false,就可以关闭友盟CrashReport收集
public static void SetCrashReportEnabled(bool value)
{
#if UNITY_EDITOR
//Debug.Log("SetCrashReportEnabled");
#else
//由于Unity在iOS平台使用AOT模式编译 你得到的CrashReport函数名将不是完全一致
_SetCrashReportEnabled(value);
//Anddroid 平台Crash Report 总是是开启的 无需调用SetCrashReportEnabled
//Anddroid 平台Crash Report 仅限于Java层的崩溃日志
#endif
}
///
/// 页面时长统计,记录某个view被打开多长时间,与调用PageBegin,PageEnd计时等价
///
/// 被统计view名称
/// 时长单位为秒
///
public static void LogPageViewWithSeconds(string pageName, int seconds)
{
#if UNITY_EDITOR
//Debug.Log("LogPageViewWithSeconds");
#else
_LogPageViewWithSeconds(pageName, seconds);
#endif
}
///
/// 判断设备是否越狱,判断方法根据 apt和Cydia.app的path来判断
///
/// 是否越狱
public static bool IsJailBroken()
{
#if UNITY_EDITOR
//always return false in UNITY_EDITOR mode
//Debug.Log("IsJailBroken always return false in UNITY_EDITOR mode");
return false;
#else
return _IsJailBroken();
#endif
}
///
/// 判断你的App是否被破解
///
/// 是否破解
public static bool IsPirated()
{
#if UNITY_EDITOR
//always return false in UNITY_EDITOR mode
//Debug.Log("IsPirated always return false in UNITY_EDITOR mode");
return false;
#else
return _IsPirated();
#endif
}
//设置是否开启background模式, 默认true.
//value 为YES,SDK会确保在app进入后台的短暂时间保存日志信息的完整性,对于已支持background模式和一般app不会有影响.
//如果该模式影响某些App在切换到后台的功能,也可将该值设置为false.
public static void SetBackgroundTaskEnabled(bool value)
{
#if UNITY_EDITOR
//Debug.Log("SetBackgroundTaskEnabled");
#elif UNITY_IPHONE
_SetBackgroundTaskEnabled (value);
#endif
}
#endif
#region Wrapper
static private string _AppKey=null;
static private string _ChannelId=null;
static public string AppKey
{
get
{
return _AppKey;
}
}
static public string ChannelId
{
get
{
return _ChannelId;
}
}
static private void CreateUmengManger()
{
GameObject go = new GameObject();
go.AddComponent();
go.name = "UmengManager";
}
#if UNITY_ANDROID
public static void onResume()
{
#if UNITY_EDITOR
#else
Agent.CallStatic("onResume", Context);
#endif
}
public static void onPause()
{
#if UNITY_EDITOR
#else
Agent.CallStatic("onPause", Context);
#endif
}
public static void onKillProcess()
{
#if UNITY_EDITOR
#else
Agent.CallStatic("onKillProcess", Context);
#endif
}
//static AndroidJavaClass AnalyticsConfig = null;
//lazy initialize singleton
static class SingletonHolder
{
public static AndroidJavaClass instance_mobclick;
public static AndroidJavaObject instance_context;
static SingletonHolder()
{
//instance_mobclick will be null if you run in editor mode
//try it on real android device
instance_mobclick = new AndroidJavaClass("com.umeng.analytics.game.UMGameAgent");
//AnalyticsConfig = new AndroidJavaClass("com.umeng.analytics.AnalyticsConfig");
//cls_UnityPlayer and instance_context will be null if you run in editor mode
//try it on real android device
using (AndroidJavaClass cls_UnityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
{
instance_context = cls_UnityPlayer.GetStatic("currentActivity");
}
}
}
private static AndroidJavaObject ToJavaHashMap(Dictionary dic)
{
var hashMap = new AndroidJavaObject("java.util.HashMap");
var putMethod = AndroidJNIHelper.GetMethodID(hashMap.GetRawClass(), "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
var arguments = new object[2];
foreach (var entry in dic)
{
using (var key = new AndroidJavaObject("java.lang.String", entry.Key))
{
using (var val = new AndroidJavaObject("java.lang.String", entry.Value))
{
arguments[0] = key;
arguments[1] = val;
AndroidJNI.CallObjectMethod(hashMap.GetRawObject(), putMethod, AndroidJNIHelper.CreateJNIArgArray(arguments));
}
} // end using
} // end foreach
return hashMap;
}
protected static AndroidJavaClass Agent
{
get
{
//instance_mobclick will be null if you run in editor mode
//try it on real android device
return SingletonHolder.instance_mobclick;
}
}
static AndroidJavaClass _UpdateAgent;
protected static AndroidJavaClass UpdateAgent
{
get
{
if (_UpdateAgent == null)
_UpdateAgent = new AndroidJavaClass("com.umeng.update.UmengUpdateAgent");
return _UpdateAgent;
}
}
protected static AndroidJavaObject Context
{
get
{
//instance_mobclick will be null if you run in editor mode
//try it on real android device
return SingletonHolder.instance_context;
}
}
public static void UMGameAgentInit()
{
var util = new AndroidJavaClass("com.umeng.analytics.UnityUtil");
util.CallStatic("initUnity", Context,AppKey,ChannelId,version);
}
public void Dispose()
{
Agent.Dispose();
Context.Dispose();
}
#endif
#if UNITY_IPHONE
static string DictionaryToJson(Dictionary dict)
{
var builder = new StringBuilder("{");
foreach (KeyValuePair kv in dict)
{
builder.AppendFormat("\"{0}\":\"{1}\",", kv.Key, kv.Value);
}
builder[builder.Length - 1] = '}';
return builder.ToString();
}
[DllImport("__Internal")]
private static extern void _SetAppVersion(string value);
[DllImport("__Internal")]
private static extern void _SetLogEnabled(bool value);
[DllImport("__Internal")]
private static extern void _SetCrashReportEnabled(bool value);
[DllImport("__Internal")]
private static extern void _StartWithAppKeyAndReportPolicyAndChannelId(string appkey, int policy, string channelId,string version);
[DllImport("__Internal")]
private static extern void _SetLogSendInterval(double interval);
[DllImport("__Internal")]
private static extern void _Event(string eventId);
[DllImport("__Internal")]
private static extern void _EventWithDuration(string eventId, int duration);
[DllImport("__Internal")]
private static extern void _EventWithDuration2(string eventId, string Label, int duration);
[DllImport("__Internal")]
private static extern void _EventWithAttributesAndDuration(string eventId, string jsonString, int duration);
[DllImport("__Internal")]
private static extern void _EventWithLabel(string eventId, string label);
[DllImport("__Internal")]
private static extern void _EventWithAccumulation(string eventId, int accumulation);
[DllImport("__Internal")]
private static extern void _EventWithLabelAndAccumulation(string eventId, string label, int accumulation);
[DllImport("__Internal")]
private static extern void _EventWithAttributes(string eventId, string jsonstring);
[DllImport("__Internal")]
private static extern void _BeginEventWithLabel(string eventId, string label);
[DllImport("__Internal")]
private static extern void _EndEventWithLabel(string eventId, string label);
[DllImport("__Internal")]
private static extern void _BeginEventWithPrimarykeyAndAttributes(string eventId, string primaryKey, string jsonstring);
[DllImport("__Internal")]
private static extern void _EndEventWithPrimarykey(string eventId, string primaryKey);
[DllImport("__Internal")]
private static extern void _LogPageViewWithSeconds(string pageName, int seconds);
[DllImport("__Internal")]
private static extern void _BeginLogPageView(string pageName);
[DllImport("__Internal")]
private static extern void _EndLogPageView(string pageName);
[DllImport("__Internal")]
private static extern bool _IsJailBroken();
[DllImport("__Internal")]
private static extern bool _IsPirated();
[DllImport("__Internal")]
private static extern string _GetDeviceID();
[DllImport("__Internal")]
private static extern void _SetBackgroundTaskEnabled(bool value);
[DllImport("__Internal")]
private static extern void _SetEncryptEnabled(bool value);
// [DllImport("__Internal")]
// private static extern void _SetLatency(int value);
[DllImport("__Internal")]
private static extern void _CCEvent(string keyPath,int value,string label);
#endif
#endregion
}
}