gpt4 book ai didi

android - locationListener 在前台服务 30 秒后不起作用

转载 作者:行者123 更新时间:2023-11-29 02:18:11 26 4
gpt4 key购买 nike

我创建了一个服务,它可以找到用户的坐标,然后将其存储在 SQLite 数据库中。

public class GPS_Service extends Service {

DatabaseHelper myDb;

private LocationListener locationListener;
private LocationManager locationManager;

private String latitude, longitude;

@Override
public void onCreate() {
super.onCreate();

myDb = new DatabaseHelper(this);

}

@SuppressLint("MissingPermission")
@Override
public int onStartCommand(Intent intent, int flags, int startId) {

Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,0, notificationIntent, 0);

Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Service")
.setContentText("Coordinates Location Running")
.setContentIntent(pendingIntent)
.build();

startForeground(1, notification);

locationListener = new LocationListener() {

@Override
public void onLocationChanged(Location location) {

Log.d("myTag", "Hello");

latitude = String.valueOf(location.getLatitude());
longitude = String.valueOf(location.getLongitude());

insertCoordinates(latitude, longitude);

Intent i = new Intent("location_update");
i.putExtra("latitude", latitude);
i.putExtra("longitude",longitude);

sendBroadcast(i);

}

@Override
public void onStatusChanged(String provider, int status, Bundle extras) {

}

@Override
public void onProviderEnabled(String provider) {

}

@Override
public void onProviderDisabled(String provider) {

Intent i = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);

}

};

locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 0, locationListener);

return START_NOT_STICKY;

}

@Override
public void onDestroy() {

super.onDestroy();

if(locationManager != null)
locationManager.removeUpdates(locationListener);

}

private void insertCoordinates(String latitude, String longitude) {

boolean inserted = myDb.insertData(latitude, longitude); //Insert coordinates

//Check if insertion is completed
if(inserted)
Toast.makeText(GPS_Service.this, "Coordinates Inserted", Toast.LENGTH_SHORT).show();
else
Toast.makeText(GPS_Service.this, "Coordinates Not Inserted", Toast.LENGTH_SHORT).show();

}

@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}

}

我可以像这样从 MainActivity 启动或停止服务

private void enable_buttons() {

buttonStartService.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {

Intent serviceIntent = new Intent(getApplicationContext(), GPS_Service.class);

//Checks if the SDK version is higher than 26 to act accordingly
ContextCompat.startForegroundService(MainActivity.this, serviceIntent);

}
});

buttonStopService.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {

Intent serviceIntent = new Intent(MainActivity.this, GPS_Service.class);
stopService(serviceIntent);

}
});

}

问题是,当我启动此服务时,如果我完全关闭该应用程序或将其留在后台,locationListener 将工作 30 秒,然后停止。如果我重新打开该应用程序,该服务会从它停止的地方继续工作。如果服务正在运行,我还检查了开发人员选项,即使 locationListener 没有输出预期的结果,它确实也是如此。有什么想法吗?

最佳答案

长话短说:

android:foregroundServiceType="location" 添加到您的 Service 的 list 条目。

解释

对于 Android 10,这一新行为与您所描述的完全一样:即使您可能正在使用前台服务,但在您的应用离开屏幕 30 秒后 - 位置更新会停止。

您可能已经注意到,Android 10 设备在授予位置权限时向用户提供了两个新选择(对于旧版 (API < 29) 应用或声明了 ACCESS_BACKGROUND_LOCATION 权限的应用):

  • “一直允许”
  • “仅在使用此应用时允许”

“仅在使用此应用程序时允许”实际上意味着“当应用程序在屏幕上可见时允许”。这是因为用户现在可以根据该标准有选择地删除位置访问权限——甚至是前台服务。用户可以随时更改此设置,即使您的应用正在运行也是如此。

Android docs解释该解决方案 android:foregroundServiceType="location" 是为您的具体用例设计的:类似“Google map ”的应用程序,具有前台服务,但预计会继续处理位置数据如果用户切换到另一个应用程序。该技术称为“继续用户启动的操作”,即使您的应用程序处于“后台”,它也允许您获取位置更新。

(文档似乎在这里扩展了术语“后台”的定义。过去,如果您有前台服务,您的应用程序将被视为“在前台”——至少出于任务的目的优先级、Doze 等等。现在看来,如果某个应用在过去 30 秒内未出现在屏幕上,则就位置访问而言,该应用被视为“在后台”。)

当您设置特定的 foregroundServiceType 时,我不确定 UI 会发生什么变化(例如在 Google Play 商店中)。无论如何,在我看来用户不太可能反对。

适用于 Android 10 设备的其他解决方案

或者,您可以声明 28 或更低的 targetSdkVersion,这将使您的应用在“兼容模式”位置运行。

您还可以选择获得 ACCESS_BACKGROUND_LOCATION 权限,但是 docs警告:

If your app doesn't require location access while running in the background, it's highly recommended that you not request ACCESS_BACKGROUND_LOCATION...

对于您的用例,这种方法不是必需的,因为您的 Activity 用于启动您的 Service;在 Service 开始获取后台位置更新之前,您可以保证您的应用至少出现在屏幕上一次。 (至少,我假设这就是操作系统确定“用户启动的操作”开始的方式。据推测,foregroundServiceType 方法将不起作用,如果您重新从 JobSchedulerBroadcastReceiver 或其他东西启动 Service。)

PS:请继续使用 WakeLock 代码。如果您想以 10 秒的稳定速度持续获取更新,则需要让设备保持唤醒状态。

关于android - locationListener 在前台服务 30 秒后不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58746210/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com