- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我目前正在开发一款必须每五分钟检查一次用户位置并将坐标发送到服务器的应用程序。我决定使用 Google Play 服务中的 FusedLocation API 而不是普通的旧 LocationManager API,主要是因为我注意到 LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY 优先级,它声称可以提供 100 米的精度级别和合理的电池使用情况,这正是我所需要的。
在我的例子中,我有一个 Activity,它的继承结构是:
public class MainActivity extends AppCompatActivity implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener
并实现了相关的回调(onConnected、onConnectionFailed、onConnectionSuspended、onLocationChanged)。按照官方文档的建议,我还使用这种方法获得了 GoogleApiClient 的一个实例:
protected synchronized GoogleApiClient buildGoogleApiClient() {
return new GoogleApiClient.Builder(this).addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
在 onConnected 中,我通过使用开始位置更新
LocationServices.FusedLocationApi.requestLocationUpdates(mApiClient,
mLocationRequest, this);
...并在 onLocationChanged() 中捕捉变化。
但是,我很快发现位置更新似乎在一段时间后停止了。也许是因为此方法与 Activity 生命周期相关联,我不确定。无论如何,我试图通过创建一个扩展 IntentService 的内部类并通过 AlarmManager 启动它来解决这个问题。所以在 onConnected 中,我最终这样做了:
AlarmManager alarmMan = (AlarmManager) this
.getSystemService(Context.ALARM_SERVICE);
Intent updateIntent = new Intent(this, LocUpService.class);
PendingIntent pIntent = PendingIntent.getService(this, 0, updateIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
alarmMan.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, 0,
1000 * 60 * 5, pIntent);
LocUpService 类如下所示:
public static class LocUpService extends IntentService {
public LocUpService() {
super("LocUpService");
}
@Override
protected void onHandleIntent(Intent intent) {
Coords coords = LocationUpdater.getLastKnownLocation(mApiClient);
}
}
LocationUpdater是另外一个类,里面包含静态方法getLastKnownLocation,就是这样的:
public static Coords getLastKnownLocation(GoogleApiClient apiClient) {
Coords coords = new Coords();
Location location = LocationServices.FusedLocationApi
.getLastLocation(apiClient);
if (location != null) {
coords.setLatitude(location.getLatitude());
coords.setLongitude(location.getLongitude());
Log.e("lat ", location.getLatitude() + " degrees");
Log.e("lon ", location.getLongitude() + " degrees");
}
return coords;
}
但是惊喜!!当我清楚地将引用传递给静态方法时,我得到“IllegalArgumentException:GoogleApiClient 参数是必需的”,我再次猜测这一定与 GoogleApiClient 实例有关,该实例与 Activity 的生命周期有关,并且将实例传递到 Intent 服务。
所以我在想:如何在不发疯的情况下每五分钟定期更新一次位置信息?我是否扩展服务,在该组件上实现所有接口(interface)回调,在其中构建 GoogleApiClient 实例并使其在后台运行?我是否让 AlarmManager 启动一项服务,每五分钟扩展一次 IntentService 来完成这项工作,再次在 IntentService 中构建所有相关的回调和 GoogleApiClient?我是否继续做我现在正在做的事情,但将 GoogleApiClient 构造为单例,并期望它会有所作为?你会怎么做?
感谢并抱歉这么长篇大论。
最佳答案
I am currently working on an app that has to check the user's location every five minutes and send the coordinates to a server. I decided to go with the FusedLocation API in Google Play Services instead of the plain old LocationManager API
我们的应用程序具有完全相同的要求,我在几天前实现了它,这就是我的实现方式。
在启动 Activity 中或任何您想开始的地方,使用 AlarmManager 配置 LocationTracker 每 5 分钟运行一次。
private void startLocationTracker() {
// Configure the LocationTracker's broadcast receiver to run every 5 minutes.
Intent intent = new Intent(this, LocationTracker.class);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, Calendar.getInstance().getTimeInMillis(),
LocationProvider.FIVE_MINUTES, pendingIntent);
}
LocationTracker.java
public class LocationTracker extends BroadcastReceiver {
private PowerManager.WakeLock wakeLock;
@Override
public void onReceive(Context context, Intent intent) {
PowerManager pow = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
wakeLock = pow.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "");
wakeLock.acquire();
Location currentLocation = LocationProvider.getInstance().getCurrentLocation();
// Send new location to backend. // this will be different for you
UserService.registerLocation(context, new Handlers.OnRegisterLocationRequestCompleteHandler() {
@Override
public void onSuccess() {
Log.d("success", "UserService.RegisterLocation() succeeded");
wakeLock.release();
}
@Override
public void onFailure(int statusCode, String errorMessage) {
Log.d("error", "UserService.RegisterLocation() failed");
Log.d("error", errorMessage);
wakeLock.release();
}
}, currentLocation);
}
}
LocationProvider.java
public class LocationProvider {
private static LocationProvider instance = null;
private static Context context;
public static final int ONE_MINUTE = 1000 * 60;
public static final int FIVE_MINUTES = ONE_MINUTE * 5;
private static Location currentLocation;
private LocationProvider() {
}
public static LocationProvider getInstance() {
if (instance == null) {
instance = new LocationProvider();
}
return instance;
}
public void configureIfNeeded(Context ctx) {
if (context == null) {
context = ctx;
configureLocationUpdates();
}
}
private void configureLocationUpdates() {
final LocationRequest locationRequest = createLocationRequest();
final GoogleApiClient googleApiClient = new GoogleApiClient.Builder(context)
.addApi(LocationServices.API)
.build();
googleApiClient.registerConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
@Override
public void onConnected(Bundle bundle) {
startLocationUpdates(googleApiClient, locationRequest);
}
@Override
public void onConnectionSuspended(int i) {
}
});
googleApiClient.registerConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
});
googleApiClient.connect();
}
private static LocationRequest createLocationRequest() {
LocationRequest locationRequest = new LocationRequest();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(FIVE_MINUTES);
return locationRequest;
}
private static void startLocationUpdates(GoogleApiClient client, LocationRequest request) {
LocationServices.FusedLocationApi.requestLocationUpdates(client, request, new com.google.android.gms.location.LocationListener() {
@Override
public void onLocationChanged(Location location) {
currentLocation = location;
}
});
}
public Location getCurrentLocation() {
return currentLocation;
}
}
我首先在扩展应用程序的类中创建 LocationProvider 的实例,在应用程序启动时创建实例:
MyApp.java
public class MyApp extends Application {
@Override
public void onCreate() {
super.onCreate();
LocationProvider locationProvider = LocationProvider.getInstance();
locationProvider.configureIfNeeded(this);
}
}
LocationProvider 被实例化并配置为仅一次位置更新,因为它是一个单例。每 5 分钟它将更新其 currentLocation
值,我们可以从任何我们需要的地方检索该值
Location loc = LocationProvider.getInstance().getCurrentLocation();
不需要运行任何类型的后台服务。 AlarmManager 将每 5 分钟向 LocationTracker.onReceive() 广播一次,部分唤醒锁将确保代码将完成运行,即使设备处于待机状态。这也是节能的。
请注意,您需要以下权限
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<!-- For keeping the LocationTracker alive while it is doing networking -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
并且不要忘记注册接收器:
<receiver android:name=".LocationTracker" />
关于java - 如何使用 FusedLocation API 每 5 分钟接收一次位置更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32979633/
我正在尝试获取从过去的 startposition/location 到当前移动的 currentposition/location 的距离(以米为单位)。 我确实有工作正常的currentposit
所以我有一堆绝对覆盖的 div。用户通过在叠加层上拖动来创建方形 div。如果您要创建一个 div,然后放大和缩小,div 会保持在同一位置,因为它对叠加层是绝对的,如前所述。 然而问题就出在这里。您
我想找到 View 在显示屏幕上的位置。 为此,我使用了 view.getLeft() 、view.getBottom() 、view.getRight() 等方法> , view.getTop()。
我有一个看起来像这样的 View 层次结构(基于其他答案和 Apple 的使用 UIScrollView 的高级 AutoLayout 指南): ScrollView 所需的2 个步骤是: 为 Scr
所以我有一个名为 MARKS 的表,我有这些列 STUDENT_ID, CLASSFORM_NAME, ACADEMIC_YEAR, TERM, SUBJECT_NAME, TOTAL_MARKS
我有一个问题我无法理解,请帮助: 我开发了带有图像的 html 页面,并使用 jQuery UI 帮助使它们可拖动,我将这些图像位置设置为相对位置并给出了左侧和顶部像素,这是页面的链接 http://
我正在尝试创建一个 CSS 动画,它在 sprite 表中循环播放 16 个图像,给人一种幽灵“漂浮”的错觉。动画通过在 background-position 位置之间移动以显示不同状态的幽灵来实现
我正在创建这个网站的 WebView https://nearxt.com/打开时询问位置但是当我使用此链接在 flutter 中创建 webview 时那么它就无法定位我还在应用程序中定义了位置,但
我正在以编程方式创建一个需要跨越 2 个屏幕的窗口。正在创建的窗口的大小是正确的,但窗口大约从第一个屏幕的一半开始。我可以将它拖回第一个屏幕的开头,NSWindow 非常适合。 我只需要知道在窗口的起
位置“/”的匹配叶路由没有元素。这意味着默认情况下它将呈现一个空值,从而导致一个“空”页面 //App.js File import { BrowserRouter as Router, Routes
我有一个运行 Ubuntu 和 Apache 的 VPS 例如,假设地址是:5.5.5.5 在 VPS 上,我有一个名为 eggdrop 的用户(除了我的 root 用户)。 用户 eggdrop 有
我有一个 JLabel与 ImageIcon ,我使用 setIcon() JLabel中的函数. ImageIcon然后上来,坐在我的JLabel 的文字左侧.是否有可能拥有 ImageIcon在文
我的图中有节点,它们的 xlabels 位于它们的左上方。我怎样才能改变这个位置?我希望 xlabels 正好位于节点本身的旁边。 最佳答案 xlp是你想要的属性,但它没有做任何事情。 你不能改变位置
我对基本的 VIM 功能有疑问:(我尝试谷歌搜索但找不到答案) 如何列出所有自定义功能。(我做了 :function 并且不能找到我的自定义函数) 如何获得自定义函数列表中的函数(或它们的存储位置)。
我是 PHP 的新手,虽然我一直在搜索,但我不知道该怎么做。 我知道可以使用 Location("some page") 进行重定向。我还读到,只要没有向用户显示任何内容,它就可以工作。 我想做的是:
如果在 jgrowl.css 中位置更改为“center”,我如何将其覆盖为默认值,即“top-right” $.jGrowl(data, { header: 'data', an
我需要根据用户是否滑动屏幕顶部、屏幕中间或屏幕底部来触发不同的事件。我正在尝试找出最好/最简单的方法来做到这一点,因为我很确定没有办法从 UISwipeGestureRecognizer 获取位置。
我需要枚举用delphi编写的外部应用程序中使用的类 ,因此我需要访问VMT表以获取该信息,但是我找不到任何有关如何在exe(由delphi生成)文件中找到VMT(虚拟方法表)的位置(地址)的文档。
在 D2010 (unicode) 中是否有像 Pos 这样不区分大小写的类似函数? 我知道我可以使用 Pos(AnsiUpperCase(FindString), AnsiUpperCase(Sou
我正在尝试为我的reveal.js 演示文稿制作一个标题,该标题会粘贴在屏幕顶部。标题中的内容在每张幻灯片的基础上都是动态的,因此我必须将标记放在 section 标记中。 显然,如果标记在 sect
我是一名优秀的程序员,十分优秀!