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/build.gradle b/app/build.gradle
index 622f5c8..a973a9f 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 6
+ versionName "1.2.2"
}
buildTypes {
release {
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/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 570b219..ac2679e 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,12 +39,14 @@ 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) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sharedPreferences = getSharedPreferences("locationHistory", Context.MODE_PRIVATE);
+
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
@@ -52,7 +56,14 @@ 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) {
+ 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()));
}
@@ -79,11 +90,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);
@@ -113,13 +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));
+ 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();
- Toast.makeText(this, "请打开模拟位置权限!", Toast.LENGTH_SHORT).show();
+ 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:
@@ -127,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) {
@@ -156,6 +186,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);
@@ -215,7 +261,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;
diff --git a/app/src/main/java/name/caiyao/fakegps/MainHook.java b/app/src/main/java/name/caiyao/fakegps/MainHook.java
index db162ed..ddfe6ef 100644
--- a/app/src/main/java/name/caiyao/fakegps/MainHook.java
+++ b/app/src/main/java/name/caiyao/fakegps/MainHook.java
@@ -1,16 +1,12 @@
package name.caiyao.fakegps;
import android.content.ContentResolver;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.database.Cursor;
+import android.net.Uri;
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;
@@ -19,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;
@@ -26,10 +23,36 @@
* Created by 蔡小木 on 2016/4/17 0017.
*/
public class MainHook implements IXposedHookLoadPackage {
+
+ public static boolean isHook = false;
+
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
- if (!loadPackageParam.packageName.contains("tencent") && !loadPackageParam.packageName.contains("alibaba") && !loadPackageParam.packageName.contains("baidu"))
+ final Object activityThread = XposedHelpers.callStaticMethod(XposedHelpers.findClass("android.app.ActivityThread", null), "currentActivityThread");
+ final Context systemContext = (Context) XposedHelpers.callMethod(activityThread, "getSystemContext");
+ 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 (value.equals("0")) {
+ isHook = false;
+ }
+ }
+ 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;
+ }
XposedHelpers.findAndHookMethod("android.provider.Settings.Secure", loadPackageParam.classLoader, "getString",
ContentResolver.class, String.class, new XC_MethodHook() {
@Override
@@ -192,14 +215,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 +309,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;
- }
}
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;
+ }
+}