android 修改gps坐标,[原创] 改机 - 从源码着手任意修改GPS地理位置
改機(jī) - 從源碼著手任意修改GPS地理位置
需求:隨意修改定位
android在改機(jī)過程中,經(jīng)常會遇到隨意修改位置GPS的需求。
修改GPS的方式有很多種:
xposed hook
MockLocation
修改源碼
以上三種方式都能修改gps隨意修改gps坐標(biāo),各有優(yōu)缺點(diǎn):xposed隱藏不好,容易被發(fā)現(xiàn);MockLocation容易在開發(fā)者模式和gps provider被識別;改源碼,編譯麻煩,而且不一定有源碼;前兩種方式具有普適性,改源碼費(fèi)時(shí)費(fèi)力,局限性比較強(qiáng);
秉承明知山有虎,偏向虎上行的心態(tài),嘗試閱讀以下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位置變化回調(diào)函數(shù)
Return gnssStatusCb(const IGnssCallback::GnssStatusValue status) override; // gps狀態(tài)變化回調(diào)函數(shù)
Return gnssSvStatusCb(const IGnssCallback::GnssSvStatus& svStatus) override; // 衛(wèi)星狀態(tài)變化回調(diào)函數(shù)
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模塊位置、狀態(tài)、精度等信息變化后,通知上層應(yīng)用的回調(diào)函數(shù)類。
2. framework
可以發(fā)現(xiàn),在gps硬件模塊拿到新的位置時(shí),通知framework調(diào)用java的函數(shù)是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系統(tǒng)就獲取到了一個(gè)地理位置。原理了解后,就可以動手修改源碼了。
3. 切斷hal層調(diào)用
GnssLocationProvider.cpp
#include
// ....... 省略
Return GnssCallback::gnssLocationCbImpl(const T& location) {
// 定義一個(gè)系統(tǒng)開關(guān),可以自由控制
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中添加一個(gè)public函數(shù)
LocationManager.java
// ...... 省略
public void reportCustomLocation(Location location) {
mService.reportLocation(true, location);
}
5. 編譯rommake update-api # 在LocationManager中添加了新的接口
make -j32 # 炫耀一下我32核的的機(jī)器
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 好像不太好用
總結(jié)
以上是生活随笔為你收集整理的android 修改gps坐标,[原创] 改机 - 从源码着手任意修改GPS地理位置的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python如何调用hslcommuni
- 下一篇: Autodesk 360 Mobile不