0

As my title says, I have a FOREGROUNDSERVICE which is stopped after around 3 minutes (I guess doze mode), and stops acquiring Accelerometry. I do use a PARTIAL_WAKE_LOCK and return START_STICKY... but I don't undestand the reason why this happens. I do really need Acc to not stop recording and log the values on a file... The way to stop the acquisition would be a battery check, a free space check or a button click on the app.

I tested the implementation below application on an Android 6.0.1 (API 23), and worked like charm. When testing the same application on a Xiaomi Pocophone Android 10 device (API 29), after 3 minutes the doze mode (I guess) kicks in and stops the acc acqquisition...

Any ideas of why? In theory a foreground service should keep the CPU running, and with the partial wake_lock I should ensure it keeps running and acquiring ACC...

Here there is my service:

public class AccelerometryService extends Service implements SensorEventListener {
    // WakeLock variable to keep CPU running obtaining Acc
    private PowerManager.WakeLock wakeLock;

    //Notification Variable to show that Acc has started
    private NotificationChannel notChannel = null;
    private NotificationManager nMservice = null;
    Intent notifIntent = null;
    PendingIntent pendingIntent = null;
    private int NOTIFICATION = 112020592;
    private String channelID = "AccRecordService";

    //Accelerometry variables
    private SensorManager sensorManager = null;
    private Sensor sensor = null;

    //File Writting
    private long SystemTime = 0;
    private File rawDataFolder = null;
    private String FileName = null;
    private File rawDataTxt = null;
    private FileOutputStream fileOutputStream = null;

    //Acc data sharing
    private Observable oString = null;
    public static final String ACCNOTIFICATION = "com.example.android.sleeppos";




    @SuppressLint("WakelockTimeout")
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        super.onStartCommand(intent, flags, startId);

        Toast.makeText(this, "Logging service started new", Toast.LENGTH_SHORT).show();

        //Acquire wake lock
        PowerManager pm = (PowerManager) this.getSystemService(Context.POWER_SERVICE);
        this.wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WLTAG:MyWakelockTag");
        wakeLock.acquire();


        //Display notification
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            createNotificationChannel(this.channelID, "AccBackgroundService");
        }
        this.notifIntent = new Intent(this, MainActivity.class);
        this.pendingIntent = PendingIntent.getActivity(this, 0, this.notifIntent, 0);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            Notification.Builder builder =  new Notification.Builder(this, this.channelID)
                    .setSmallIcon(R.drawable.ic_launcher_background)
                    .setContentTitle("SleepPos app")
                    .setContentText("Acc has started being recorded")
                    .setVisibility(Notification.VISIBILITY_PUBLIC)
                    .setContentIntent(this.pendingIntent)
                    .setOngoing(true);
            startForeground(this.NOTIFICATION, builder.build());
        } else {
            NotificationCompat.Builder builder = new NotificationCompat.Builder(this, this.channelID)
                    .setSmallIcon(R.drawable.ic_launcher_background)
                    .setContentTitle("SleepPos app")
                    .setContentText("Acc has started being recorded")
                    .setPriority(NotificationCompat.PRIORITY_HIGH)
                    .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
                    .setContentIntent(this.pendingIntent)
                    .setOngoing(true);
            startForeground(this.NOTIFICATION, builder.build());
        }


        // register Acc listener
        sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_FASTEST);


        //Parse variables given from the intent
        this.rawDataFolder = (File) intent.getExtras().get("DataFolder");
        this.FileName = intent.getStringExtra("FileName");
        this.SystemTime = intent.getLongExtra("SystemTime", 0);
        this.rawDataTxt = new File(this.rawDataFolder, this.FileName);
        try {
            this.rawDataTxt.createNewFile();
            this.fileOutputStream = new FileOutputStream(this.rawDataTxt);
            this.fileOutputStream.write(("Time_elapsed_(nanoseconds);X-Axis;Y-Axis;Z-Axis" + System.lineSeparator()).getBytes());
        } catch (IOException ioe) {
            Log.v("ErrorFile", "Error while creating empty file:");
        }

        return START_STICKY;
    }

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

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

        //unregister sensor listener
        sensorManager.unregisterListener(this);

        //cancel notification
        stopForeground(true);

        //Close the file being used to register Acc
        try {
            this.fileOutputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        //release wakeLock
        wakeLock.release();

        Log.v("DEBUG_SLEEPPOS","onDestroyDone");
        //Stop Service
        stopSelf();
    }

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

    @Override
    public void onSensorChanged(SensorEvent event) {
        // grab the values and timestamp -- off the main thread
        long dataTime = event.timestamp;

        // Call the file handle to write
        try {
            String delimiter = ";";
            fileOutputStream.write(((dataTime - AccelerometryService.this.SystemTime) + delimiter +
                    event.values[0] + delimiter +
                    event.values[1] + delimiter +
                    event.values[2] +
                    System.lineSeparator()).getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }


    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
    }



    @RequiresApi(Build.VERSION_CODES.O)
    private void createNotificationChannel(String channelId, String channelName) {
        this.notChannel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH);
        this.notChannel.enableLights(true);
        this.notChannel.setLightColor(Color.RED);
        this.notChannel.enableVibration(true);
        long[] Vibrations = {100, 200, 300, 400, 500, 400, 300, 200, 400};
        this.notChannel.setVibrationPattern(Vibrations);
        this.notChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
        this.notChannel.setImportance(NotificationManager.IMPORTANCE_HIGH);
        this.nMservice = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        this.nMservice.createNotificationChannel(this.notChannel);
    }


}

UPDATE: I tested the command adb shell dumpsys deviceidle force-idle on the terminal to force idle state and Acc was still acquiring... so no idea why it stops after 3 minutes on my XIAOMI Pocophone F1 Android 10 (API 29). I don't know if the doze mode can be forced with any other command...

Ignasi
  • 601
  • 2
  • 10
  • 23
  • Be aware of: https://dontkillmyapp.com/xiaomi – Morrison Chang May 02 '20 at 19:56
  • Then, is it something with Xiaomi rather than a problem with my implementation? – Ignasi May 02 '20 at 20:02
  • I would check on emulator and different manufacturer devices to make sure there isn't a error in your foreground service, per https://developer.android.com/training/monitoring-device-state/doze-standby#understand_app_standby but there may not be anything a developer can do: https://stackoverflow.com/a/56868660/295004 – Morrison Chang May 02 '20 at 21:28
  • Hi Ignasi, please check on Xiaomi device battery setting like in OnePlus and realme. I am also facing this issue with both manufacturers, my app is getting killed after 15-20 minutes . https://stackoverflow.com/questions/62305294/foreground-service-is-killed-in-android-10 – mdroid Jun 10 '20 at 14:19

0 Answers0