• After 15+ years, we've made a big change: Android Forums is now Early Bird Club. Learn more here.

Apps Service not working when phone is idle / dozing / locked

Louen

Lurker
Feb 10, 2020
4
1
Good evening,

I've been trying to achieve something for several days now and I literally don't know what else to try, I've basically tried everything I found online and it still doesn't work but I have the feeling that once I find the solution it must be something quite simple.

I'm working on a bigger project, but here I'm just trying to get a very simple example to work which I can later adapt to my project.

What I want to do

I want to have a counter add +1 every second for 1200 seconds (20 minutes) and write to a file every time it counts. I should end up with a file with 1200 lines with a timestamp per sample.

How I'm trying to do it

I've tried a million things, but here, I've just gone back to a very basic example so I can showcase it and ask for help:

- I have a MAIN acticity with a single START button.
- When clicking the button I start a new process from the activity. This is a FOREGROUND process.
- I start counting in a loop. When I reach 1200, the counting stops.

My problem

While the phone screen is ON everything works just fine, but as soon as I lock the screen and put my phone in my pocket, depending on the phone I'm testing on, it starts to fail.

What I would like

If someone could tell me what to modify / add / change or even do it for me and write back here (it's a really simple project) I would be extremely grateful, I'm wasting a ton of time and I just can't seem to hit the right key.

Code

Since it's a very simple project I will just copy the 4 parts it consists of right here:

XML activity_main.xml

Code:
    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
  
        <Button
            android:id="@+id/start_button"
            android:layout_width="150dp"
            android:layout_height="50dp"
            android:layout_marginStart="52dp"
            android:layout_marginBottom="116dp"
            android:onClick="startProcess"
            android:text="@string/button_label_start"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent" />
  
        <TextView
            android:id="@+id/counter_textView"
            android:layout_width="383dp"
            android:layout_height="412dp"
            android:gravity="center_horizontal|center_vertical"
            android:text="@string/counter_label_value"
            android:textSize="160sp"
            android:textStyle="bold"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.428"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.169" />
  
    </androidx.constraintlayout.widget.ConstraintLayout>

MANIFEST AndroidManifest.xml

Code:
    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.helloworld">
  
        <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
  
        <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
  
            <service
                android:name=".ForegroundService"
                android:enabled="true"
                android:exported="true"
                android:process=":externalProcess">
            </service>
  
            <activity android:name=".MainActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
  
    </manifest>

MAIN MainActivity.java

Java:
package com.example.helloworld;
  
    import androidx.annotation.Nullable;
    import androidx.appcompat.app.AppCompatActivity;
    import androidx.core.content.ContextCompat;
  
    import android.app.PendingIntent;
    import android.content.Intent;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.TextView;
  
    public class MainActivity extends AppCompatActivity {
  
        public static final String CHANNEL_ID = "ForegroundServiceChannel";
        private TextView mShowCount;
  
        @Override
        protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
  
            int mCount = data.getIntExtra(ForegroundService.FOREGROUND_MESSAGE, -1);
            if(mShowCount != null)
                mShowCount.setText(Integer.toString(mCount));
        }
  
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mShowCount = findViewById(R.id.counter_textView);
        }
  
        @Override
        protected void onResume() {
            super.onResume();
        }
  
        @Override
        protected void onStart() {
            super.onStart();
        }
  
        @Override
        protected void onPause() {
            super.onPause();
        }
  
        @Override
        protected void onStop() {
            super.onStop();
        }
  
        @Override
        protected void onDestroy() {
            super.onDestroy();
        }
  
        @Override
        protected void onRestart() {
            super.onRestart();
        }
  
        public void startProcess(View view) {
            PendingIntent pendingResult = createPendingResult(100, new Intent(), 0);
            Intent serviceIntent = new Intent(this, ForegroundService.class);
            serviceIntent.putExtra("pendingIntent", pendingResult);
            ContextCompat.startForegroundService(this, serviceIntent);
        }
  
        public void stopProcess(View view) {
            Intent serviceIntent = new Intent(this, ForegroundService.class);
            stopService(serviceIntent);
        }
    }

FOREGROUND SERVICE ForegroundService.java

Java:
    package com.example.helloworld;
  
    import android.app.Notification;
    import android.app.NotificationChannel;
    import android.app.NotificationManager;
    import android.app.PendingIntent;
    import android.app.Service;
    import android.content.Intent;
    import android.os.Build;
    import android.os.IBinder;
    import android.os.SystemClock;
    import android.util.Log;
    import androidx.core.app.NotificationCompat;
  
    import java.io.File;
    import java.io.FileWriter;
    import java.util.Date;
  
    public class ForegroundService extends Service {
  
        public static final String CHANNEL_ID = "ForegroundServiceChannel";
        public static final String FOREGROUND_MESSAGE = "com.example.helloworld.FOREGROUND_MESSAGE";
  
        private PendingIntent data;
        private int mCount;
        private File basePath;
  
        public ForegroundService() {
        }
  
        @Override
        protected void finalize() throws Throwable {
            super.finalize();
        }
  
        @Override
        public void onCreate() {
            super.onCreate();
        }
  
        @Override
        public boolean stopService(Intent name) {
            return super.stopService(name);
        }
  
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            String input = intent.getStringExtra("inputExtra");
  
            createNotificationChannel();
            Intent notificationIntent = new Intent(this, MainActivity.class);
            PendingIntent pendingIntent = PendingIntent.getActivity(this,
                    0, notificationIntent, 0);
            Notification notification = new NotificationCompat.Builder(this, MainActivity.CHANNEL_ID)
                    .setContentTitle("Foreground Service")
                    .setContentText(input)
                    .setContentIntent(pendingIntent)
                    .build();
  
            startForeground(1, notification);
            data = intent.getParcelableExtra("pendingIntent");
            this.basePath = this.getExternalFilesDir("recs");
  
            mCount = 0;
            new Thread(new Runnable() {
                public void run() {
                    try {
                        while(mCount < 1200) {
                            Intent resultIntent = new Intent();
                            resultIntent.putExtra(FOREGROUND_MESSAGE, ++mCount);
                            writeFile((new Date().getTime() / 1000) + " Increasing counter: " + mCount + "\n");
                            data.send(ForegroundService.this, 200, resultIntent);
                            SystemClock.sleep(1000);
                        }
                    }catch (Exception ignored){}
                }
            }).start();
  
            //stopSelf();
            return START_NOT_STICKY;
        }
  
        private void createNotificationChannel() {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                NotificationChannel serviceChannel = new NotificationChannel(
                        CHANNEL_ID,
                        "Foreground Service Channel",
                        NotificationManager.IMPORTANCE_DEFAULT
                );
                NotificationManager manager = getSystemService(NotificationManager.class);
                manager.createNotificationChannel(serviceChannel);
            }
        }
  
        @Override
        public void onDestroy(){
            super.onDestroy();
        }
  
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
  
        private void writeFile(String data)
        {
            File file = new File (basePath,"test");
            if (!file.exists()) {
                boolean mkdirs = file.mkdirs();
                if (!mkdirs) {
                    Log.e("RECORDING", "Error creating SAVE BASE PATH");
                }
            }
  
            try{
                File counter_file = new File(file, "counter.txt");
                FileWriter writer = new FileWriter(counter_file, true);
                writer.append(data);
                writer.flush();
                writer.close();
            } catch (Exception e){
                e.printStackTrace();
            }
        }
    }


I know I might be asking a bit too much but I'm quite desperate at this point. I'd be really greatful if someone could come up with a working solution.

Thank you very much.
 
You say that you have 'tried a million things', but don't tell us what any of those are.

Is this an app you are working on?
If so, have you ensured that Battery Optimization is off for it?

If that is not it, some devices will turn apps off when the phone sleeps if they are not 'pinned'.
So pinning the app might also help.
 
Upvote 0
You say that you have 'tried a million things', but don't tell us what any of those are.

Is this an app you are working on?
If so, have you ensured that Battery Optimization is off for it?

If that is not it, some devices will turn apps off when the phone sleeps if they are not 'pinned'.
So pinning the app might also help.

Hi puppykickr, thank you for your reply.

This example is not the full app, it's just a small test to try to get something to work that I could later adapt to the full app.

I didn't enumerate all my attempts because then the post would become too long and people would / could start replying to different parts of it. I tried to simplify the problem as much as I could and ask for a very specific solution for simplicity's sake.

I did try turning Battery Optimizations off and I believe I also tried pinning the app (by pinning you mean keeping a notification open at all times that can't be closed until you kill the process, right?). Still no luck :(.
 
  • Like
Reactions: puppykickr
Upvote 0
Hi puppykickr, thank you for your reply.

This example is not the full app, it's just a small test to try to get something to work that I could later adapt to the full app.

I didn't enumerate all my attempts because then the post would become too long and people would / could start replying to different parts of it. I tried to simplify the problem as much as I could and ask for a very specific solution for simplicity's sake.

I did try turning Battery Optimizations off and I believe I also tried pinning the app (by pinning you mean keeping a notification open at all times that can't be closed until you kill the process, right?). Still no luck :(.

Pinning the app is different than you explain, and can be different in function depending upon the device. For some, pinning an app will simply keep that app active in the device memory at all times.
For other devices, pinning restricts the device to only that screen or function.

Settings
Security
Pinning (Screen Pinning, App Pinning, etc.)
 
Upvote 0
Pinning the app is different than you explain, and can be different in function depending upon the device. For some, pinning an app will simply keep that app active in the device memory at all times.
For other devices, pinning restricts the device to only that screen or function.

Settings
Security
Pinning (Screen Pinning, App Pinning, etc.)

Oh ok, just read about pinning. But from what I'm seeing, I'm pretty sure that's not the way to go (based on examples of other apps on the store). I'm quite confident that the solution is somewhere between a foregroundProcess and a partial wakelock (I've spent hours going through the android developer docs) however... I can't get it to work no matter what I try :(.
 
Upvote 0
Oh ok, just read about pinning. But from what I'm seeing, I'm pretty sure that's not the way to go (based on examples of other apps on the store). I'm quite confident that the solution is somewhere between a foregroundProcess and a partial wakelock (I've spent hours going through the android developer docs) however... I can't get it to work no matter what I try :(.

Have you tried using the screen saver to keep the screen from sleeping?
I know ths will eat battery life, but you can use a screen dimming app to negate quite a lot of that.

Ths is how I keep my sharing app active when transferring large files.
 
Upvote 0

BEST TECH IN 2023

We've been tracking upcoming products and ranking the best tech since 2007. Thanks for trusting our opinion: we get rewarded through affiliate links that earn us a commission and we invite you to learn more about us.

Smartphones