前段时间任天堂发布的首款移动平台AR游戏——Pokemon Go,这款游戏不仅是借助宠物小精灵粉这个众多怀旧粉的IP,更多的人也是因为先体验当前大热的AR和VR技术热潮带来的改变,这款游戏无可厚非地在短时间内产生了巨大的效应。这篇文章打算针对技术宅们,聊聊自己的解决思路,实际是基于xposed进行了实现,希望能够起到抛砖引玉的效果,欢迎大家交流。
关于游戏锁区
由于游戏上线初期,为了避免大量用户涌入对服务器造成的巨大压力,任天堂选择了分区域开放游戏的同时,针对部分区域还进行了锁区。至于为什么锁区,这里就不继续黑了,但有一点毫无疑问,中国肯定是其中之一。
国内android用户的玩法
很多国内用户为了体验Pokemon Go在满大街抓小精灵的“快感”,不得不去试验网上各种的教程,什么个人信息安全都先放一边。
android用户体验:虽然国内应用市场没发布,但还是很容易找到apk包安装,由于需要Google地图的支持,首先不得不刷去个gapps,搞定谷歌服务后还得翻墙,所以VPN肯定少不了。一切搞定后,打开游戏~没问题!直接用google账户登入~成功!进入游戏界面~速度很快,正准备浪起来,但是!但是!但是!卧槽,周围怎么一个小精灵和道馆都没有!说好的满大街收集小精灵呢~
Pokemon Go锁区,不是封锁了登陆的ip地址或是google账号,其实是锁了几个坐标范围,因此我们需要模拟位置到锁区外才能愉快地找小精灵。
技术宅拯救世界
技术宅拯救世界这句第一次出现的时候已经无法考证了。但是就目前而言,能够拯救世界的,大概只有技术宅了。当然还有春哥,七颗龙珠。 ————萌娘百科
下面用Xposed实现模拟位置信息成功开飞机到澳大利亚,通过屏幕上悬浮按钮手动控制当前人物移动并成功收集到小精灵。不怕开飞机导致被封号的,可以先来看看实际使用效果:
下面介绍如何一步一步地实现对Pokemon Go的锁区的突破。
应用反编译分析
Android获取位置信息的来源包含多个维度(GPS,WIFI,移动网络),通过反编译Pokemon Go的apk包,查看项目源码可知:1.其通过android系统API提供的LocationManager类,调用getLastKnownLocation方法来获取位置信息对象Location。
而最终获取位置经纬度的方法则是调用Location类的getLatitude()和getLongitude()方法来实现,获取经纬度相关信息后应用就会针对当前的位置坐标进行判断,如果不在游戏开放区域内,将无法请求到相应的游戏数据(表现出来就是玩家无法在锁区内找到宠物小精灵)。
下面根据从反编译得到的得到的相关信息,考虑如何针对应用进行位置模拟或更改,突破其位置锁区的封闭。
两种实现方式——基于Xposed
因为游戏最先在澳大利亚开放,所以demo的实现演示如何开飞机到堪培拉去抓小精灵,下面介绍目前自己能想到的两种实现方式。
方式一:位置偏移转化
该方式简单来说就是对获取位置方法的hook,让本地GPS偏移转化成目标地的位置信息变化。首先需要事先计算锁区内(天朝某地)与未锁区目标地(堪培拉)的地理位置坐标差,设置好相对合理modify偏移值,再利用设备获取到的实际GPS定位信息,使用Xposed对Pokemon Go获取位置信息的方法进行hook,对实际的位置数据进行向目标位置的偏移处理,实现从本地GPS到目标地位置的信息转化:
具体的转化公式:(demo是广州转化到堪培拉,google地图提供的经纬度坐标数据)
广州位置坐标:lat_gz = 23.129042, long_gz = 113.264435
堪培拉位置坐标:lat_cap = -35.302747, long_cap = 149.125318
modify坐标差:modify_lat = 58.431789 modify_long = 35.860883
修正值:corrected = 0.000868
转化公式 :convertLocation.latitude = localLocation.latitude - modify_lat + corrected convertLocation.longtitude = localLocation.longtitude + modify_long + corrected
具体的编码实现
方式二:位置信息模拟
Android开发者调试模式中有用于位置模拟的接口,可以利用相关的api直接进行模拟位置信息,通过结合悬浮控制按钮可以实现手动控制游戏人物位置。
LocationManager.setTestProviderLocation(providerName,localLocation);//设置模拟位置信息的方法,参数localLocation为传入的模拟位置location。
需要在开发者选项中开启位置模拟:
如果直接使用模拟位置的方法,系统也提供有相应的检测方法,Pokemon Go会判断是否开启了位置模拟,如果检测到是模拟位置还是无法解决锁区的问题,所以需要对相关检测方法进行hook,下面是使用xposed对判断是否开启了位置模拟的方法hook的编码实现:
结语
由于是文章中介绍的基于xposed进行了实现,所以对于普通玩家来说,使用起来的门槛还是先对较高,所以相关的demo也不打算开放出来,当然如果有朋友想要体验一下的,也可以给我留言,我私下会发一下。所以主要目的是针对技术宅们,提供点自己的解决思路,很多细节的处理当然也有不同的实现方式,后续会对xposed的实际使用和实现细节写一篇纯技术文章,相关的源码也会在整理push到github。希望能够起到抛砖引玉的效果,欢迎大家交流。