在实际项目开发过程中,可能需要收集用户的信息以及用户在APP中产生的所有痕迹,以便于分析用户在APP中的行为,这样可以更好地指导我们去更新APP,做出更好的APP。
但是,我们在开发中,难免会出现需要屏蔽测试用户的信息,这个其实有一些曲线救国的方式,比如:
1、拿到我们测试机型的IDFA,通过IDFA将测试产生的数据都排除掉,以免影响数据分析。这个方式的缺点就是IDFA也许会自动化变,目前知道的情况是,用户手机系统升级时,可能会变。还有一个情况是,用户主动将广告跟踪的选项关闭,如果再次开启,IDFA就肯定也变了。一般情况,自己的测试机器主要还是系统升级,然后不可避免的使IDFA变了,这就导致我们每隔一段时间就需要获取一下所有测试机器的IDFA,也是一个比较麻烦的事。
2、另外一个方式,就是通过版本号去做,比如设定某个版本为测试版本,待测试完毕之后,将版本提高,然后提交。这个方式好处是可以一次性解决IDFA变化的问题,但是版本管理起来也是不方便的,尤其在正式版本可能侧出问题了,那么版本号就又要继续增加。
以上两种方式基本是常用手段,个人在想到IOS是可以检测手机是否安装了某个应用的,从这一点出发,我们可以将测试手机都安装一个特定的APP,专门用于其他APP检测只用。
这样,我们可以通过判断用户是否安装了检测APP来判断这个用户是否为测试用户。这么做,就可以避免人工方面的失误!
下面是关于如何给检测APP添加Schemes,其他应用就可以通过 canOpenURL 来判断是否安装了 检测APP ,以此判断测试用户:
1、使用Unity创建一个空项目,项目名可以随意。
2、设置好基本信息之后(PlayerSettings),导出为xCode工程,然后找到Info标签,最Info这一页最下方的URL Types,点击“+”号,在Identifier 填写这个应用的boundle id,也就是常用的“com.xxx.xxx”,然后在URL Schemes这一项填一个自己可以识别的字符串,“checkinstall”;
3、设置好之后,运行xCode,将这个APP安装到测试手机上;
4、安装好之后,我们可以通过苹果自带的浏览器调用下,看看能否打开:" checkinstall:// ",如果能打开,说明配置就没问题了;
下面是第二步,我们需要在其他应用里面增加一个检测上面应用的功能:
1、首先,我们需要写一个原生的类,用来调用 canOpenURL,带上一个参数,返回是否安装的结果:
@implementation CheckInstall
+ (bool)IsInstallApp:(NSString*)appId{
NSURL* appURL = [NSURL URLWithString:appId];
if ([[UIApplication sharedApplication] canOpenURL:appURL]){
return YES;
}
return NO;
}
@end
extern "C"{
const bool _IsInstallApp(char* schemes){
NSString *sch = [NSString stringWithUTF8String: schemes];
return [CheckInstall IsInstallApp: sch];
}
}
2、在C#端,创建一个类,用于衔接上面OC的接口:
public class CheckInstallApp: MonoBehaviour {
private static CheckInstallApp _instance = null;
public static CheckInstallApp Instance {
get {
if (_instance == null) {
_instance = GameObject.FindObjectOfType(typeof(CheckInstallApp)) as CheckInstallApp;
if (_instance == null) {
_instance = new GameObject ().AddComponent<CheckInstallApp> ();
_instance.gameObject.name = _instance.GetType ().FullName;
}
}
return _instance;
}
}
[DllImport ("__Internal")]
private static extern bool _GJC_IsInstallApp(string appID);
public bool IsInstallApp(string schemes){
#if UNITY_IPHONE && !UNITY_EDITOR
return _IsInstallApp(schemes);
#else
return false;
#endif
}
}
3、在需要调用的地方,直接调用:
CheckInstallApp.Instance.IsInstallApp("checkinstall://");
4、到处xCode工程之后,如果是IOS9.0以上,我们还需要把 checkinstall 加入到应用的白名单中,具体地方是在Info标签,在这个页面添加一个key为“LSApplicationQueriesSchemes”的项,它是Array的,然后在这个Array里面添加一个,字符串就是我们上面设置的“checkinstall”,结果如下:
5、运行App,点击调用了 IsInstallApp 的按钮,我们就能知道返回的是 True 或者 False了,这样我们就能判断是否为测试用户来。
另外,如果觉得手动添加麻烦,也可以用自动添加,Unity在导出xCode工程之后,会回调一个函数“OnPostprocessBuild”,我们在Unity工程里面的Editor文件夹下面创建一个脚本,然后重写这个函数:
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEditor.iOS.Xcode;
#endif
using System.IO;
public static class XCodePostProcess {
#if UNITY_EDITOR
[PostProcessBuildAttribute(100)]
public static void OnPostprocessBuild(BuildTarget target, string pathToBuiltProject) {
if (target != BuildTarget.iOS){
Debug.LogWarning("Target is not iphone, XCodePostProcess will not run");
return;
}
//得到xcode工程的路径
string path = Path.GetFullPath(pathToBuiltProject);
//编辑info.plist文件
EditorPlist(path);
}
private static void EditorPlist(string filePath)
{
filePath = Path.Combine(filePath, "info.plist");
if (!File.Exists(filePath)){
Debug.LogError(filePath + " 路径下文件不存在");
return;
}
PlistDocument plist = new PlistDocument();
plist.ReadFromString(File.ReadAllText(filePath));
PlistElementDict rootDict = plist.root;
string listschemesKey = "LSApplicationQueriesSchemes";
if (rootDict.values.ContainsKey(listschemesKey)){
bool blnContains = false;
PlistElementArray pea = rootDict.values[listschemesKey].AsArray();
for(int i=0;i<pea.values.Count;i++){
if (pea.values[i].AsString() == "checkinstall"){
blnContains = true;
break;
}
}
if (!blnContains){
rootDict.values[listschemesKey].AsArray().AddString("checkinstall");
}
}else{
PlistElementArray pea = new PlistElementArray();
pea.AddString("checkinstall");
rootDict.values.Add(listschemesKey, pea);
}
File.WriteAllText(filePath, plist.WriteToString());
}
#endif
}
完工~