android 修改gps坐标,[原创] 改机 - 从源码着手任意修改GPS地理位置

本文介绍了如何通过修改Android源码来实现任意修改GPS地理位置,包括在jni层切断hal与framework的通讯,以及在framework中添加公共函数以报告自定义位置。
AI助手已提取文章相关产品:

改机 - 从源码着手任意修改GPS地理位置

需求:随意修改定位

android在改机过程中,经常会遇到随意修改位置GPS的需求。

修改GPS的方式有很多种:

xposed hook

MockLocation

修改源码

以上三种方式都能修改gps随意修改gps坐标,各有优缺点:xposed隐藏不好,容易被发现;MockLocation容易在开发者模式和gps provider被识别;改源码,编译麻烦,而且不一定有源码;前两种方式具有普适性,改源码费时费力,局限性比较强;

秉承明知山有虎,偏向虎上行的心态,尝试阅读以下android的源码,并且修改gps部分的代码;

具体原理:切断hal层和framework之间的通讯,模仿硬件向framework通知硬件信息

样例:android 8.0

1. gps jni callbackstruct GnssCallback : public IGnssCallback {

Return gnssLocationCb(

const android::hardware::gnss::V1_0::GnssLocation& location) override; // gps位置变化回调函数

Return gnssStatusCb(const IGnssCallback::GnssStatusValue status) override; // gps状态变化回调函数

Return gnssSvStatusCb(const IGnssCallback::GnssSvStatus& svStatus) override; // 卫星状态变化回调函数

Return gnssNmeaCb(int64_t timestamp, const android::hardware::hidl_string& nmea) override;

Return gnssSetCapabilitesCb(uint32_t capabilities) override;

Return gnssAcquireWakelockCb() override;

Return gnssReleaseWakelockCb() override;

Return gnssRequestTimeCb() override;

Return gnssSetSystemInfoCb(const IGnssCallback::GnssSystemInfo& info) override;

static GnssSvInfo sGnssSvList[static_cast(

android::hardware::gnss::V1_0::GnssMax::SVS_COUNT)];

static size_t sGnssSvListSize;

static const char* sNmeaString;

static size_t sNmeaStringLength;

};

// 省略......

Return GnssCallback::gnssLocationCbImpl(const T& location) {

JNIEnv* env = getJniEnv();

jobject jLocation = translateGnssLocation(env, location);

env->CallVoidMethod(mCallbacksObj,

method_reportLocation, // frameworks

boolToJbool(hasLatLong(location)),

jLocation);

checkAndClearExceptionFromCallback(env, __FUNCTION__);

env->DeleteLocalRef(jLocation);

return Void();

}

// 省略......

method_reportLocation = env->GetMethodID(clazz, "reportLocation",

"(ZLandroid/location/Location;)V");

GnssCallback的作用就是在gps模块位置、状态、精度等信息变化后,通知上层应用的回调函数类。

2. framework

可以发现,在gps硬件模块拿到新的位置时,通知framework调用java的函数是reportLocation, 源码如下:

/*

* @hasLatLong: 地理位置是否合法

* @loction: 地理位置

*/

private void reportLocation(boolean hasLatLong, Location location) {

if (location.hasSpeed()) {

mItarSpeedLimitExceeded = location.getSpeed() > ITAR_SPEED_LIMIT_METERS_PER_SECOND;

}

if (mItarSpeedLimitExceeded) {

Log.i(TAG, "Hal reported a speed in excess of ITAR limit." +

" GPS/GNSS Navigation output blocked.");

mGnssMetrics.logReceivedLocationStatus(false);

return;

}

if (VERBOSE) Log.v(TAG, "reportLocation " + location.toString());

synchronized (mLocation) {

mLocation = location;

// It would be nice to push the elapsed real-time timestamp

// further down the stack, but this is still useful

mLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());

mLocation.setExtras(mLocationExtras);

try {

mILocationManager.reportLocation(mLocation, false);

} catch (RemoteException e) {

Log.e(TAG, "RemoteException calling reportLocation");

}

}

mGnssMetrics.logReceivedLocationStatus(hasLatLong);

if (hasLatLong) {

if (location.hasAccuracy()) {

mGnssMetrics.logPositionAccuracyMeters(location.getAccuracy());

}

if (mTimeToFirstFix > 0) {

int timeBetweenFixes = (int) (SystemClock.elapsedRealtime() - mLastFixTime);

mGnssMetrics.logMissedReports(mFixInterval, timeBetweenFixes);

}

}

mLastFixTime = SystemClock.elapsedRealtime();

// report time to first fix

if (mTimeToFirstFix == 0 && hasLatLong) {

mTimeToFirstFix = (int)(mLastFixTime - mFixRequestTime);

if (DEBUG) Log.d(TAG, "TTFF: " + mTimeToFirstFix);

mGnssMetrics.logTimeToFirstFixMilliSecs(mTimeToFirstFix);

// notify status listeners

mListenerHelper.onFirstFix(mTimeToFirstFix);

}

if (mSingleShot) {

stopNavigating();

}

if (mStarted && mStatus != LocationProvider.AVAILABLE) {

// we want to time out if we do not receive a fix

// within the time out and we are requesting infrequent fixes

if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mFixInterval < NO_FIX_TIMEOUT) {

mAlarmManager.cancel(mTimeoutIntent);

}

// send an intent to notify that the GPS is receiving fixes.

Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);

intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, true);

mContext.sendBroadcastAsUser(intent, UserHandle.ALL);

updateStatus(LocationProvider.AVAILABLE, mSvCount, mMeanCn0, mMaxCn0);

}

if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mStarted &&

mFixInterval > GPS_POLLING_THRESHOLD_INTERVAL) {

if (DEBUG) Log.d(TAG, "got fix, hibernating");

hibernate();

}

}

自此,刨除hal层,android系统就获取到了一个地理位置。原理了解后,就可以动手修改源码了。

3. 切断hal层调用

GnssLocationProvider.cpp

#include

// ....... 省略

Return GnssCallback::gnssLocationCbImpl(const T& location) {

// 定义一个系统开关,可以自由控制

char property[PROP_VALUE_MAX];

int len = __system_property_get("gps.location.custom", property);

if(len > 0) {

if(strcmp(property, "1") == 0) return Void();

}

// ...... 省略

}

4. 在framework中添加一个public函数

LocationManager.java

// ...... 省略

public void reportCustomLocation(Location location) {

mService.reportLocation(true, location);

}

5. 编译rommake update-api # 在LocationManager中添加了新的接口

make -j32 # 炫耀一下我32核的的机器

5. 在APK中使用

MainActivity.java

// ...... 省略

Button btn = findViewById(R.id.test_btn);

btn.setOnClickListener(new View.OnClickListener() {

public void onClick(View v) {

try {

Location l = new Location("gps");

l.setLatitude(41.055962);

l.setLongitude(110.307711);

l.setAccuracy(2.0f);

l.setTime(System.currentTimeMillis());

l.setElapsedRealtimeNanos(System.currentTimeMillis());

l.setAccuracy(1.0f);

locationManager.reportCustomLocation(l);

Location lo = locationManager.getLastKnownLocation(provider);

Log.d(TAG, lo.toString());

} catch (Exception e) {

e.printStackTrace();

}

}

});

}

最后于 2020-6-29 11:04

被neocanable编辑

,原因: markdown 好像不太好用

您可能感兴趣的与本文相关内容

Android应用源码安卓源码(172个合集),可以做为你的学习参考。 365MobileSecretary v1.0.6(365手助手AIDL) 888个经典 Logo.rar AdXmpp(Openfire+asmack+spark) .zip AidlDemo(简单aidl的例子) aidl跨进程调用.rar andbatdog电池监控.rar andbatdog监视电池.rar andricoFacebook客户端.rar Android Gamex分析报告.rar Android 英语单词记忆程序源码 AndroidPdfViewerPDF查看器.zip AndroidPlayer(仿酷狗播放器).tar androidtalk_2010_11_17【Sundy系列】全看懂了-加两年经验-语音朗读-语音识别-语音.rar Android下的信息客户端 WhisperSystems-TextSecure.zip Android与js交互.rar Android中监听电话状态.rar Android之Wifi学习教程.rar Android之用PopupWindow实现弹出菜单.rar android在wifi下手与电脑的socket通信.rar android多线程断点下载.rar Android一键Root原理分析.zip Android的VoIP客户端 Sipdroid.rar Android有未接来电后处理(判断未接来电).rar Android模仿乐淘的应用程序分析源码.zip Android游戏源码——忍者快跑.rar Android自动发送短信.rar Android自动开关实现.rar Android视频采集+RTSP完整代码(可用) Android远程登录含有loading登录效.zip Angle v1.0_2D游戏引擎.ZIP BOOK看遍所有UI控件.7z BrewClock闹钟.zip BTAndroidWebViewSelection(webview选择文字) cellmap v2.0 基站查询定位导航系统 .rar DialogShow.rar dialog去除边框代码.rar DocumentViewer(PDF阅读器) douBanList(滚动到底部加载新的,软缓存,懒加载) Droid Wall 手防火墙.zip FBReader修改epub快速加载.rar FiveChess五子棋.zip Flashlight灯光.zip GetSDTree(简单SD卡文件浏览器) hotel宾馆系统.zip ImageView 图片循环跑马灯的效果.rar ipcamera-for-android变成IP Camera.rar jamendo-开源在线音乐.rar jchat4android聊天程序.rar LoginXml.rar MineSweeper由java实现.zip miniTwitter登录界面.rar MyAppWeixin(仿微信界面) MyBrowser(简单网页浏览器) Myjob3(图片剪辑功能).rar OPENG开发的示例代码.rar OpenSudoku一个简单的九宫格数独游戏.zip OssSystem(OA系统图书管理简单版).rar Phonegap+HTML5+CSS3+jQuer简单界面模板示例及源码.rar ProgressBar 几乎全部的用法.rar QQ_UI之分类菜单DEMO.zip QQ的登录界面 源代码 .zip quitesleep手电话功能软件.rar rokon_src_2-0-3_游戏引擎.zip scientific-calculator-for-android( 功能强大的科学计算器).zip SeeJoPlayer(播放器).7z SipDroid客户端源码.rar sipdroid语音及视频通话.rar tablelogin(登陆界面).rar TankWar坦克大战.zip telecapoland-jamendo-android-6cd07fb(国外开源音乐播放器) TorProxy应用实现了Android无线电电传通讯(TOR).rar UI设计之 仿做蘑菇街UI设计 源码.zip ViewPager-实现左右两个屏幕的切换.rar VIEW双缓冲与SurfaceView比较.zip weibo4andriod-2011-01-14.zip WordPress for Android zirco-browser浏览器源码.rar Zirco-browser:超越海豚的开源浏览器.rar zz-doctor中医大夫助
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值