android修改gps坐标,[原创]改机-从源码着⼿任意修改GPS地理
位置
改机 - 从源码着⼿任意修改GPS地理位置
需求:随意修改定位
android在改机过程中,经常会遇到随意修改位置GPS的需求。
修改GPS的⽅式有很多种:
xpod hook
MockLocation
修改源码
以上三种⽅式都能修改gps随意修改gps坐标,各有优缺点:xpod隐藏不好,容易被发现;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 gnssReleaWakelockCb() 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 = Speed() > 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(fal);
return;
}
if (VERBOSE) Log.v(TAG, "reportLocation " + String());
synchronized (mLocation) {
mLocation = location;
/
/ It would be nice to push the elapd real-time timestamp
// further down the stack, but this is still uful
热爱祖国的作文mLocation.tElapdRealtimeNanos(SystemClock.elapdRealtimeNanos());
mLocation.tExtras(mLocationExtras);
try {
} catch (RemoteException e) {
Log.e(TAG, "RemoteException calling reportLocation");
}
}
mGnssMetrics.logReceivedLocationStatus(hasLatLong);
if (hasLatLong) {
if (location.hasAccuracy()) {
mGnssMetrics.Accuracy());
}
if (mTimeToFirstFix > 0) {
int timeBetweenFixes = (int) (SystemClock.elapdRealtime() - mLastFixTime); mGnssMetrics.logMisdReports(mFixInterval, timeBetweenFixes);
}
}
mLastFixTime = SystemClock.elapdRealtime();
// 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
}
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);
}
// nd 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.ndBroadcastAsUr(intent, UrHandle.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) {
}
理想的诗歌5. 编译rommake update-api # 在LocationManager中添加了新的接⼝make -j32 # 炫耀⼀下我32核的的机器
5. 在APK中使⽤
MainActivity.java
服装搭配技巧// ...... 省略
Button btn = findViewById(st_btn);
btn.tOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try {
Location l = new Location("gps");
l.tLatitude(41.055962);
l.tLongitude(110.307711);
l.tAccuracy(2.0f);
l.tTime(System.currentTimeMillis());简历样版
l.tElapdRealtimeNanos(System.currentTimeMillis());
l.tAccuracy(1.0f);
Location lo = LastKnownLocation(provider); Log.d(TAG, lo.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
最后于 2020-6-29 11:04
被neocanable编辑
,原因: markdown 好像不太好⽤