Использование базовой функции R aggregate
:
aggregate(value ~ name, dat1, I)
# name value.1 value.2 value.3 value.4
#1 firstName 0.4145 -0.4747 0.0659 -0.5024
#2 secondName -0.8259 0.1669 -0.8962 0.1681
Я провел некоторое расследование и поделился своими результатами здесь, это может быть полезно для других.
Сначала мы можем проверить, включена ли опция MockSetting
public static boolean isMockSettingsON(Context context) {
// returns true if mock location enabled, false if not enabled.
if (Settings.Secure.getString(context.getContentResolver(),
Settings.Secure.ALLOW_MOCK_LOCATION).equals("0"))
return false;
else
return true;
}
Second , мы можем проверить, есть ли в устройстве другие приложения, которые используют android.permission.ACCESS_MOCK_LOCATION
(Приложения для спуфинга места)
public static boolean areThereMockPermissionApps(Context context) {
int count = 0;
PackageManager pm = context.getPackageManager();
List<ApplicationInfo> packages =
pm.getInstalledApplications(PackageManager.GET_META_DATA);
for (ApplicationInfo applicationInfo : packages) {
try {
PackageInfo packageInfo = pm.getPackageInfo(applicationInfo.packageName,
PackageManager.GET_PERMISSIONS);
// Get Permissions
String[] requestedPermissions = packageInfo.requestedPermissions;
if (requestedPermissions != null) {
for (int i = 0; i < requestedPermissions.length; i++) {
if (requestedPermissions[i]
.equals("android.permission.ACCESS_MOCK_LOCATION")
&& !applicationInfo.packageName.equals(context.getPackageName())) {
count++;
}
}
}
} catch (NameNotFoundException e) {
Log.e("Got exception " , e.getMessage());
}
}
if (count > 0)
return true;
return false;
}
Если оба метода выше, первый и второй являются истинными, тогда есть хорошие шансы это местоположение может быть подделанным или поддельным.
Теперь с помощью API-интерфейса диспетчера местоположений можно избежать спуфинга.
Мы можем удалить поставщика теста, прежде чем запрашивать обновления местоположения как у поставщиков (сеть и GPS)
LocationManager lm = (LocationManager) getSystemService(LOCATION_SERVICE);
try {
Log.d(TAG ,"Removing Test providers")
lm.removeTestProvider(LocationManager.GPS_PROVIDER);
} catch (IllegalArgumentException error) {
Log.d(TAG,"Got exception in removing test provider");
}
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, locationListener);
Я видел, что removeTestProvider (~) отлично работает над версией Jelly Bean и далее. Этот API оказался ненадежным до Ice Cream Sandwich.
Этот скрипт работает для всей версии Android, и я нахожу его после многих поисков
LocationManager locMan;
String[] mockProviders = {LocationManager.GPS_PROVIDER, LocationManager.NETWORK_PROVIDER};
try {
locMan = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
for (String p : mockProviders) {
if (p.contentEquals(LocationManager.GPS_PROVIDER))
locMan.addTestProvider(p, false, false, false, false, true, true, true, 1,
android.hardware.SensorManager.SENSOR_STATUS_ACCURACY_HIGH);
else
locMan.addTestProvider(p, false, false, false, false, true, true, true, 1,
android.hardware.SensorManager.SENSOR_STATUS_ACCURACY_LOW);
locMan.setTestProviderEnabled(p, true);
locMan.setTestProviderStatus(p, android.location.LocationProvider.AVAILABLE, Bundle.EMPTY,
java.lang.System.currentTimeMillis());
}
} catch (Exception ignored) {
// here you should show dialog which is mean the mock location is not enable
}
Спустя пару лет наткнулся на эту тему. В 2016 году большинство устройств Android будут иметь уровень API> = 18 и поэтому должны полагаться на Location.isFromMockProvider (), как указано Fernando .
Я интенсивно экспериментировал с фальшивым / макетным местоположения на разных устройствах и дистрибутивах Android. К сожалению .isFromMockProvider () не на 100% надежнее. Время от времени подделка не будет помечена как макет . Похоже, что это связано с некоторой ошибочной логикой внутреннего слияния в Google Location API.
Я написал подробное сообщение в блоге об этом , если вы хотите узнать больше. Подводя итог, если вы подписаны на обновления местоположения из API местоположения, затем включите поддельное приложение GPS и распечатайте результат каждой команды Location.toString () на консоли, вы увидите что-то вроде этого:
Обратите внимание, что в потоке обновлений местоположения одно местоположение имеет те же координаты, что и другие, но не помечено как макет и имеет гораздо более худшую точность местоположения.
Чтобы исправить эту проблему, я написал класс утилиты, который будет надежно подавлять местоположения Mock во всех современных версиях Android (уровень API 15 и выше):
LocationAssistant - бесплатные обновления местоположения на Android
В принципе, он «недоверяет» немощные местоположения, которые находятся в пределах 1 км от последнего известного макетного местоположения, а также называет их как макет. Он делает это до тех пор, пока не достигнет значительного количества немощных мест. LocationAssistant может не только отбрасывать ложные местоположения, но и освобождает вас от большинства проблем с настройкой и подпиской на обновления местоположения.
Чтобы получать только реальные обновления местоположения (например, подавлять издевки), используйте его следующим образом :
public class MyActivity extends Activity implements LocationAssistant.Listener {
private LocationAssistant assistant;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
// You can specify a different accuracy and interval here.
// The last parameter (allowMockLocations) must be 'false' to suppress mock locations.
assistant = new LocationAssistant(this, this, LocationAssistant.Accuracy.HIGH, 5000, false);
}
@Override
protected void onResume() {
super.onResume();
assistant.start();
}
@Override
protected void onPause() {
assistant.stop();
super.onPause();
}
@Override
public void onNewLocationAvailable(Location location) {
// No mock locations arriving here
}
...
}
onNewLocationAvailable()
теперь будет вызываться только с информацией о реальном местоположении. Есть еще несколько методов слушателя, которые вам нужно реализовать, но в контексте вашего вопроса (как предотвратить спуфинг с GPS) это в основном это.
Конечно, с корневой ОС вы все равно можете найти способы информация о спуфинге, которую невозможно обнаружить обычным приложениям.
Кажется, что единственный способ сделать это - предотвратить спуфинг места, предотвращающий MockLocations. С другой стороны, есть некоторые пользователи, которые используют Bluetooth-устройства GPS для получения лучшего сигнала, они не смогут использовать приложение, поскольку они должны использовать макет местоположения.
Для этого я сделал следующее:
// returns true if mock location enabled, false if not enabled.
if (Settings.Secure.getString(getContentResolver(),
Settings.Secure.ALLOW_MOCK_LOCATION).equals("0"))
return false;
else return true;
return !x
вместо if(x) return false; else return true
.
– CodesInChaos
12 August 2014 в 14:10
Поскольку API 18, объект Местоположение имеет метод .isFromMockProvider () , поэтому вы можете отфильтровывать поддельные местоположения.
Если вы хотите поддерживать версии до 18, можно использовать что-то вроде этого:
boolean isMock = false;
if (android.os.Build.VERSION.SDK_INT >= 18) {
isMock = location.isFromMockProvider();
} else {
isMock = !Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION).equals("0");
}
isMock = !Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION).equals("0");
– AjahnCharles
18 July 2016 в 18:48
попробуйте этот код очень просто и полезно
public boolean isMockLocationEnabled() {
boolean isMockLocation = false;
try {
//if marshmallow
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
AppOpsManager opsManager = (AppOpsManager) getApplicationContext().getSystemService(Context.APP_OPS_SERVICE);
isMockLocation = (opsManager.checkOp(AppOpsManager.OPSTR_MOCK_LOCATION, android.os.Process.myUid(), BuildConfig.APPLICATION_ID)== AppOpsManager.MODE_ALLOWED);
} else {
// in marshmallow this will always return true
isMockLocation = !android.provider.Settings.Secure.getString(getApplicationContext().getContentResolver(), "mock_location").equals("0");
}
} catch (Exception e) {
return isMockLocation;
}
return isMockLocation;
}
Если вам удалось узнать общее местоположение вышек сотовой связи, вы можете проверить, соответствует ли текущая ячейковая башня указанному местоположению (в пределах допустимой погрешности чего-то большого, например, 10 или более миль).
Например, если ваше приложение разблокирует функции только в том случае, если пользователь находится в определенном месте (например, в вашем магазине), вы можете проверить gps, а также сотовые башни. В настоящее время ни одно приложение для спуфинга gps также не обманывает башни сотовых телефонов, поэтому вы можете увидеть, пытается ли кто-то по всей стране просто подтолкнуть их к вашим особым функциям (например, я думаю о приложении Disney Mobile Magic на одном примере).
Так как приложение Llama управляет местоположением по умолчанию, так как проверка идентификаторов ячеек ячеек значительно меньше, чем у gps. Это не полезно для очень конкретных мест, но если дом и работа находятся в нескольких милях от него, он может легко различать два общих местоположения.
Конечно, это потребует от пользователя наличия ячейки сигнал вообще. И вам нужно будет знать все идентификаторы ячеек в этой области - на всех сетевых провайдерах - или вы рискуете ложным отрицанием.
Вы можете добавить дополнительную проверку, основанную на триангуляции башни ячеек или информации о точках доступа Wi-Fi, используя API геолокации Google Maps
Самый простой способ получить информацию о CellTowers
final TelephonyManager telephonyManager = (TelephonyManager) appContext.getSystemService(Context.TELEPHONY_SERVICE);
String networkOperator = telephonyManager.getNetworkOperator();
int mcc = Integer.parseInt(networkOperator.substring(0, 3));
int mnc = Integer.parseInt(networkOperator.substring(3));
String operatorName = telephonyManager.getNetworkOperatorName();
final GsmCellLocation cellLocation = (GsmCellLocation) telephonyManager.getCellLocation();
int cid = cellLocation.getCid();
int lac = cellLocation.getLac();
Вы можете сравнить свои результаты с сайтом
. Чтобы получить информацию о точках доступа Wifi
final WifiManager mWifiManager = (WifiManager) appContext.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
if (mWifiManager != null && mWifiManager.getWifiState() == WifiManager.WIFI_STATE_ENABLED) {
// register WiFi scan results receiver
IntentFilter filter = new IntentFilter();
filter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
List<ScanResult> results = mWifiManager.getScanResults();//<-result list
}
};
appContext.registerReceiver(broadcastReceiver, filter);
// start WiFi Scan
mWifiManager.startScan();
}
android.permission.ACCESS_MOCK_LOCATION
для работыremoveTestProvider
, что, по моему мнению, является самым большим недостатком. – Timur_C 17 March 2015 в 18:41isMockSettingsON()
,Location.isFromMockProvider()
иareThereMockPermissionApps()
с черным списком приложений. Существует множество предустановленных системных приложений с разрешениемACCESS_MOCK_LOCATION
, например, на устройствах HTC и Samsung. Белым списком всех законных приложений было бы лучше, но черный список самых популярных приложений для спуфинга приложений хорошо работал в моем случае. И я также проверил, было ли устройство укоренено. – Timur_C 12 May 2016 в 23:11