Foreground service not receiving location updates in Android 7.0+ when screen is off(屏幕关闭时,前台服务未在 Android 7.0+ 中接收位置更新)
问题描述
我正在尝试创建一个 Android 应用程序,该应用程序可以在设备屏幕关闭时持续实时记录设备位置数据.我的代码适用于 Android 6.0 及更早版本,但似乎 Android 7.0+ 破坏了我的应用程序.
I am trying to create an Android application that continuously logs device location data in realtime while the device screen is off. My code works correctly with Android 6.0 and earlier but it seems that Android 7.0+ breaks my app.
我已经实现了一个使用唤醒锁并订阅 Google FusedLocation API 的 Android 前台服务.一旦屏幕关闭,就永远不会触发 onLocationChanged
回调.
I have implemented an Android foreground service that uses a wakelock and subscribes to the Google FusedLocation API. Once the screen is turned off the onLocationChanged
callback is never triggered.
有没有人看到这个问题的解决方案?我已尝试通过 Android 设备设置为我的应用以及 Google 服务框架和 Fused Location 禁用电池优化.
Has anyone seen a solution to this problem? I have tried disabling Battery Optimization through the Android Device Settings for my app as well as for the Google Services Framework and the Fused Location.
public class ForegroundLocationService extends Service implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener {
private static final String TAG = ForegroundLocationService.class.getSimpleName();
// the notification id for the foreground notification
public static final int GPS_NOTIFICATION = 1;
// the interval in seconds that gps updates are requested
private static final int UPDATE_INTERVAL_IN_SECONDS = 15;
// is this service currently running in the foreground?
private boolean isForeground = false;
// the google api client
private GoogleApiClient googleApiClient;
// the wakelock used to keep the app alive while the screen is off
private PowerManager.WakeLock wakeLock;
@Override
public void onCreate() {
super.onCreate();
// create google api client
googleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
// get a wakelock from the power manager
final PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (!isForeground) {
Log.v(TAG, "Starting the " + this.getClass().getSimpleName());
startForeground(ForegroundLocationService.GPS_NOTIFICATION,
notifyUserThatLocationServiceStarted());
isForeground = true;
// connect to google api client
googleApiClient.connect();
// acquire wakelock
wakeLock.acquire();
}
return START_REDELIVER_INTENT;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onDestroy() {
Log.v(TAG, "Stopping the " + this.getClass().getSimpleName());
stopForeground(true);
isForeground = false;
// disconnect from google api client
googleApiClient.disconnect();
// release wakelock if it is held
if (null != wakeLock && wakeLock.isHeld()) {
wakeLock.release();
}
super.onDestroy();
}
private LocationRequest getLocationRequest() {
LocationRequest locationRequest = LocationRequest.create();
// we always want the highest accuracy
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
// we want to make sure that we get an updated location at the specified interval
locationRequest.setInterval(TimeUnit.SECONDS.toMillis(0));
// this sets the fastest interval that the app can receive updates from other apps accessing
// the location service. for example, if Google Maps is running in the background
// we can update our location from what it sees every five seconds
locationRequest.setFastestInterval(TimeUnit.SECONDS.toMillis(0));
locationRequest.setMaxWaitTime(TimeUnit.SECONDS.toMillis(UPDATE_INTERVAL_IN_SECONDS));
return locationRequest;
}
private Notification notifyUserThatLocationServiceStarted() {
// pop up a notification that the location service is running
Intent notificationIntent = new Intent(this, NotificationActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);
final Notification.Builder builder = new Notification.Builder(this)
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentTitle(getString(R.string.foreground_location_service))
.setContentText(getString(R.string.service_is_running))
.setContentIntent(pendingIntent)
.setWhen(System.currentTimeMillis());
final Notification notification;
if (Build.VERSION.SDK_INT < 16) {
notification = builder.getNotification();
} else {
notification = builder.build();
}
return notification;
}
@Override
public void onConnected(@Nullable Bundle bundle) {
try {
// request location updates from the fused location provider
LocationServices.FusedLocationApi.requestLocationUpdates(
googleApiClient, getLocationRequest(), this);
} catch (SecurityException securityException) {
Log.e(TAG, "Exception while requesting location updates", securityException);
}
}
@Override
public void onConnectionSuspended(int i) {
Log.i(TAG, "Google API Client suspended.");
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
Log.e(TAG, "Failed to connect to Google API Client.");
}
@Override
public void onLocationChanged(Location location) {
Log.e(TAG, "onLocationChanged: " + location.toString());
}
}
我在这里包含了我用来测试的代码的完整工作示例:https://github.com/joshuajwitter/ForegroundLocationService
I have included a complete working sample of the code that I am using to test here: https://github.com/joshuajwitter/ForegroundLocationService
FitBit 好像也一样问题,这里是讨论
以下是我已经看过的资源:
Here are the resources that I have already looked at:
Android O 代码示例
保持应用在后台运行一直在安卓上
安卓,在屏幕关闭时获取位置
后台位置限制
深度睡眠(打瞌睡)时前台服务中的位置更新不一致
前台服务未接收位置Android O 中打盹模式的更新
编辑 2018.01.30:我也尝试在自己的进程中运行 ForegroundLocationService:
EDIT 2018.01.30: I have also tried running the ForegroundLocationService in its own process:
<service
android:name="foregroundlocation.stackoverflowexample.com.foregroundlocation.ForegroundLocationService"
android:enabled="true"
android:stopWithTask="false"
android:process=":ForegroundLocationService"
android:exported="false" >
</service>
以及更新我的代码以使用 FusedLocationProviderClient
,仍然没有运气.
as well as updating my code to use the FusedLocationProviderClient
, still no luck.
推荐答案
我在运行 7.0 和 8.0 的模拟设备上遇到了这个问题,并且在屏幕关闭 (cmd+P) 时始终没有触发位置回调.我终于能够拿到真正的 7.0 设备(Galaxy S7),但我无法复制这个问题.对不起,如果我浪费了任何人的时间,显然这是一个模拟器问题.
I had been experiencing this issue on emulated devices running 7.0 and 8.0 and consistently the location callback was not being triggered when the screen was off (cmd+P). I was finally able to get my hands on a real 7.0 device (Galaxy S7) and I was not able to replicate the issue. Sorry if I wasted anyone's time, apparently it is an emulator issue.
这篇关于屏幕关闭时,前台服务未在 Android 7.0+ 中接收位置更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:屏幕关闭时,前台服务未在 Android 7.0+ 中接收位置更新
基础教程推荐
- 如何在 iPhone 上显示来自 API 的 HTML 文本? 2022-01-01
- 当从同一个组件调用时,两个 IBAction 触发的顺序是什么? 2022-01-01
- 如何在 UIImageView 中异步加载图像? 2022-01-01
- android 应用程序已发布,但在 google play 中找不到 2022-01-01
- 如何在没有IB的情况下将2个按钮添加到右侧的UINavigationbar? 2022-01-01
- 在 gmail 中为 ios 应用程序检索朋友的朋友 2022-01-01
- Android:对话框关闭而不调用关闭 2022-01-01
- Kivy Buildozer 无法构建 apk,命令失败:./distribute.sh -m “kivy"d 2022-01-01
- 如何让对象对 Cocos2D 中的触摸做出反应? 2022-01-01
- UIWebView 委托方法 shouldStartLoadWithRequest:在 WKWebView 中等效? 2022-01-01