android - 未显示应用时,Android 前台停止
问题描述
我是 android 新手,正在开发一个 Android 应用程序,该应用程序每隔几秒钟进行一次测量,并将这些测量结果链接到用户的当前位置。即使用户正在使用手机(应用程序已最小化)或屏幕锁定时,仍应收集数据。我应该注意,这个应用程序是为了在内部使用(而不是在 Google Play 商店中)并且得到用户的完全许可!
在查看 Android 文档时,我发现前台服务可能是我的解决方案。所以我按照记录的方式实施了这项服务。在对应用程序进行编程时,一切似乎都运行良好,但是当我开始制作应用程序的发布版本并测试应用程序时,我注意到了一些意外行为。这是我用于服务并从我的活动中调用服务的代码:
public class LocationService extends Service {
private final LocationServiceBinder binder = new LocationServiceBinder();
private final String TAG = "LocationService";
private LocationListener mLocationListener;
private LocationManager mLocationManager;
private PowerManager.WakeLock wakeLock;
private Timer timer;
private final int LOCATION_INTERVAL = 500;
private final int LOCATION_DISTANCE = 1;
@Override
public void onCreate() {
startForeground(12345678, getNotification());
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
PowerManager pm = (PowerManager)getSystemService(POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Service:WakeLock");
wakeLock.acquire();
startTracking();
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public void onTaskRemoved(Intent rootIntent) {
task.cancel();
wakeLock.release();
if (timer != null) {
timer.cancel();
timer.purge();
timer.cancel();
timer = null;
}
if (mLocationManager != null) {
try {
mLocationManager.removeUpdates(mLocationListener);
} catch (Exception ex) {
Log.i(TAG, "fail to remove location listeners, ignore", ex);
}
}
stopForeground(true);
stopSelf();
super.onTaskRemoved(rootIntent);
}
private Notification getNotification() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel("channel_01",
"My Channel", NotificationManager.IMPORTANCE_DEFAULT);
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,
0, intent, 0);
return new NotificationCompat.Builder(this, "channel_01")
.setContentTitle("APP")
.setContentText("App is running!")
.setContentIntent(pendingIntent).build();
}
@Override
public IBinder onBind(Intent intent) {
return binder;
}
public class LocationServiceBinder extends Binder {
public LocationService getService() {
return LocationService.this;
}
}
private TimerTask task = new TimerTask() {
@Override
public void run() {
requestLocationInformation();
}
};
public void startTracking() {
initializeLocationManager();
mLocationListener = new LocationListener(LocationManager.GPS_PROVIDER);
if (timer == null) {
timer = new Timer("Measurements");
timer.scheduleAtFixedRate(task, 1000, 5000);
}
try {
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
LOCATION_INTERVAL, LOCATION_DISTANCE, mLocationListener);
} catch (java.lang.SecurityException ex) {
Log.i(TAG, "fail to request location update, ignore", ex);
} catch (IllegalArgumentException ex) {
Log.d(TAG, "gps provider does not exist " + ex.getMessage());
}
}
}
private class LocationListener implements android.location.LocationListener {
private Location lastLocation = null;
private final String TAG = "LocationListener";
private Location mLastLocation;
public LocationListener(String provider) {
mLastLocation = new Location(provider);
}
}
public void requestLocationUpdates() {
try {
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
LOCATION_INTERVAL, LOCATION_DISTANCE, mLocationListener);
} catch (java.lang.SecurityException ex) {
Log.i(TAG, "fail to request location update, ignore", ex);
} catch (IllegalArgumentException ex) {
Log.d(TAG, "gps provider does not exist " + ex.getMessage());
}
}
private void initializeLocationManager() {
if (mLocationManager == null) {
mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
}
}
private void requestLocationInformation() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
Location location = mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null && swbRunning) {
String locInfo = "latitude:" + location.getLatitude() + " longitude:" + location.getLongitude() + " accuracy: " + location.getAccuracy() + "\n";
Log.d(TAG, "Location --> " + locInfo);
}
}
}
}
public class MainActivity extends ReactActivity {
//permissions to be requested at runtime - needed for android 6.0+
static String[] runtimePermissions = { Manifest.permission.INTERNET, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.READ_PHONE_STATE, Manifest.permission.WAKE_LOCK };
static int permissionRequestCode = 1;
private LocationService locaService;
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (!havePermissions()) {
requestPermissions(runtimePermissions, permissionRequestCode);
} else {
Intent intent = new Intent(this, LocationService.class);
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
startForegroundService(intent);
else
startService(intent);
}
}
private ServiceConnection serviceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
locaService = ((LocationService.LocationServiceBinder) service).getService();
}
public void onServiceDisconnected(ComponentName className) {
locaService = null;
}
};
为了测试应用程序,我使用了三星 Galaxy A42 (android 11) 设备,这也是我们的用户使用的设备。在发布版本中,一切正常,直到应用程序被最小化或屏幕被锁定。我调查了这个问题,并根据我可以在网上找到的关于这个问题的信息,我尝试了一些不同的解决方案。我添加了一个部分唤醒锁以保持设备平稳运行,并且按照以下帖子的建议,我还在 android 清单中添加了 stopWithTask=false。我还在没有此问题的旧设备(android 8)上运行了该应用程序。
杀死应用程序后保持后台服务运行 当用户将其置于后台时,我的 Android 11 应用程序将停止运行,除非手机已连接到电源 Android 在三星设备上保持屏幕打开
如上一篇文章所述,三星以执行电池优化而闻名,这可能会影响运行前台服务的应用程序。所以我使用了https://dontkillmyapp.com/上的建议,但这并不能解决问题。由于我尝试了所有能找到的解决方案,我开始认为这可能是我问题的主要根源。我想知道是否有人遇到过类似的问题,以及是否有解决此问题的方法。
解决方案
推荐阅读
- c# - 无法将指向 Identity 的链接重定向到自己的操作方法
- android - 如何在 Android 中制作这样的列表?
- matlab - Simulink Scope 是否可以选择在单列中显示布局?
- javascript - 使用 1 个模式合并来自 JSON 的对象
- ssh - 期望启用登录
- python - 合并 30 天内出现的 pandas 数据框中的行
- javascript - Javascript:如何获得下一个发生在一周中的 X 天
- oracle - 使用 64 位来宾操作系统的 Amazon AWS 上的 Virtualbox
- c - 将变量转换为函数
- unity3d - ScriptableObject 列表到 Json