Android 接近警报误报
我在我的应用程序中设置了接近警报,它可以很好地捕捉我的位置。然而,我注意到我收到了很多不该收到的警告,我也不知道为什么 误报的频率与我离prox警报的距离成反比。如果我将prox设置为5公里以外,每隔一小时就会出现误报,但如果我将prox设置为加拿大北部,则不会出现误报 这是我的日志在5公里外的样子(我的范围设置为100米) 有人能看到模式或怀疑我为什么会出现误报吗?(更多可能的线索,请参见底部) 我自然怀疑Prox警报不是很准确,但我没有发现其他人对此抱怨的证据。此外,我的设备上的其他prox alert应用程序(如Road Rooster)也没有出现故障Android 接近警报误报,android,gps,geolocation,proximity,Android,Gps,Geolocation,Proximity,我在我的应用程序中设置了接近警报,它可以很好地捕捉我的位置。然而,我注意到我收到了很多不该收到的警告,我也不知道为什么 误报的频率与我离prox警报的距离成反比。如果我将prox设置为5公里以外,每隔一小时就会出现误报,但如果我将prox设置为加拿大北部,则不会出现误报 这是我的日志在5公里外的样子(我的范围设置为100米) 有人能看到模式或怀疑我为什么会出现误报吗?(更多可能的线索,请参见底部) 我自然怀疑Prox警报不是很准确,但我没有发现其他人对此抱怨的证据。此外,我的设备上的其他prox
//This is called once when when initial location is selected, the code for which I have ommitted.
public void addProximityAlert(double lat, double lng){
LocationManager lm=(LocationManager) getSystemService(LOCATION_SERVICE);
SharedPreferences prefs = getApplicationContext().getSharedPreferences(Constants.SHARED_PREFS, Context.MODE_MULTI_PROCESS);
removeAllProximityAlerts(this);
float range = (float) prefs.getInt("range", -1);
if (range < 0){
prefs.edit().putFloat("range", (float) 50);
range = 50;
}
Intent intent = new Intent(Constants.PROX_INTENT_FILTER);
int alertId= (int) System.currentTimeMillis();
PendingIntent pi = PendingIntent.getBroadcast(this, alertId , intent, 0);
SharedPreferences.Editor editor = prefs.edit();
editor.putInt("maxAlertId", alertId).commit();
Util.putDouble(editor, Constants.DEST_LAT, lat);
Util.putDouble(editor, Constants.DEST_LNG, lng);
editor.commit();
lm.addProximityAlert(lat, lng, range, -1, pi);
}
public void removeAllProximityAlerts(Context context) {
LocationManager lm=(LocationManager) getSystemService(LOCATION_SERVICE);
SharedPreferences prefs = getApplicationContext().getSharedPreferences(Constants.SHARED_PREFS, Context.MODE_MULTI_PROCESS);
int maxAlertId = prefs.getInt("maxAlertId", 0);
Intent intent = new Intent(Constants.PROX_INTENT_FILTER);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this , maxAlertId, intent, 0);
lm.removeProximityAlert(pendingIntent);
}
清单
<?xml version="1.0" encoding="utf-8"?>
引导接收器只是重置报警管理器
附加信息
- 在Nexus5上测试
- 总是在需要时接收prox警报
- 当距离较近时,误报的频率较高
- 我正在我的接收器中检查LocationManager的getLastKnownLocation,它从未被更新,尽管我可能使用不正确
- 切换到显式意图(使用RegisterReceiver)时问题仍然存在
- 即使在只选择了一个位置的干净安装之后,问题仍然存在(这意味着多个冲突警报不是问题)
花了两个周末试图找出这个错误-我一直认为它已被修复,几个小时后,我会得到另一个假阳性 接近警报基于GPS或网络位置。这两种方法都不准确。事实上,在定位对象中传回的精度以米为单位。只有67%的几率你在这个范围内,有1/3的几率你在这个范围之外 轻微的误差远比大的误差大。用GPS离地球10米远?合理,事实上是普遍的。离这里1公里?如果卫星系统发生了奇怪的事情,可能会发生,但应该会很快自我纠正。距离100公里?这是不会发生的,除了软件中的一个bug 因此,假设GPS定位偏离5公里的几率为5%。每分钟更新2个位置,或每小时更新120个位置。没有假阳性的几率为.95^120,或.2%。即使只有1%的几率出现假阳性,也有27%的几率有一个小时没有假阳性。在执行基于位置的算法时,误报只是必须处理的问题
解决这一问题的一种方法是,不要通过近距离警报触发您的操作。相反,当近距离警报触发时,请请求位置更新,并确保其停留在该区域内进行一两次更新。这会增加延迟,但会减少误报。还要注意的是,当您越来越接近目标区域时,误报率会随着将您放入该区域所需的不准确度的降低而增加,因此,误报的可能性更大。接近警报是基于GPS或网络位置的。这两种方法都不准确。事实上,在定位对象中传回的精度以米为单位。只有67%的几率你在这个范围内,有1/3的几率你在这个范围之外 轻微的误差远比大的误差大。用GPS离地球10米远?合理,事实上是普遍的。离这里1公里?如果卫星系统发生了奇怪的事情,可能会发生,但应该会很快自我纠正。距离100公里?这是不会发生的,除了软件中的一个bug 因此,假设GPS定位偏离5公里的几率为5%。每分钟更新2个位置,或每小时更新120个位置。没有假阳性的几率为.95^120,或.2%。即使只有1%的几率出现假阳性,也有27%的几率有一个小时没有假阳性。在执行基于位置的算法时,误报只是必须处理的问题
解决这一问题的一种方法是,不要通过近距离警报触发您的操作。相反,当近距离警报触发时,请请求位置更新,并确保其停留在该区域内进行一两次更新。这会增加延迟,但会减少误报。还要注意的是,当您越来越接近目标区域时,误报率会随着将您放入该区域所需的不准确度的降低而增加,因此这种情况更可能发生。感谢您的回复,这正是我希望听到的。您提到请求位置更新以验证准确性-这是否会在电池方面产生重大成本?我想另一种方法是等待2-3分钟,看看GPS是否能自我修正。刚刚看到你的编辑,这回答了我的最后一个问题,谢谢。如果你一直这么做,它会的。相反,您只能在进入或退出事件后请求它,并在完成后将其关闭。那么,只有当你处于边缘并不断打开它时,这才有意义。此外,由于已经为“倾向性警报”启用了定位功能,因此,如果系统使用网络,并且你使用gpsThanks进行回复,则只会增加电池电量,这是我希望听到的。您提到请求位置更新以验证准确性-这是否会在电池方面产生重大成本?我想另一种方法是等待2-3分钟,看看GPS是否能自我修正。刚刚看到你的编辑,这回答了我的最后一个问题,谢谢。如果你一直这么做,它会的。相反,您只能在进入或退出事件后请求它,并在完成后将其关闭。那就只有签字了
public class ProximityReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent arg1) {
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "");
wl.acquire();
String k = LocationManager.KEY_PROXIMITY_ENTERING;
boolean state = arg1.getBooleanExtra(k, false);
String enterOrLeave;
if (state) {
//Todo: Enter state
enterOrLeave="entered";
updateLastDayRecord("Went to gym");
} else {
//Todo: Exit state
enterOrLeave="exited";
}
//Do stuff (ommitted unrelated code)
}
}
<?xml version="1.0" encoding="utf-8"?>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:name="GlobalState"
android:theme="@style/AppTheme" >
<activity
android:name=".AllinOneActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".IntroductionActivity"
android:label="@string/intro_label"
android:parentActivityName=".AllinOneActivity" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".AllinOneActivity" />
</activity>
<activity android:name=".MessageBodyActivity"
android:label="@string/message_label"
android:parentActivityName=".AllinOneActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".AllinOneActivity" />
</activity>
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="@string/GOOGLE_API_KEY" />
<receiver
android:name=".AlarmManagerBroadcastReceiver"
android:process=":remote">
</receiver>
<receiver
android:name=".ProximityReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.pipit.agc.agc.ProximityReceiver" />
</intent-filter>
</receiver>
<receiver android:name=".BootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
</application>