I’m making an application that records a GPS track. On some devices there is a problem (Google Pixel 4a, Android 14) that the application crashes after a long time of operation (~4 hours)
At first I thought that the problem was in energy saving, I added this to AndroidManifest REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
But the problem did not go away. At the moment it is known that it appears mainly on Android 14; no such problems were noticed on versions < 14
At the moment I have already tried almost everything and I don’t know what can help me.
Here’s the code I’m using
MainActivity
public void startGpsService() {
Intent serviceIntent = new Intent(this, ForegroundGpsService.class);
ContextCompat.startForegroundService(this, serviceIntent);
}
Service
public class ForegroundGpsService extends Service implements locListenerInterface {
private LocationManager locationManager;
private myLocListener myLocLis;
private static final int NOTIFY_ID = 101;
private static String CHANNEL_ID = "my_GPS_channel";
private String pointsStrList = "";
private Location NowLoc = null;
private int duration = 0;
private Handler handler = new Handler();
private Handler handler2 = new Handler();
ExecutorService executor = Executors.newSingleThreadExecutor();
private long startTime = 0;
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onDestroy(){
locationManager.removeUpdates(myLocLis);
handler.removeMessages(0);
handler2.removeMessages(0);
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
SharedPreferences sharedPref = getSharedPreferences("MyDudesTrackerApp", MODE_PRIVATE);
pointsStrList = sharedPref.getString("pointsList", "");
startTime = sharedPref.getLong("startTime", 0);
if(startTime == 0){
startTime = System.currentTimeMillis()/1000;
SharedPreferences.Editor editor = sharedPref.edit();
editor.putLong("startTime", startTime).commit();
}
init();
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,0, notificationIntent, PendingIntent.FLAG_IMMUTABLE);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Начало записи")
.setContentText("Ждём обновления координат")
.setSmallIcon(R.drawable.notify_ico)
.setContentIntent(pendingIntent)
.setSilent(true)
.setContentIntent(pendingIntent)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.build();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
startForeground(NOTIFY_ID, notification);
} else {
startForeground(NOTIFY_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION);
}
return START_NOT_STICKY;
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onLocationChanged(Location Loc) {
NowLoc = Loc;
double[] point = new double[2];
point[0] = Loc.getLatitude();
point[1] = Loc.getLongitude();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
String formattedDate = sdf.format(new Date());
//save point
pointsStrList += String.format("%.7f", point[0]).replaceAll(",", ".") + "&" + String.format("%.7f", point[1]).replaceAll(",", ".") + "&" + formattedDate+"|";
SharedPreferences sharedPref = getSharedPreferences("TrackerApp", MODE_PRIVATE);;
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString("pointsList", pointsStrList).commit();
}
private void init(){
createChannel();
locationManager = (LocationManager)this.getSystemService(Context.LOCATION_SERVICE);
myLocLis = new myLocListener();
myLocLis.setMyLocLisInterface(this);
checkPremissions();
//timer
final Runnable r = new Runnable() {
public void run() {
sendNotify();
handler.postDelayed(this, 1000);
}
};
handler.postDelayed(r, 1000);
//send position to server
final Runnable r2 = new Runnable() {
public void run() {
SharedPreferences sharedPref = getSharedPreferences("TrackerApp", MODE_PRIVATE);
boolean sendPosState = sharedPref.getBoolean("SendPos", false);
if(NowLoc != null && sendPosState){
String requestUrl = "***";
StringRequest stringRequest = new StringRequest(Request.Method.POST, requestUrl, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
//
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace(); //
}
}){
@Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> postMap = new HashMap<>();
SharedPreferences sharedPref = getSharedPreferences("***", MODE_PRIVATE);
String login = sharedPref.getString("", "");
String password = sharedPref.getString("", "");
postMap.put("l", login);
postMap.put("p", password);
postMap.put("c", String.format("%.5f", NowLoc.getLatitude()) + "|" + String.format("%.5f", NowLoc.getLongitude()));
return postMap;
}
};
Volley.newRequestQueue(getApplicationContext()).add(stringRequest);
}
handler.postDelayed(this, 10000);
}
};
handler.postDelayed(r2, 10000);
}
private void sendNotify(){
duration = (int)(System.currentTimeMillis()/1000 - startTime);
String title = "Record: "+secondToMinHour(duration);
String content = "Find gps...";
if(NowLoc != null){
content = "Your position:nlat: " + String.format("%.5f", NowLoc.getLatitude()) + " lon: " + String.format("%.5f", NowLoc.getLongitude());
}
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,0, notificationIntent, PendingIntent.FLAG_IMMUTABLE);
NotificationCompat.Builder builder =
new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.notify_ico)
.setContentTitle(title)
.setContentText(content)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setContentIntent(pendingIntent)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) {
//
}
notificationManager.notify(NOTIFY_ID, builder.build());
}
private void createChannel(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = CHANNEL_ID;
String description = "coords";
int importance = NotificationManager.IMPORTANCE_LOW;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
channel.setDescription(description);
channel.setSound(null, null);
NotificationManager notificationManager = this.getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
private void checkPremissions(){
//code
}
}
Permissions
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION"/>
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
Service
<service
android:name="ru.my_dudes.mydudesapp.ForegroundGpsService"
android:enabled="true"
android:exported="true"
android:foregroundServiceType="location"></service>
OT_VINTA is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.