From 86e7aeabc60731b3f495bbbf8ca0b15bb6bfc4b8 Mon Sep 17 00:00:00 2001 From: YiuChoi Date: Tue, 10 May 2016 19:07:19 +0800 Subject: [PATCH 01/10] =?UTF-8?q?=E5=87=86=E5=A4=871.2=E6=AD=A3=E5=BC=8F?= =?UTF-8?q?=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../name/caiyao/fakegps/MainActivity.java | 40 +++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/name/caiyao/fakegps/MainActivity.java b/app/src/main/java/name/caiyao/fakegps/MainActivity.java index 570b219..25ade48 100644 --- a/app/src/main/java/name/caiyao/fakegps/MainActivity.java +++ b/app/src/main/java/name/caiyao/fakegps/MainActivity.java @@ -9,10 +9,12 @@ import android.location.LocationManager; import android.net.Uri; import android.os.Bundle; +import android.provider.Settings; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.util.Log; +import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; @@ -37,6 +39,7 @@ public class MainActivity extends AppCompatActivity implements AMap.OnMapClickLi private AMap aMap; private LatLng latLng; private SharedPreferences sharedPreferences; + private long mExitTime=0; @Override protected void onCreate(Bundle savedInstanceState) { @@ -52,7 +55,7 @@ protected void onCreate(Bundle savedInstanceState) { aMap = mv.getMap(); double lat = Double.parseDouble(sharedPreferences.getString("lat", "0.0")); double lon = Double.parseDouble(sharedPreferences.getString("lon", "0.0")); - if (lat != 0.0 && lon != 0.0){ + if (lat != 0.0 && lon != 0.0) { aMap.moveCamera(CameraUpdateFactory.changeLatLng(new LatLng(lat, lon))); aMap.moveCamera(CameraUpdateFactory.zoomTo(aMap.getMaxZoomLevel())); } @@ -79,11 +82,26 @@ protected void onResume() { locationManager.requestLocationUpdates(mockProviderName, 0, 0, this); } catch (Exception e) { e.printStackTrace(); - Toast.makeText(this, "请打开模拟位置权限!", Toast.LENGTH_SHORT).show(); + showDialog(); } mv.onResume(); } + private void showDialog() { + new AlertDialog.Builder(this).setTitle("需要打开模拟位置").setMessage("是否跳转到开发者选项打开模拟位置").setPositiveButton("确认", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + Intent intent = new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS); + startActivity(intent); + } + }).setNegativeButton("取消", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + } + }).show(); + } + @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_main, menu); @@ -116,7 +134,7 @@ public boolean onOptionsItemSelected(MenuItem item) { startService(new Intent(MainActivity.this, MockGpsService.class).putExtra("action", MockGpsService.ACTION_START).putExtra("location", latLng.latitude + ":" + latLng.longitude)); } catch (Exception e) { e.printStackTrace(); - Toast.makeText(this, "请打开模拟位置权限!", Toast.LENGTH_SHORT).show(); + showDialog(); } break; case R.id.stop: @@ -156,6 +174,22 @@ protected void onPause() { mv.onPause(); } + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { + if ((System.currentTimeMillis() - mExitTime) > 2000) {// + // 如果两次按键时间间隔大于2000毫秒,则不退出 + Toast.makeText(this, "再按一次退出程序,停止模拟位置!", Toast.LENGTH_SHORT).show(); + mExitTime = System.currentTimeMillis();// 更新mExitTime + } else { + System.exit(0);// 否则退出程序 + } + return true; + } + return super.onKeyDown(keyCode, event); + + } + private void search(final String key) { PoiSearch.Query query = new PoiSearch.Query(key, null, null); query.setPageSize(10); From 9e83d531c053674619fc7dbfc1e18cc878979915 Mon Sep 17 00:00:00 2001 From: YiuChoi Date: Tue, 10 May 2016 19:16:02 +0800 Subject: [PATCH 02/10] =?UTF-8?q?1.2=E6=AD=A3=E5=BC=8F=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 622f5c8..115ba97 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,8 +8,8 @@ android { applicationId "name.caiyao.fakegps" minSdkVersion 9 targetSdkVersion 22 - versionCode 3 - versionName "1.2.0 beta" + versionCode 4 + versionName "1.2.0" } buildTypes { release { From de10d3b27f79fe0c0df99aa874345cc55ca71fbb Mon Sep 17 00:00:00 2001 From: YiuChoi Date: Wed, 11 May 2016 10:17:12 +0800 Subject: [PATCH 03/10] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=8E=92=E9=99=A4?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E5=BA=94=E7=94=A8=E8=80=8C=E9=9D=9E=E5=8C=85?= =?UTF-8?q?=E5=90=AB=E7=89=B9=E5=AE=9A=E5=85=B3=E9=94=AE=E5=AD=97=E7=9A=84?= =?UTF-8?q?=E5=BA=94=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/name/caiyao/fakegps/MainHook.java | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/name/caiyao/fakegps/MainHook.java b/app/src/main/java/name/caiyao/fakegps/MainHook.java index db162ed..37477de 100644 --- a/app/src/main/java/name/caiyao/fakegps/MainHook.java +++ b/app/src/main/java/name/caiyao/fakegps/MainHook.java @@ -1,6 +1,7 @@ package name.caiyao.fakegps; import android.content.ContentResolver; +import android.content.pm.ApplicationInfo; import android.os.Build; import android.provider.Settings; import android.telephony.CellIdentityCdma; @@ -28,18 +29,17 @@ public class MainHook implements IXposedHookLoadPackage { @Override public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable { - if (!loadPackageParam.packageName.contains("tencent") && !loadPackageParam.packageName.contains("alibaba") && !loadPackageParam.packageName.contains("baidu")) - return; - XposedHelpers.findAndHookMethod("android.provider.Settings.Secure", loadPackageParam.classLoader, "getString", - ContentResolver.class, String.class, new XC_MethodHook() { - @Override - protected void beforeHookedMethod(MethodHookParam param) throws Throwable { - String requested = (String) param.args[1]; - if (requested.equals(Settings.Secure.ALLOW_MOCK_LOCATION)) { - param.setResult("0"); + if (loadPackageParam.appInfo.flags != ApplicationInfo.FLAG_SYSTEM) + XposedHelpers.findAndHookMethod("android.provider.Settings.Secure", loadPackageParam.classLoader, "getString", + ContentResolver.class, String.class, new XC_MethodHook() { + @Override + protected void beforeHookedMethod(MethodHookParam param) throws Throwable { + String requested = (String) param.args[1]; + if (requested.equals(Settings.Secure.ALLOW_MOCK_LOCATION)) { + param.setResult("0"); + } } - } - }); + }); // at API level 18, the function Location.isFromMockProvider is added if (Build.VERSION.SDK_INT >= 18) { From 8fdc36dede43c870e7a4e06eaccd8669da07011d Mon Sep 17 00:00:00 2001 From: YiuChoi Date: Wed, 11 May 2016 10:43:43 +0800 Subject: [PATCH 04/10] =?UTF-8?q?=E4=BD=BF=E7=94=A8=E5=B9=BF=E6=92=AD?= =?UTF-8?q?=E6=8E=A7=E5=88=B6=E6=98=AF=E5=90=A6Hook?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../name/caiyao/fakegps/MainActivity.java | 14 ++- .../java/name/caiyao/fakegps/MainHook.java | 99 ++++++++----------- 2 files changed, 53 insertions(+), 60 deletions(-) diff --git a/app/src/main/java/name/caiyao/fakegps/MainActivity.java b/app/src/main/java/name/caiyao/fakegps/MainActivity.java index 25ade48..5df382c 100644 --- a/app/src/main/java/name/caiyao/fakegps/MainActivity.java +++ b/app/src/main/java/name/caiyao/fakegps/MainActivity.java @@ -39,7 +39,7 @@ public class MainActivity extends AppCompatActivity implements AMap.OnMapClickLi private AMap aMap; private LatLng latLng; private SharedPreferences sharedPreferences; - private long mExitTime=0; + private long mExitTime = 0; @Override protected void onCreate(Bundle savedInstanceState) { @@ -56,6 +56,13 @@ protected void onCreate(Bundle savedInstanceState) { double lat = Double.parseDouble(sharedPreferences.getString("lat", "0.0")); double lon = Double.parseDouble(sharedPreferences.getString("lon", "0.0")); if (lat != 0.0 && lon != 0.0) { + latLng = new LatLng(lat, lon); + aMap.clear(); + MarkerOptions markerOptions = new MarkerOptions(); + markerOptions.position(latLng); + markerOptions.draggable(true); + markerOptions.title("经度:" + latLng.longitude + ",纬度:" + latLng.latitude); + aMap.addMarker(markerOptions); aMap.moveCamera(CameraUpdateFactory.changeLatLng(new LatLng(lat, lon))); aMap.moveCamera(CameraUpdateFactory.zoomTo(aMap.getMaxZoomLevel())); } @@ -131,6 +138,7 @@ public boolean onOptionsItemSelected(MenuItem item) { android.location.Criteria.ACCURACY_FINE); locationManager.setTestProviderEnabled(mockProviderName, true); locationManager.requestLocationUpdates(mockProviderName, 0, 0, this); + sendBroadcast(new Intent(MainHook.ACTION_START_HOOK)); startService(new Intent(MainActivity.this, MockGpsService.class).putExtra("action", MockGpsService.ACTION_START).putExtra("location", latLng.latitude + ":" + latLng.longitude)); } catch (Exception e) { e.printStackTrace(); @@ -182,6 +190,7 @@ public boolean onKeyDown(int keyCode, KeyEvent event) { Toast.makeText(this, "再按一次退出程序,停止模拟位置!", Toast.LENGTH_SHORT).show(); mExitTime = System.currentTimeMillis();// 更新mExitTime } else { + sendBroadcast(new Intent(MainHook.ACTION_STOP_HOOK)); System.exit(0);// 否则退出程序 } return true; @@ -239,6 +248,7 @@ protected void onSaveInstanceState(Bundle outState) { @Override protected void onDestroy() { super.onDestroy(); + sendBroadcast(new Intent(MainHook.ACTION_STOP_HOOK)); mv.onDestroy(); } @@ -249,7 +259,6 @@ public void onMapClick(LatLng latLng) { MarkerOptions markerOptions = new MarkerOptions(); markerOptions.position(latLng); markerOptions.draggable(true); - Log.i("TAG", "经度:" + latLng.longitude + ",纬度:" + latLng.latitude); markerOptions.title("经度:" + latLng.longitude + ",纬度:" + latLng.latitude); aMap.addMarker(markerOptions); this.latLng = latLng; @@ -257,6 +266,7 @@ public void onMapClick(LatLng latLng) { @Override public void onBackPressed() { + sendBroadcast(new Intent(MainHook.ACTION_STOP_HOOK)); startService(new Intent(MainActivity.this, MockGpsService.class).putExtra("action", MockGpsService.ACTION_STOP)); super.onBackPressed(); } diff --git a/app/src/main/java/name/caiyao/fakegps/MainHook.java b/app/src/main/java/name/caiyao/fakegps/MainHook.java index 37477de..559fdee 100644 --- a/app/src/main/java/name/caiyao/fakegps/MainHook.java +++ b/app/src/main/java/name/caiyao/fakegps/MainHook.java @@ -1,17 +1,13 @@ package name.caiyao.fakegps; +import android.content.BroadcastReceiver; import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.os.Build; import android.provider.Settings; -import android.telephony.CellIdentityCdma; -import android.telephony.CellIdentityGsm; -import android.telephony.CellIdentityLte; -import android.telephony.CellIdentityWcdma; -import android.telephony.CellInfoCdma; -import android.telephony.CellInfoGsm; -import android.telephony.CellInfoLte; -import android.telephony.CellInfoWcdma; import android.telephony.CellLocation; import android.telephony.gsm.GsmCellLocation; @@ -27,19 +23,44 @@ * Created by 蔡小木 on 2016/4/17 0017. */ public class MainHook implements IXposedHookLoadPackage { + + private static boolean isHook = false; + public static final String ACTION_START_HOOK = "name.caiyao.fakegps.ACTION_START_HOOK"; + public static final String ACTION_STOP_HOOK = "name.caiyao.fakegps.ACTION_STOP_HOOK"; + @Override public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable { - if (loadPackageParam.appInfo.flags != ApplicationInfo.FLAG_SYSTEM) - XposedHelpers.findAndHookMethod("android.provider.Settings.Secure", loadPackageParam.classLoader, "getString", - ContentResolver.class, String.class, new XC_MethodHook() { - @Override - protected void beforeHookedMethod(MethodHookParam param) throws Throwable { - String requested = (String) param.args[1]; - if (requested.equals(Settings.Secure.ALLOW_MOCK_LOCATION)) { - param.setResult("0"); - } + + final Object activityThread = XposedHelpers.callStaticMethod(XposedHelpers.findClass("android.app.ActivityThread", null), "currentActivityThread"); + final Context systemContext = (Context) XposedHelpers.callMethod(activityThread, "getSystemContext"); + IntentFilter intentFilter = new IntentFilter(); + intentFilter.addAction(ACTION_START_HOOK); + intentFilter.addAction(ACTION_STOP_HOOK); + systemContext.registerReceiver(new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (intent.getAction().equals(ACTION_START_HOOK)) + isHook = true; + else if (intent.getAction().equals(ACTION_STOP_HOOK)) + isHook = false; + } + }, intentFilter); + + if ((loadPackageParam.appInfo.flags & ApplicationInfo.FLAG_SYSTEM) > 0) + return; + if (!isHook) { + return; + } + XposedHelpers.findAndHookMethod("android.provider.Settings.Secure", loadPackageParam.classLoader, "getString", + ContentResolver.class, String.class, new XC_MethodHook() { + @Override + protected void beforeHookedMethod(MethodHookParam param) throws Throwable { + String requested = (String) param.args[1]; + if (requested.equals(Settings.Secure.ALLOW_MOCK_LOCATION)) { + param.setResult("0"); } - }); + } + }); // at API level 18, the function Location.isFromMockProvider is added if (Build.VERSION.SDK_INT >= 18) { @@ -192,14 +213,14 @@ protected void afterHookedMethod(MethodHookParam param) throws Throwable { "getAllCellInfo", new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { - param.setResult(getCell(0, 0, 0, 0, 0, 0)); + param.setResult(new ArrayList<>()); } }); XposedHelpers.findAndHookMethod("android.telephony.PhoneStateListener", loadPackageParam.classLoader, "onCellInfoChanged", List.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { - param.setResult(getCell(0, 0, 0, 0, 0, 0)); + param.setResult(new ArrayList<>()); } }); } @@ -286,42 +307,4 @@ protected void afterHookedMethod(MethodHookParam param) throws Throwable { } }); } - - private static ArrayList getCell(int mcc, int mnc, int lac, int cid, int sid, int networkType) { - ArrayList arrayList = new ArrayList(); - CellInfoGsm cellInfoGsm = (CellInfoGsm) XposedHelpers.newInstance(CellInfoGsm.class); - XposedHelpers.callMethod(cellInfoGsm, "setCellIdentity", XposedHelpers.newInstance(CellIdentityGsm.class, new Object[]{Integer.valueOf(mcc), Integer.valueOf(mnc), Integer.valueOf( - lac), Integer.valueOf(cid)})); - CellInfoCdma cellInfoCdma = (CellInfoCdma) XposedHelpers.newInstance(CellInfoCdma.class); - XposedHelpers.callMethod(cellInfoCdma, "setCellIdentity", XposedHelpers.newInstance(CellIdentityCdma.class, new Object[]{Integer.valueOf(lac), Integer.valueOf(sid), Integer.valueOf(cid), Integer.valueOf(0), Integer.valueOf(0)})); - CellInfoWcdma cellInfoWcdma = (CellInfoWcdma) XposedHelpers.newInstance(CellInfoWcdma.class); - XposedHelpers.callMethod(cellInfoWcdma, "setCellIdentity", XposedHelpers.newInstance(CellIdentityWcdma.class, new Object[]{Integer.valueOf(mcc), Integer.valueOf(mnc), Integer.valueOf(lac), Integer.valueOf(cid), Integer.valueOf(300)})); - CellInfoLte cellInfoLte = (CellInfoLte) XposedHelpers.newInstance(CellInfoLte.class); - XposedHelpers.callMethod(cellInfoLte, "setCellIdentity", XposedHelpers.newInstance(CellIdentityLte.class, new Object[]{Integer.valueOf(mcc), Integer.valueOf(mnc), Integer.valueOf(cid), Integer.valueOf(300), Integer.valueOf(lac)})); - switch (networkType) { - case 1: - case 2: - arrayList.add(cellInfoGsm); - break; - case 13: - arrayList.add(cellInfoLte); - break; - case 4: - case 5: - case 6: - case 7: - case 12: - case 14: - arrayList.add(cellInfoCdma); - break; - case 3: - case 8: - case 9: - case 10: - case 15: - arrayList.add(cellInfoWcdma); - break; - } - return arrayList; - } } From 85c20f1dddf5f0f91956a69b11f5a1590f1f99d0 Mon Sep 17 00:00:00 2001 From: YiuChoi Date: Wed, 11 May 2016 12:38:15 +0800 Subject: [PATCH 05/10] =?UTF-8?q?=E4=BD=BF=E7=94=A8ContentProvider?= =?UTF-8?q?=E9=80=9A=E8=AE=AF=E6=98=AF=E5=90=A6Hook?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 4 ++ .../java/name/caiyao/fakegps/DbHelper.java | 27 ++++++++++ .../name/caiyao/fakegps/MainActivity.java | 5 +- .../java/name/caiyao/fakegps/MainHook.java | 34 +++++++------ .../name/caiyao/fakegps/MockGpsService.java | 27 ++++++++-- .../name/caiyao/fakegps/SettingProvider.java | 49 +++++++++++++++++++ 6 files changed, 123 insertions(+), 23 deletions(-) create mode 100644 app/src/main/java/name/caiyao/fakegps/DbHelper.java create mode 100644 app/src/main/java/name/caiyao/fakegps/SettingProvider.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index bbb859a..3366b0b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -45,6 +45,10 @@ android:value="e34a748230a8123b72fd71a6f1604946" /> + \ No newline at end of file diff --git a/app/src/main/java/name/caiyao/fakegps/DbHelper.java b/app/src/main/java/name/caiyao/fakegps/DbHelper.java new file mode 100644 index 0000000..a6d2a00 --- /dev/null +++ b/app/src/main/java/name/caiyao/fakegps/DbHelper.java @@ -0,0 +1,27 @@ +package name.caiyao.fakegps; + +import android.content.Context; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; + +/** + * Created by 蔡小木 on 2016/5/11 0011. + */ +public class DbHelper extends SQLiteOpenHelper { + + private static final String DB_NAME = "fake.db"; + public static final String TABLE_NAME = "fake"; + public DbHelper(Context context) { + super(context, DB_NAME, null, 1); + } + + @Override + public void onCreate(SQLiteDatabase db) { + db.execSQL("CREATE TABLE IF NOT EXISTS "+TABLE_NAME + "(key TEXT PRIMARY KEY,value TEXT)"); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + + } +} diff --git a/app/src/main/java/name/caiyao/fakegps/MainActivity.java b/app/src/main/java/name/caiyao/fakegps/MainActivity.java index 5df382c..24a65e9 100644 --- a/app/src/main/java/name/caiyao/fakegps/MainActivity.java +++ b/app/src/main/java/name/caiyao/fakegps/MainActivity.java @@ -46,6 +46,7 @@ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); sharedPreferences = getSharedPreferences("locationHistory", Context.MODE_PRIVATE); + Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); @@ -138,7 +139,6 @@ public boolean onOptionsItemSelected(MenuItem item) { android.location.Criteria.ACCURACY_FINE); locationManager.setTestProviderEnabled(mockProviderName, true); locationManager.requestLocationUpdates(mockProviderName, 0, 0, this); - sendBroadcast(new Intent(MainHook.ACTION_START_HOOK)); startService(new Intent(MainActivity.this, MockGpsService.class).putExtra("action", MockGpsService.ACTION_START).putExtra("location", latLng.latitude + ":" + latLng.longitude)); } catch (Exception e) { e.printStackTrace(); @@ -190,7 +190,6 @@ public boolean onKeyDown(int keyCode, KeyEvent event) { Toast.makeText(this, "再按一次退出程序,停止模拟位置!", Toast.LENGTH_SHORT).show(); mExitTime = System.currentTimeMillis();// 更新mExitTime } else { - sendBroadcast(new Intent(MainHook.ACTION_STOP_HOOK)); System.exit(0);// 否则退出程序 } return true; @@ -248,7 +247,6 @@ protected void onSaveInstanceState(Bundle outState) { @Override protected void onDestroy() { super.onDestroy(); - sendBroadcast(new Intent(MainHook.ACTION_STOP_HOOK)); mv.onDestroy(); } @@ -266,7 +264,6 @@ public void onMapClick(LatLng latLng) { @Override public void onBackPressed() { - sendBroadcast(new Intent(MainHook.ACTION_STOP_HOOK)); startService(new Intent(MainActivity.this, MockGpsService.class).putExtra("action", MockGpsService.ACTION_STOP)); super.onBackPressed(); } diff --git a/app/src/main/java/name/caiyao/fakegps/MainHook.java b/app/src/main/java/name/caiyao/fakegps/MainHook.java index 559fdee..ddfe6ef 100644 --- a/app/src/main/java/name/caiyao/fakegps/MainHook.java +++ b/app/src/main/java/name/caiyao/fakegps/MainHook.java @@ -1,11 +1,10 @@ package name.caiyao.fakegps; -import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; import android.content.pm.ApplicationInfo; +import android.database.Cursor; +import android.net.Uri; import android.os.Build; import android.provider.Settings; import android.telephony.CellLocation; @@ -16,6 +15,7 @@ import de.robv.android.xposed.IXposedHookLoadPackage; import de.robv.android.xposed.XC_MethodHook; +import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.callbacks.XC_LoadPackage; @@ -24,30 +24,32 @@ */ public class MainHook implements IXposedHookLoadPackage { - private static boolean isHook = false; - public static final String ACTION_START_HOOK = "name.caiyao.fakegps.ACTION_START_HOOK"; - public static final String ACTION_STOP_HOOK = "name.caiyao.fakegps.ACTION_STOP_HOOK"; + public static boolean isHook = false; @Override public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable { - final Object activityThread = XposedHelpers.callStaticMethod(XposedHelpers.findClass("android.app.ActivityThread", null), "currentActivityThread"); final Context systemContext = (Context) XposedHelpers.callMethod(activityThread, "getSystemContext"); - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(ACTION_START_HOOK); - intentFilter.addAction(ACTION_STOP_HOOK); - systemContext.registerReceiver(new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (intent.getAction().equals(ACTION_START_HOOK)) + Uri uri = Uri.parse("content://name.caiyao.fakegps.SettingProvider/fake"); + Cursor cursor = systemContext.getContentResolver().query(uri, null, null, null, null); + if (cursor != null && cursor.moveToNext()) { + String key = cursor.getString(cursor.getColumnIndex("key")); + String value = cursor.getString(cursor.getColumnIndex("value")); + if (key.equals("hook")) { + if (value.equals("1")) { isHook = true; - else if (intent.getAction().equals(ACTION_STOP_HOOK)) + } else if (value.equals("0")) { isHook = false; + } } - }, intentFilter); + cursor.close(); + }else{ + XposedBridge.log("cusor is null"); + } if ((loadPackageParam.appInfo.flags & ApplicationInfo.FLAG_SYSTEM) > 0) return; + XposedBridge.log(loadPackageParam.packageName + ",hook;" + isHook); if (!isHook) { return; } diff --git a/app/src/main/java/name/caiyao/fakegps/MockGpsService.java b/app/src/main/java/name/caiyao/fakegps/MockGpsService.java index 45e2e50..009642c 100644 --- a/app/src/main/java/name/caiyao/fakegps/MockGpsService.java +++ b/app/src/main/java/name/caiyao/fakegps/MockGpsService.java @@ -2,11 +2,15 @@ import android.app.PendingIntent; import android.app.Service; +import android.content.ContentValues; import android.content.Context; import android.content.Intent; +import android.database.sqlite.SQLiteDatabase; import android.graphics.BitmapFactory; +import android.location.Criteria; import android.location.Location; import android.location.LocationManager; +import android.os.Build; import android.os.IBinder; import android.os.SystemClock; import android.support.v7.app.NotificationCompat; @@ -18,10 +22,17 @@ public class MockGpsService extends Service { public static final String ACTION_STOP = "name.caiyao.fakegps.STOP_FAKE"; UpdateGPSThread currentThread = null; + private SQLiteDatabase mSQLiteDatabase; public MockGpsService() { } + @Override + public void onCreate() { + super.onCreate(); + mSQLiteDatabase = new DbHelper(this).getWritableDatabase(); + } + @Override public IBinder onBind(Intent intent) { return null; @@ -34,8 +45,16 @@ public int onStartCommand(Intent intent, int flags, int startId) { currentThread = new UpdateGPSThread(); currentThread.mLocation = intent.getStringExtra("location"); currentThread.start(); + ContentValues contentValues = new ContentValues(); + contentValues.put("key", "hook"); + contentValues.put("value", "1"); + mSQLiteDatabase.insertWithOnConflict(DbHelper.TABLE_NAME, null, contentValues, SQLiteDatabase.CONFLICT_REPLACE); } if (intent.getStringExtra("action").equalsIgnoreCase(ACTION_STOP)) { + ContentValues contentValues = new ContentValues(); + contentValues.put("key", "hook"); + contentValues.put("value", "0"); + mSQLiteDatabase.insertWithOnConflict(DbHelper.TABLE_NAME, null, contentValues, SQLiteDatabase.CONFLICT_REPLACE); if (currentThread != null) { currentThread.Running = false; currentThread.interrupt(); @@ -83,13 +102,15 @@ public void run() { location.setAltitude(2.0f); location.setAccuracy(3.0f); createProgressNotification(location); - location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos()); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos()); + } try { locationManager.addTestProvider("gps", "requiresNetwork".equals(""), "requiresSatellite".equals(""), "requiresCell".equals(""), "hasMonetaryCost".equals(""), "supportsAltitude".equals(""), "supportsSpeed".equals(""), - "supportsBearing".equals(""), android.location.Criteria.POWER_LOW, - android.location.Criteria.ACCURACY_FINE); + "supportsBearing".equals(""), Criteria.POWER_LOW, + Criteria.ACCURACY_FINE); locationManager.setTestProviderLocation("gps", location); } catch (SecurityException e) { e.printStackTrace(); diff --git a/app/src/main/java/name/caiyao/fakegps/SettingProvider.java b/app/src/main/java/name/caiyao/fakegps/SettingProvider.java new file mode 100644 index 0000000..bfda26f --- /dev/null +++ b/app/src/main/java/name/caiyao/fakegps/SettingProvider.java @@ -0,0 +1,49 @@ +package name.caiyao.fakegps; + +import android.content.ContentProvider; +import android.content.ContentValues; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.net.Uri; +import android.support.annotation.Nullable; + +/** + * Created by 蔡小木 on 2016/5/11 0011. + */ +public class SettingProvider extends ContentProvider { + private SQLiteDatabase mSQLiteDatabase; + + @Override + public boolean onCreate() { + mSQLiteDatabase = new DbHelper(getContext()).getWritableDatabase(); + return true; + } + + @Nullable + @Override + public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { + return mSQLiteDatabase.query(DbHelper.TABLE_NAME,projection,selection,selectionArgs,null,null,sortOrder,null); + } + + @Nullable + @Override + public String getType(Uri uri) { + return null; + } + + @Nullable + @Override + public Uri insert(Uri uri, ContentValues values) { + return null; + } + + @Override + public int delete(Uri uri, String selection, String[] selectionArgs) { + return 0; + } + + @Override + public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { + return 0; + } +} From 5a182909e86e50fa60a1b233de41e45c8b4d1c32 Mon Sep 17 00:00:00 2001 From: YiuChoi Date: Wed, 11 May 2016 12:49:15 +0800 Subject: [PATCH 06/10] 1.2.1 --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 115ba97..e3f75b8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,8 +8,8 @@ android { applicationId "name.caiyao.fakegps" minSdkVersion 9 targetSdkVersion 22 - versionCode 4 - versionName "1.2.0" + versionCode 5 + versionName "1.2.1" } buildTypes { release { From 88c4a88e838bb9111ffd6df3753a8f3bba47ee28 Mon Sep 17 00:00:00 2001 From: YiuChoi Date: Tue, 24 May 2016 11:17:50 +0800 Subject: [PATCH 07/10] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=87=8D=E5=90=AF?= =?UTF-8?q?=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/.name | 1 - .idea/gradle.xml | 9 +-------- .idea/runConfigurations.xml | 12 ------------ .../main/java/name/caiyao/fakegps/MainActivity.java | 2 ++ 4 files changed, 3 insertions(+), 21 deletions(-) delete mode 100644 .idea/.name delete mode 100644 .idea/runConfigurations.xml diff --git a/.idea/.name b/.idea/.name deleted file mode 100644 index be3b5af..0000000 --- a/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -FakeGps \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 4f23291..df527ea 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -3,21 +3,14 @@ diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml deleted file mode 100644 index 7f68460..0000000 --- a/.idea/runConfigurations.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/java/name/caiyao/fakegps/MainActivity.java b/app/src/main/java/name/caiyao/fakegps/MainActivity.java index 24a65e9..abfec7c 100644 --- a/app/src/main/java/name/caiyao/fakegps/MainActivity.java +++ b/app/src/main/java/name/caiyao/fakegps/MainActivity.java @@ -140,12 +140,14 @@ public boolean onOptionsItemSelected(MenuItem item) { locationManager.setTestProviderEnabled(mockProviderName, true); locationManager.requestLocationUpdates(mockProviderName, 0, 0, this); startService(new Intent(MainActivity.this, MockGpsService.class).putExtra("action", MockGpsService.ACTION_START).putExtra("location", latLng.latitude + ":" + latLng.longitude)); + Toast.makeText(this,"重启需定位的应用以生效!",Toast.LENGTH_LONG).show(); } catch (Exception e) { e.printStackTrace(); showDialog(); } break; case R.id.stop: + Toast.makeText(this,"重启需定位的应用以生效!",Toast.LENGTH_LONG).show(); startService(new Intent(MainActivity.this, MockGpsService.class).putExtra("action", MockGpsService.ACTION_STOP)); break; case R.id.search: From c3043c22c3d6d677d45b50ce53b8eff8176f6f11 Mon Sep 17 00:00:00 2001 From: YiuChoi Date: Tue, 24 May 2016 16:22:34 +0800 Subject: [PATCH 08/10] =?UTF-8?q?=E8=BD=AC=E6=8D=A2=E9=AB=98=E5=BE=B7?= =?UTF-8?q?=E7=BB=8F=E7=BA=AC=E5=BA=A6=E4=B8=BAGPS=E7=BB=8F=E7=BA=AC?= =?UTF-8?q?=E5=BA=A6=EF=BC=8C=E9=99=8D=E4=BD=8E=E8=AF=AF=E5=B7=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/name/caiyao/fakegps/GpsUtils.java | 89 +++++++++++++++++++ .../name/caiyao/fakegps/MainActivity.java | 7 +- 2 files changed, 93 insertions(+), 3 deletions(-) create mode 100644 app/src/main/java/name/caiyao/fakegps/GpsUtils.java diff --git a/app/src/main/java/name/caiyao/fakegps/GpsUtils.java b/app/src/main/java/name/caiyao/fakegps/GpsUtils.java new file mode 100644 index 0000000..9927436 --- /dev/null +++ b/app/src/main/java/name/caiyao/fakegps/GpsUtils.java @@ -0,0 +1,89 @@ +package name.caiyao.fakegps; + +/** + * Created by 蔡小木 on 2016/5/24 0024. + */ + +public class GpsUtils { + + static double x_pi = 3.14159265358979324 * 3000.0 / 180.0; + // π + static double pi = 3.1415926535897932384626; + // 长半轴 + static double a = 6378245.0; + // 扁率 + static double ee = 0.00669342162296594323; + + private GpsUtils(){ + } + + /** + * GCJ02(火星坐标系)转GPS84 + * + * @param lng 火星坐标系的经度 + * @param lat 火星坐标系纬度 + * @return WGS84坐标数组 + */ + public static double[] gcj02towgs84(double lng, double lat) { + if (out_of_china(lng, lat)) { + return new double[] { lng, lat }; + } + double dlat = transformlat(lng - 105.0, lat - 35.0); + double dlng = transformlng(lng - 105.0, lat - 35.0); + double radlat = lat / 180.0 * pi; + double magic = Math.sin(radlat); + magic = 1 - ee * magic * magic; + double sqrtmagic = Math.sqrt(magic); + dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * pi); + dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * pi); + double mglat = lat + dlat; + double mglng = lng + dlng; + return new double[] { lng * 2 - mglng, lat * 2 - mglat }; + } + + /** + * 纬度转换 + * + * @param lng + * @param lat + * @return + */ + public static double transformlat(double lng, double lat) { + double ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng)); + ret += (20.0 * Math.sin(6.0 * lng * pi) + 20.0 * Math.sin(2.0 * lng * pi)) * 2.0 / 3.0; + ret += (20.0 * Math.sin(lat * pi) + 40.0 * Math.sin(lat / 3.0 * pi)) * 2.0 / 3.0; + ret += (160.0 * Math.sin(lat / 12.0 * pi) + 320 * Math.sin(lat * pi / 30.0)) * 2.0 / 3.0; + return ret; + } + + /** + * 经度转换 + * + * @param lng + * @param lat + * @return + */ + public static double transformlng(double lng, double lat) { + double ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng)); + ret += (20.0 * Math.sin(6.0 * lng * pi) + 20.0 * Math.sin(2.0 * lng * pi)) * 2.0 / 3.0; + ret += (20.0 * Math.sin(lng * pi) + 40.0 * Math.sin(lng / 3.0 * pi)) * 2.0 / 3.0; + ret += (150.0 * Math.sin(lng / 12.0 * pi) + 300.0 * Math.sin(lng / 30.0 * pi)) * 2.0 / 3.0; + return ret; + } + + /** + * 判断是否在国内,不在国内不做偏移 + * + * @param lng + * @param lat + * @return + */ + public static boolean out_of_china(double lng, double lat) { + if (lng < 72.004 || lng > 137.8347) { + return true; + } else if (lat < 0.8293 || lat > 55.8271) { + return true; + } + return false; + } +} diff --git a/app/src/main/java/name/caiyao/fakegps/MainActivity.java b/app/src/main/java/name/caiyao/fakegps/MainActivity.java index abfec7c..796f23e 100644 --- a/app/src/main/java/name/caiyao/fakegps/MainActivity.java +++ b/app/src/main/java/name/caiyao/fakegps/MainActivity.java @@ -139,15 +139,16 @@ public boolean onOptionsItemSelected(MenuItem item) { android.location.Criteria.ACCURACY_FINE); locationManager.setTestProviderEnabled(mockProviderName, true); locationManager.requestLocationUpdates(mockProviderName, 0, 0, this); - startService(new Intent(MainActivity.this, MockGpsService.class).putExtra("action", MockGpsService.ACTION_START).putExtra("location", latLng.latitude + ":" + latLng.longitude)); - Toast.makeText(this,"重启需定位的应用以生效!",Toast.LENGTH_LONG).show(); + double[] gpsLocation = GpsUtils.gcj02towgs84(latLng.longitude, latLng.latitude); + startService(new Intent(MainActivity.this, MockGpsService.class).putExtra("action", MockGpsService.ACTION_START).putExtra("location", gpsLocation[1] + ":" + gpsLocation[0])); + Toast.makeText(this, "重启需定位的应用以生效!", Toast.LENGTH_LONG).show(); } catch (Exception e) { e.printStackTrace(); showDialog(); } break; case R.id.stop: - Toast.makeText(this,"重启需定位的应用以生效!",Toast.LENGTH_LONG).show(); + Toast.makeText(this, "重启需定位的应用以生效!", Toast.LENGTH_LONG).show(); startService(new Intent(MainActivity.this, MockGpsService.class).putExtra("action", MockGpsService.ACTION_STOP)); break; case R.id.search: From 60afc23c41f53da1c373e916de3d814a36e1e33a Mon Sep 17 00:00:00 2001 From: YiuChoi Date: Tue, 24 May 2016 16:24:54 +0800 Subject: [PATCH 09/10] =?UTF-8?q?=E8=BD=AC=E6=8D=A2=E9=AB=98=E5=BE=B7?= =?UTF-8?q?=E7=BB=8F=E7=BA=AC=E5=BA=A6=E4=B8=BAGPS=E7=BB=8F=E7=BA=AC?= =?UTF-8?q?=E5=BA=A6=EF=BC=8C=E9=99=8D=E4=BD=8E=E8=AF=AF=E5=B7=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index e3f75b8..a973a9f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,8 +8,8 @@ android { applicationId "name.caiyao.fakegps" minSdkVersion 9 targetSdkVersion 22 - versionCode 5 - versionName "1.2.1" + versionCode 6 + versionName "1.2.2" } buildTypes { release { From 08bcf95829420a34eeef5dc2b1ccf20cd525d032 Mon Sep 17 00:00:00 2001 From: YiuChoi Date: Tue, 24 May 2016 17:21:32 +0800 Subject: [PATCH 10/10] =?UTF-8?q?=E8=BD=AC=E6=8D=A2=E9=AB=98=E5=BE=B7?= =?UTF-8?q?=E7=BB=8F=E7=BA=AC=E5=BA=A6=E4=B8=BAGPS=E7=BB=8F=E7=BA=AC?= =?UTF-8?q?=E5=BA=A6=EF=BC=8C=E9=99=8D=E4=BD=8E=E8=AF=AF=E5=B7=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/name/caiyao/fakegps/MainActivity.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/name/caiyao/fakegps/MainActivity.java b/app/src/main/java/name/caiyao/fakegps/MainActivity.java index 796f23e..ac2679e 100644 --- a/app/src/main/java/name/caiyao/fakegps/MainActivity.java +++ b/app/src/main/java/name/caiyao/fakegps/MainActivity.java @@ -141,14 +141,14 @@ public boolean onOptionsItemSelected(MenuItem item) { locationManager.requestLocationUpdates(mockProviderName, 0, 0, this); double[] gpsLocation = GpsUtils.gcj02towgs84(latLng.longitude, latLng.latitude); startService(new Intent(MainActivity.this, MockGpsService.class).putExtra("action", MockGpsService.ACTION_START).putExtra("location", gpsLocation[1] + ":" + gpsLocation[0])); - Toast.makeText(this, "重启需定位的应用以生效!", Toast.LENGTH_LONG).show(); + Toast.makeText(this, "位置模拟成功,重启需定位的应用以生效!", Toast.LENGTH_LONG).show(); } catch (Exception e) { e.printStackTrace(); showDialog(); } break; case R.id.stop: - Toast.makeText(this, "重启需定位的应用以生效!", Toast.LENGTH_LONG).show(); + Toast.makeText(this, "位置模拟关闭,重启需定位的应用以生效!", Toast.LENGTH_LONG).show(); startService(new Intent(MainActivity.this, MockGpsService.class).putExtra("action", MockGpsService.ACTION_STOP)); break; case R.id.search: @@ -156,6 +156,7 @@ public boolean onOptionsItemSelected(MenuItem item) { final EditText et_key = (EditText) view.findViewById(R.id.key); new AlertDialog.Builder(this).setView(view) .setTitle("搜索位置") + .setMessage("只能搜索国内地点,如需定位国外请拖拽地图选取!定位到国外使用Google地图的需要翻墙!") .setPositiveButton("搜索", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) {