/// <summary> /// Android系统一个app一个uid,如果同一uid下有两个进程对应的包名,在"/data/data"下有两个私有目录,则该应用被多开了 /// </summary> /// <returns></returns> public static bool CheckByHasSameUid() { if (mCheckByHasSameUid.HasValue) { return(mCheckByHasSameUid.Value); } var filter = GetUidStrFormat(); if (string.IsNullOrWhiteSpace(filter)) { return(false); } var result = CommandUtil.Exec("ps"); if (string.IsNullOrWhiteSpace(result)) { return(false); } #pragma warning disable CS8602 // 取消引用可能出现的空引用。 var lines = result.Split(new[] { "\n" }, StringSplitOptions.RemoveEmptyEntries); #pragma warning restore CS8602 // 取消引用可能出现的空引用。 if (lines == null || lines.Length <= 0) { return(false); } var exitDirCount = 0; for (int i = 0; i < lines.Length; i++) { if (lines[i].Contains(filter, StringComparison.OrdinalIgnoreCase)) { var pkgStartIndex = lines[i].LastIndexOf(" "); var processName = lines[i].JavaSubstring( pkgStartIndex <= 0 ? 0 : pkgStartIndex + 1, lines[i].Length); using var dataFile = new Java.IO.File($"/data/data/{processName}"); if (dataFile.Exists()) { exitDirCount++; } } if (exitDirCount > 1) { mCheckByHasSameUid = true; return(mCheckByHasSameUid.Value); } } mCheckByHasSameUid = exitDirCount > 1; return(mCheckByHasSameUid.Value); }
static string?GetUidStrFormat() { var filter = CommandUtil.Exec("cat /proc/self/cgroup"); if (string.IsNullOrWhiteSpace(filter)) { return(null); } #pragma warning disable CS8604 // 可能的 null 引用参数。 var filter2 = filter.ToJavaString(); #pragma warning restore CS8604 // 可能的 null 引用参数。 int uidStartIndex = filter2.LastIndexOf("uid"); int uidEndIndex = filter2.LastIndexOf("/pid"); if (uidStartIndex < 0) { return(null); } if (uidEndIndex <= 0) { uidEndIndex = filter2.Length(); } filter2 = filter2.Substring(uidStartIndex + 4, uidEndIndex).ToJavaString(); try { var strUid = filter2.ReplaceAll("\n", ""); var uid = strUid.TryParseInt32(); if (uid.HasValue) { return(Java.Lang.String.Format("u0_a%d", uid - 10000)); } } catch (Java.Lang.Throwable t) { t.PrintStackTraceWhenDebug(); } return(null); }