Commit 1eca0652 authored by Administrator's avatar Administrator

定位,经纬度数据同步完成

parent 39366e74
...@@ -49,12 +49,10 @@ android { ...@@ -49,12 +49,10 @@ android {
dependencies { dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs') implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation fileTree(include: ['*.aar'], dir: 'libs') implementation fileTree(include: ['*.aar'], dir: 'libs')
provided files('jar/XposedBridgeApi-54.jar')
// implementation(name: 'BaiduLBS_aar_android', ext: 'aar')
// jniLibs.srcDir 'src/main/jniLibs'
implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'com.android.support:appcompat-v7:28.0.0'
//implementation 'com.android.support.constraint:constraint-layout:2.0.0-rc1' //implementation 'com.android.support.constraint:constraint-layout:2.0.0-rc1'
implementation 'com.android.support:cardview-v7:28.0.0' implementation 'com.android.support:cardview-v7:28.0.0'
implementation 'com.android.support:recyclerview-v7:28.0.0' implementation 'com.android.support:recyclerview-v7:28.0.0'
implementation 'com.android.support:design:28.0.0' implementation 'com.android.support:design:28.0.0'
compileOnly 'com.virjar:ratel-api:1.3.4'
} }
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
<!-- 模块描述 --> <!-- 模块描述 -->
<meta-data <meta-data
android:name="xposeddescription" android:name="xposeddescription"
android:value="微信运行虚拟定位"/> android:value="虚拟定位"/>
<!-- XposedBridgeApi的最低版本号 --> <!-- XposedBridgeApi的最低版本号 -->
<meta-data <meta-data
...@@ -65,6 +65,13 @@ ...@@ -65,6 +65,13 @@
</activity> </activity>
<activity android:name="top.littlerich.virtuallocation.activity.AppsActivity"> <activity android:name="top.littlerich.virtuallocation.activity.AppsActivity">
</activity> </activity>
<provider
android:name="top.littlerich.virtuallocation.service.GPSContentProvider"
android:authorities="com.virjar.ratel.virtuallocation"
android:exported="true"
android:grantUriPermissions="true"
tools:ignore="ExportedContentProvider" />
</application> </application>
</manifest> </manifest>
\ No newline at end of file
package top.littlerich.virtuallocation; package top.littlerich.virtuallocation;
import android.content.Context; import android.location.Location;
import android.util.Log; import android.util.Log;
import de.robv.android.xposed.IXposedHookLoadPackage; import com.virjar.ratel.api.RatelToolKit;
import de.robv.android.xposed.XC_MethodHook; import com.virjar.ratel.api.inspect.ClassLoadMonitor;
import de.robv.android.xposed.XposedHelpers; import com.virjar.ratel.api.rposed.IRposedHookLoadPackage;
import de.robv.android.xposed.callbacks.XC_LoadPackage; import com.virjar.ratel.api.rposed.RC_MethodHook;
import top.littlerich.virtuallocation.presenter.HookApis; import com.virjar.ratel.api.rposed.RposedBridge;
import top.littlerich.virtuallocation.presenter.SdkHookManager; import com.virjar.ratel.api.rposed.RposedHelpers;
import top.littlerich.virtuallocation.util.XposedUtil; import com.virjar.ratel.api.rposed.callbacks.RC_LoadPackage;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import top.littlerich.virtuallocation.common.AppApplication;
/** /**
* Created by xuqingfu on 2017/4/15. * Created by xuqingfu on 2017/4/15.
*/ */
public class XPosedPlugin implements IXposedHookLoadPackage { public class XPosedPlugin implements IRposedHookLoadPackage {
private static final String TAG = "silence"; private static final String TAG = AppApplication.tag;
@Override @Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable { public void handleLoadPackage(RC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
if (!XposedUtil.isNeedHook(loadPackageParam.packageName)) { //过滤程序
return;
}
Log.i(TAG, "加载Hook程序:" + loadPackageParam.packageName); Log.i(TAG, "加载Hook程序:" + loadPackageParam.packageName);
SdkHookManager.findMethodIsFromMockProvider(); AppApplication.queryMockGPS(RatelToolKit.sContext);
if (AppApplication.mockGPS == null) {
Log.i(TAG, "未配置虚拟定位");
return;
}
Log.i(TAG, "虚拟定位位置:" + AppApplication.mockGPS.mLongitude + "," + AppApplication.mockGPS.mLatitude);
SdkHookManager.findMethodGetInt(loadPackageParam); handleGaoDeMap();
handleBaiduMap();
XposedHelpers.findAndHookMethod("android.app.Application", loadPackageParam.classLoader, "attach", Context.class, new XC_MethodHook() { ClassLoadMonitor.addClassLoadMonitor(new ClassLoadMonitor.OnClassLoader() {
@Override @Override
protected void afterHookedMethod(XC_MethodHook.MethodHookParam param) throws Throwable { public void onClassLoad(Class<?> clazz) {
super.afterHookedMethod(param); // if (clazz.getName().contains("location")) {
Log.v(TAG, "启动程序:" + param.thisObject.toString()); // Log.i(AppApplication.tag, "init class: " + clazz.getName());
ClassLoader appClassLoader = ((Context)param.args[0]).getClassLoader(); // }
try {
HookApis.findMethodAmapLongitudeAndLatitude(appClassLoader);
}
catch(Exception e) {
Log.e(TAG, "Hook发生异常:" + e.toString());
}
} }
}); });
}
private static void handleBaiduMap() {
//com.baidu.location.LocationClient.registerLocationListener(com.baidu.location.BDLocationListener)
//com.baidu.location.LocationClient.registerLocationListener(com.baidu.location.BDAbstractLocationListener)
ClassLoadMonitor.addClassLoadMonitor("com.baidu.location.LocationClient", new ClassLoadMonitor.OnClassLoader() {
@Override
public void onClassLoad(Class<?> clazz) {
Log.i(AppApplication.tag, "命中百度API:" + clazz);
RposedBridge.hookAllMethods(clazz, "registerLocationListener", new RC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
//TODO param.parameterTypes is null
Method method = (Method) param.method;
param.parameterTypes = method.getParameterTypes();
final Object originListener = param.args[0];
if (originListener == null) {
return;
}
Class<?> BDLocationLikeListener = param.parameterTypes[0];
if (RatelToolKit.dexMakerProxyBuilderHelper.isProxyClass(originListener.getClass())) {
return;
}
InvocationHandler invocationHandler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("onReceiveLocation")) {
// void onReceiveLocation(AMapLocation var1);
for (Object obj : args) {
//com.baidu.location.BDLocation final的,所以不需要考虑被继承了
if (!(obj.getClass().getName().equals("com.baidu.location.BDLocation"))) {
continue;
}
//location.setLatitude();
//location.setLongitude();
RposedHelpers.callMethod(obj, "setLatitude", AppApplication.mockGPS.mLatitude);
RposedHelpers.callMethod(obj, "setLongitude", AppApplication.mockGPS.mLongitude);
}
}
return RposedHelpers.callMethod(originListener, method.getName(), args);
}
};
Object proxyListener;
if (BDLocationLikeListener.isInterface()) {
proxyListener = Proxy.newProxyInstance(BDLocationLikeListener.getClassLoader(),
new Class[]{BDLocationLikeListener}, invocationHandler
);
} else {
proxyListener = RatelToolKit.dexMakerProxyBuilderHelper
.forClass(BDLocationLikeListener)
.parentClassLoader(BDLocationLikeListener.getClassLoader())
.onlyMethods(BDLocationLikeListener.getDeclaredMethods())
.handler(invocationHandler).build();
}
param.args[0] = proxyListener;
}
});
}
});
} }
private static void handleGaoDeMap() {
//com.amap.api.location.AMapLocationClient.setLocationListener(com.amap.api.location.AMapLocationListener lis)
ClassLoadMonitor.addClassLoadMonitor("com.amap.api.location.AMapLocationClient", new ClassLoadMonitor.OnClassLoader() {
@Override
public void onClassLoad(Class<?> clazz) {
Log.i(AppApplication.tag, "命中高德API:" + clazz);
RposedHelpers.findAndHookMethod(clazz, "setLocationListener",
"com.amap.api.location.AMapLocationListener",
new RC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
//TODO param.parameterTypes is null
Method method = (Method) param.method;
param.parameterTypes = method.getParameterTypes();
Class<?> aMapLocationListenerInterfaceClass = param.parameterTypes[0];
final Object originListener = param.args[0];
if (originListener == null) {
Log.i(AppApplication.tag, "originListener is null");
return;
}
Log.i(AppApplication.tag, "原始定位回掉监听器:" + originListener.getClass().getName());
if (RatelToolKit.dexMakerProxyBuilderHelper.isProxyClass(originListener.getClass())) {
Log.i(AppApplication.tag, "this is proxyClass");
return;
}
InvocationHandler invocationHandler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("onLocationChanged")) {
Log.i(AppApplication.tag, "回掉onLocationChanged");
// void onLocationChanged(AMapLocation var1);
for (Object obj : args) {
if (!(obj instanceof Location)) {
continue;
}
Location location = (Location) obj;
location.setLatitude(AppApplication.mockGPS.mLatitude);
location.setLongitude(AppApplication.mockGPS.mLongitude);
}
}
return RposedHelpers.callMethod(originListener, method.getName(), args);
}
};
Object proxyListener;
if (aMapLocationListenerInterfaceClass.isInterface()) {
proxyListener = Proxy.newProxyInstance(aMapLocationListenerInterfaceClass.getClassLoader(),
new Class[]{aMapLocationListenerInterfaceClass}, invocationHandler
);
} else {
proxyListener = RatelToolKit.dexMakerProxyBuilderHelper
.forClass(aMapLocationListenerInterfaceClass)
.parentClassLoader(aMapLocationListenerInterfaceClass.getClassLoader())
.onlyMethods(aMapLocationListenerInterfaceClass.getDeclaredMethods())
.handler(invocationHandler).build();
}
param.args[0] = proxyListener;
}
});
}
});
}
} }
...@@ -3,8 +3,12 @@ package top.littlerich.virtuallocation.common; ...@@ -3,8 +3,12 @@ package top.littlerich.virtuallocation.common;
import android.Manifest; import android.Manifest;
import android.app.Application; import android.app.Application;
import android.app.Service; import android.app.Service;
import android.content.Context;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Vibrator; import android.os.Vibrator;
import android.util.Log;
import com.baidu.mapapi.CoordType; import com.baidu.mapapi.CoordType;
import com.baidu.mapapi.SDKInitializer; import com.baidu.mapapi.SDKInitializer;
...@@ -24,11 +28,14 @@ import top.littlerich.virtuallocation.util.PermissionUtil; ...@@ -24,11 +28,14 @@ import top.littlerich.virtuallocation.util.PermissionUtil;
* Created by xuqingfu on 2017/4/15. * Created by xuqingfu on 2017/4/15.
*/ */
public class AppApplication extends Application { public class AppApplication extends Application {
public static final String tag = "RVLocation";
public LocationService locationService; public LocationService locationService;
public Vibrator mVibrator; public Vibrator mVibrator;
private static AppApplication appApplication; private static AppApplication appApplication;
public static Gps mockGPS = null;
@Override @Override
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
...@@ -101,4 +108,24 @@ public class AppApplication extends Application { ...@@ -101,4 +108,24 @@ public class AppApplication extends Application {
} }
} }
public static void queryMockGPS(Context context) {
try {
Bundle bundle = context.getContentResolver()
.call(Uri.parse("content://com.virjar.ratel.virtuallocation"),
"invoke", context.getPackageName(), null);
if (bundle == null) {
return;
}
double lat = bundle.getDouble("lat", -1);
double lng = bundle.getDouble("lng", -1);
Log.i(AppApplication.tag, "queryMockGPS: " + lng + "," + lat);
if (lat == -1 && lng == -1) {
return;
}
mockGPS = new Gps(lat, lng);
} catch (Exception e) {
Log.e(AppApplication.tag, "error for queryMockGPS", e);
}
}
} }
\ No newline at end of file
package top.littlerich.virtuallocation.common;
/**
* Created by xuqingfu on 2017/5/31.
*/
public class Common {
public static final String SP_FILTER_APP_PKG_NAME = "hook_app_name";
}
...@@ -27,7 +27,7 @@ public class AsyncLocationResultListener implements BDLocationListener { ...@@ -27,7 +27,7 @@ public class AsyncLocationResultListener implements BDLocationListener {
mMapView = mapView; mMapView = mapView;
this.isFirstLoc = isFirstLoc; this.isFirstLoc = isFirstLoc;
//this.myGpslatitude = myGpslatitude; //this.myGpslatitude = myGpslatitude;
// this.myGpslongitude = myGpslongitude; // this.myGpslongitude = myGpslongitude;
} }
@Override @Override
......
package top.littlerich.virtuallocation.presenter; //package top.littlerich.virtuallocation.presenter;
//
import android.content.ContentResolver; //import android.content.ContentResolver;
import android.location.Location; //import android.location.Location;
import android.provider.Settings; //import android.provider.Settings;
//
import de.robv.android.xposed.XC_MethodHook; //import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XC_MethodReplacement; //import de.robv.android.xposed.XC_MethodReplacement;
import de.robv.android.xposed.XposedHelpers; //import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage; //import de.robv.android.xposed.callbacks.XC_LoadPackage;
//
import static android.provider.Settings.Secure.LOCATION_MODE_SENSORS_ONLY; //import static android.provider.Settings.Secure.LOCATION_MODE_SENSORS_ONLY;
//
/** ///**
* Created by xuqingfu on 2017/5/31. // * Created by xuqingfu on 2017/5/31.
*/ // */
//
public class SdkHookManager { //public class SdkHookManager {
//
/** // /**
* 判断是否开启允许ADB模拟定位功能 // * 判断是否开启允许ADB模拟定位功能
*/ // */
public static void findMethodIsFromMockProvider(){ // public static void findMethodIsFromMockProvider(){
XposedHelpers.findAndHookMethod(Location.class, "isFromMockProvider", new XC_MethodHook() { // XposedHelpers.findAndHookMethod(Location.class, "isFromMockProvider", new XC_MethodHook() {
@Override // @Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable { // protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param); // super.afterHookedMethod(param);
param.setResult(false); // param.setResult(false);
} // }
}); // });
} // }
//
/** // /**
* 劫持判断是否使用虚拟定位 // * 劫持判断是否使用虚拟定位
* @param loadPackageParam // * @param loadPackageParam
*/ // */
public static void findMethodGetInt(XC_LoadPackage.LoadPackageParam loadPackageParam){ // public static void findMethodGetInt(XC_LoadPackage.LoadPackageParam loadPackageParam){
// boolean isOpen = Settings.Secure.getInt(getContentResolver(),Settings.Secure.ALLOW_MOCK_LOCATION, 0) != 0; // // boolean isOpen = Settings.Secure.getInt(getContentResolver(),Settings.Secure.ALLOW_MOCK_LOCATION, 0) != 0;
XposedHelpers.findAndHookMethod("android.provider.Settings$Secure", loadPackageParam.classLoader, "getInt", ContentResolver.class, String.class, int.class, new XC_MethodHook() { // XposedHelpers.findAndHookMethod("android.provider.Settings$Secure", loadPackageParam.classLoader, "getInt", ContentResolver.class, String.class, int.class, new XC_MethodHook() {
//
/** // /**
* 设置返回值类型: // * 设置返回值类型:
* 1、gpsEnabled && networkEnabled:LOCATION_MODE_HIGH_ACCURACY // * 1、gpsEnabled && networkEnabled:LOCATION_MODE_HIGH_ACCURACY
* 2、gpsEnabled:LOCATION_MODE_SENSORS_ONLY // * 2、gpsEnabled:LOCATION_MODE_SENSORS_ONLY
* 3、networkEnabled:LOCATION_MODE_BATTERY_SAVING // * 3、networkEnabled:LOCATION_MODE_BATTERY_SAVING
* 4、disable:LOCATION_MODE_OFF // * 4、disable:LOCATION_MODE_OFF
*/ // */
@Override // @Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable { // protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param); // super.afterHookedMethod(param);
param.setResult(LOCATION_MODE_SENSORS_ONLY); // param.setResult(LOCATION_MODE_SENSORS_ONLY);
} // }
}); // });
//
XposedHelpers.findAndHookMethod(Settings.Secure.class, "getInt", ContentResolver.class, String.class, int.class, new XC_MethodReplacement() { // XposedHelpers.findAndHookMethod(Settings.Secure.class, "getInt", ContentResolver.class, String.class, int.class, new XC_MethodReplacement() {
@Override // @Override
protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable { // protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable {
return LOCATION_MODE_SENSORS_ONLY; // return LOCATION_MODE_SENSORS_ONLY;
} // }
}); // });
} // }
//
//
//
} //}
package top.littlerich.virtuallocation.service;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import top.littlerich.virtuallocation.common.AppApplication;
import top.littlerich.virtuallocation.model.Gps;
public class GPSContentProvider extends ContentProvider {
@Override
public boolean onCreate() {
return false;
}
@Nullable
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
return null;
}
@Nullable
@Override
public String getType(@NonNull Uri uri) {
return null;
}
@Nullable
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
return null;
}
@Override
public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
return 0;
}
@Override
public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
return 0;
}
@Nullable
@Override
public Bundle call(@NonNull String method, @Nullable String arg, @Nullable Bundle extras) {
//return super.call(method, arg, extras);
boolean appMockStatus = AppApplication.getAppMockStatus(arg);
Bundle bundle = new Bundle();
if (!appMockStatus) {
return bundle;
}
Gps configGPS = AppApplication.getConfigGPS();
bundle.putDouble("lat", configGPS.mLatitude);
bundle.putDouble("lng", configGPS.mLongitude);
return bundle;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment