android开发检测用户是否使用了虚拟定位
在應用開發中,如果有簽到打卡之類的功能,你是否會遇到檢測用戶是否使用了虛擬定位軟件來進行打卡?如果有,那么請仔細閱讀這篇文章。該文章會帶你認識什么是虛擬定位、什么是應用分身,以及如何通過代碼來檢測用戶是否使用了虛擬定位進行打卡...在寫之前首先要感覺這位博主的分享https://blog.csdn.net/mawei7510/article/details/80250416;他主要寫的是應用分身、應用雙開之類的內容,受他的影響,研究了一下虛擬定位,其實這兩者的原理是一樣的,虛擬定位也是通過一些第三方應用,然后把你自己的應用克隆了一個。啟動的時候需要在第三方的應用里面來啟動,這樣的話在私有文件里面生成的包名勢必會和直接啟動自己的應用有區別,知道了這些,我們將通過以下三個方法來一一檢測;
首先介紹一些那些使用應用分身雙開和虛擬定位的應用和自己的應用在私有目錄下生成的包名有什么區別:
我們知道App的私有目錄是/data/data/包名/或/data/user/用戶號/包名,通過Context.getFilesDir()方法可以拿到私有目錄下的files目錄。在多開環境下,獲取到目錄會變為/data/data/多開App的包名/xxxxxxxx或/data/user/用戶號/多開App的包名/xxxxxxxx。
舉個例子,在我手機上,正常使用App上面的代碼獲取到的路徑為/data/user/0/top.darkness463.virtualcheck/files。在多開分身的多開環境下,路徑為/data/user/0/dkmodel.zom.rxo/virtual/data/user/0/top.darkness463.virtualcheck/files。
當然,多開軟件是可以hook處理讓你拿到正常的目錄,但截至寫這篇文章為止,市面上大部分多開App沒有繞過這項檢測,僅有360家的分身大師可以繞過。
下面開始正式檢測:
1.?ps檢測(詳見https://www.jianshu.com/p/216d65d9971e)
我們先通過執行對uid進行過濾,得到類似下面的結果
?
可以看到在多開環境下,會獲取到自己的包名和多開App的包名這2個包名,通過這些包名去/data/data/下找會找到2個目錄,而正常情況下只能在/data/data/下找到自己的App的目錄。看下具體代碼實現;
public static boolean isRunInVirtual() {String filter = getUidStrFormat();String result = exec("ps");if (result == null || result.isEmpty()) {return false;}String[] lines = result.split("\n");if (lines == null || lines.length <= 0) {return false;}int exitDirCount = 0;for (int i = 0; i < lines.length; i++) {if (lines[i].contains(filter)) {int pkgStartIndex = lines[i].lastIndexOf(" ");String processName = lines[i].substring(pkgStartIndex <= 0? 0 : pkgStartIndex + 1, lines[i].length());File dataFile = new File(String.format("/data/data/%s",processName, Locale.CHINA));if (dataFile.exists()) {exitDirCount++;}}}return exitDirCount > 1; }2.應用列表檢測
這里的應用列表檢測不是指簡單的遍歷應用列表判斷是不是安裝了多開App,我們并不阻止用戶安裝多開App并多開其他App,我們只是不希望用戶多開我們自己的App,因此不能檢測到用戶安裝了多開App就把他干掉。
多開App都會對context.getPackageName()進行處理,讓這個方法返回原始App的包名,因此在被多開的App看來,多開App的包名和原始的那個App的包名一樣,因此在多開環境下遍歷應用列表時會發現包名等于原始App的包名的應用會有兩個。
private boolean checkPkg(Context context) {try {if (context == null) {return false;}int count = 0;String packageName = context.getPackageName();PackageManager pm = context.getPackageManager();List<PackageInfo> pkgs = pm.getInstalledPackages(0);for (PackageInfo info : pkgs) {if (packageName.equals(info.packageName)) {count++;}}return count > 1;} catch (Exception ignore) {}return false; }3.maps檢測
讀取/proc/self/maps,多開App會加載一些自己的so到內存空間,舉個例子,360的分身大師加載了其目錄下的某個so,/data/app/com.qihoo.magic-gdEsg8KRAuJy0MuY18BlqQ==/lib/arm/libbreakpad-jni-1.5.so,通過對各種多開App的包名的匹配,如果maps中有多開App的包名的東西,那么當前就是運行在多開環境下。目前沒有發現多開App繞過該項檢測,但缺點是需要收集所有多開App的包名,一旦多開App改個包名就失效了。
Set<String> virtualPkgs; // 多開第三方App包名列表 private boolean check() {BufferedReader bufr = null;try {bufr = new BufferedReader(new FileReader("/proc/self/maps"));String line;while ((line = bufr.readLine()) != null) {for (String pkg : virtualPkgs) {if (line.contains(pkg)) {return true;}}}} catch (Exception ignore) {} finally {if (bufr != null) {try {bufr.close();} catch (IOException e) {}}}return false; }以上三種檢測方法有的會被第三方虛擬定位軟件或者多開分身軟件躲避掉,有的則不會,所以使用的時候建議三種方法全部用上。好了今天就寫到這里,再次感謝mawei7510的分享;
轉載于:https://www.cnblogs.com/yzssoft/p/9933522.html
總結
以上是生活随笔為你收集整理的android开发检测用户是否使用了虚拟定位的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ML激活函数使用法则
- 下一篇: Party at Hali-Bula(树