1. Are you ready for the Galaxy S20? Here is everything we know so far!

Service not working when phone is idle / dozing / locked

Discussion in 'Android Development' started by Louen, Feb 13, 2020.

  1. Louen

    Louen Lurker
    Thread Starter

    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 (Text):
    1.     <?xml version="1.0" encoding="utf-8"?>
    2.     <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    3.         xmlns:app="http://schemas.android.com/apk/res-auto"
    4.         xmlns:tools="http://schemas.android.com/tools"
    5.         android:layout_width="match_parent"
    6.         android:layout_height="match_parent"
    7.         tools:context=".MainActivity">
    8.  
    9.         <Button
    10.             android:id="@+id/start_button"
    11.             android:layout_width="150dp"
    12.             android:layout_height="50dp"
    13.             android:layout_marginStart="52dp"
    14.             android:layout_marginBottom="116dp"
    15.             android:onClick="startProcess"
    16.             android:text="@string/button_label_start"
    17.             app:layout_constraintBottom_toBottomOf="parent"
    18.             app:layout_constraintStart_toStartOf="parent" />
    19.  
    20.         <TextView
    21.             android:id="@+id/counter_textView"
    22.             android:layout_width="383dp"
    23.             android:layout_height="412dp"
    24.             android:gravity="center_horizontal|center_vertical"
    25.             android:text="@string/counter_label_value"
    26.             android:textSize="160sp"
    27.             android:textStyle="bold"
    28.             app:layout_constraintBottom_toBottomOf="parent"
    29.             app:layout_constraintEnd_toEndOf="parent"
    30.             app:layout_constraintHorizontal_bias="0.428"
    31.             app:layout_constraintStart_toStartOf="parent"
    32.             app:layout_constraintTop_toTopOf="parent"
    33.             app:layout_constraintVertical_bias="0.169" />
    34.  
    35.     </androidx.constraintlayout.widget.ConstraintLayout>
    MANIFEST AndroidManifest.xml

    Code (Text):
    1.     <?xml version="1.0" encoding="utf-8"?>
    2.     <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    3.         package="com.example.helloworld">
    4.  
    5.         <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    6.  
    7.         <application
    8.             android:allowBackup="true"
    9.             android:icon="@mipmap/ic_launcher"
    10.             android:label="@string/app_name"
    11.             android:roundIcon="@mipmap/ic_launcher_round"
    12.             android:supportsRtl="true"
    13.             android:theme="@style/AppTheme">
    14.  
    15.             <service
    16.                 android:name=".ForegroundService"
    17.                 android:enabled="true"
    18.                 android:exported="true"
    19.                 android:process=":externalProcess">
    20.             </service>
    21.  
    22.             <activity android:name=".MainActivity">
    23.                 <intent-filter>
    24.                     <action android:name="android.intent.action.MAIN" />
    25.                     <category android:name="android.intent.category.LAUNCHER" />
    26.                 </intent-filter>
    27.             </activity>
    28.         </application>
    29.  
    30.     </manifest>
    MAIN MainActivity.java

    Code (Java):
    1. package com.example.helloworld;
    2.  
    3.     import androidx.annotation.Nullable;
    4.     import androidx.appcompat.app.AppCompatActivity;
    5.     import androidx.core.content.ContextCompat;
    6.  
    7.     import android.app.PendingIntent;
    8.     import android.content.Intent;
    9.     import android.os.Bundle;
    10.     import android.view.View;
    11.     import android.widget.TextView;
    12.  
    13.     public class MainActivity extends AppCompatActivity {
    14.  
    15.         public static final String CHANNEL_ID = "ForegroundServiceChannel";
    16.         private TextView mShowCount;
    17.  
    18.         @Override
    19.         protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    20.             super.onActivityResult(requestCode, resultCode, data);
    21.  
    22.             int mCount = data.getIntExtra(ForegroundService.FOREGROUND_MESSAGE, -1);
    23.             if(mShowCount != null)
    24.                 mShowCount.setText(Integer.toString(mCount));
    25.         }
    26.  
    27.         @Override
    28.         protected void onCreate(Bundle savedInstanceState) {
    29.             super.onCreate(savedInstanceState);
    30.             setContentView(R.layout.activity_main);
    31.             mShowCount = findViewById(R.id.counter_textView);
    32.         }
    33.  
    34.         @Override
    35.         protected void onResume() {
    36.             super.onResume();
    37.         }
    38.  
    39.         @Override
    40.         protected void onStart() {
    41.             super.onStart();
    42.         }
    43.  
    44.         @Override
    45.         protected void onPause() {
    46.             super.onPause();
    47.         }
    48.  
    49.         @Override
    50.         protected void onStop() {
    51.             super.onStop();
    52.         }
    53.  
    54.         @Override
    55.         protected void onDestroy() {
    56.             super.onDestroy();
    57.         }
    58.  
    59.         @Override
    60.         protected void onRestart() {
    61.             super.onRestart();
    62.         }
    63.  
    64.         public void startProcess(View view) {
    65.             PendingIntent pendingResult = createPendingResult(100, new Intent(), 0);
    66.             Intent serviceIntent = new Intent(this, ForegroundService.class);
    67.             serviceIntent.putExtra("pendingIntent", pendingResult);
    68.             ContextCompat.startForegroundService(this, serviceIntent);
    69.         }
    70.  
    71.         public void stopProcess(View view) {
    72.             Intent serviceIntent = new Intent(this, ForegroundService.class);
    73.             stopService(serviceIntent);
    74.         }
    75.     }
    FOREGROUND SERVICE ForegroundService.java

    Code (Java):
    1.     package com.example.helloworld;
    2.  
    3.     import android.app.Notification;
    4.     import android.app.NotificationChannel;
    5.     import android.app.NotificationManager;
    6.     import android.app.PendingIntent;
    7.     import android.app.Service;
    8.     import android.content.Intent;
    9.     import android.os.Build;
    10.     import android.os.IBinder;
    11.     import android.os.SystemClock;
    12.     import android.util.Log;
    13.     import androidx.core.app.NotificationCompat;
    14.  
    15.     import java.io.File;
    16.     import java.io.FileWriter;
    17.     import java.util.Date;
    18.  
    19.     public class ForegroundService extends Service {
    20.  
    21.         public static final String CHANNEL_ID = "ForegroundServiceChannel";
    22.         public static final String FOREGROUND_MESSAGE = "com.example.helloworld.FOREGROUND_MESSAGE";
    23.  
    24.         private PendingIntent data;
    25.         private int mCount;
    26.         private File basePath;
    27.  
    28.         public ForegroundService() {
    29.         }
    30.  
    31.         @Override
    32.         protected void finalize() throws Throwable {
    33.             super.finalize();
    34.         }
    35.  
    36.         @Override
    37.         public void onCreate() {
    38.             super.onCreate();
    39.         }
    40.  
    41.         @Override
    42.         public boolean stopService(Intent name) {
    43.             return super.stopService(name);
    44.         }
    45.  
    46.         @Override
    47.         public int onStartCommand(Intent intent, int flags, int startId) {
    48.             String input = intent.getStringExtra("inputExtra");
    49.  
    50.             createNotificationChannel();
    51.             Intent notificationIntent = new Intent(this, MainActivity.class);
    52.             PendingIntent pendingIntent = PendingIntent.getActivity(this,
    53.                     0, notificationIntent, 0);
    54.             Notification notification = new NotificationCompat.Builder(this, MainActivity.CHANNEL_ID)
    55.                     .setContentTitle("Foreground Service")
    56.                     .setContentText(input)
    57.                     .setContentIntent(pendingIntent)
    58.                     .build();
    59.  
    60.             startForeground(1, notification);
    61.             data = intent.getParcelableExtra("pendingIntent");
    62.             this.basePath = this.getExternalFilesDir("recs");
    63.  
    64.             mCount = 0;
    65.             new Thread(new Runnable() {
    66.                 public void run() {
    67.                     try {
    68.                         while(mCount < 1200) {
    69.                             Intent resultIntent = new Intent();
    70.                             resultIntent.putExtra(FOREGROUND_MESSAGE, ++mCount);
    71.                             writeFile((new Date().getTime() / 1000) + " Increasing counter: " + mCount + "\n");
    72.                             data.send(ForegroundService.this, 200, resultIntent);
    73.                             SystemClock.sleep(1000);
    74.                         }
    75.                     }catch (Exception ignored){}
    76.                 }
    77.             }).start();
    78.  
    79.             //stopSelf();
    80.             return START_NOT_STICKY;
    81.         }
    82.  
    83.         private void createNotificationChannel() {
    84.             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    85.                 NotificationChannel serviceChannel = new NotificationChannel(
    86.                         CHANNEL_ID,
    87.                         "Foreground Service Channel",
    88.                         NotificationManager.IMPORTANCE_DEFAULT
    89.                 );
    90.                 NotificationManager manager = getSystemService(NotificationManager.class);
    91.                 manager.createNotificationChannel(serviceChannel);
    92.             }
    93.         }
    94.  
    95.         @Override
    96.         public void onDestroy(){
    97.             super.onDestroy();
    98.         }
    99.  
    100.         @Override
    101.         public IBinder onBind(Intent intent) {
    102.             return null;
    103.         }
    104.  
    105.         private void writeFile(String data)
    106.         {
    107.             File file = new File (basePath,"test");
    108.             if (!file.exists()) {
    109.                 boolean mkdirs = file.mkdirs();
    110.                 if (!mkdirs) {
    111.                     Log.e("RECORDING", "Error creating SAVE BASE PATH");
    112.                 }
    113.             }
    114.  
    115.             try{
    116.                 File counter_file = new File(file, "counter.txt");
    117.                 FileWriter writer = new FileWriter(counter_file, true);
    118.                 writer.append(data);
    119.                 writer.flush();
    120.                 writer.close();
    121.             } catch (Exception e){
    122.                 e.printStackTrace();
    123.             }
    124.         }
    125.     }

    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.
     


  2. puppykickr

    puppykickr Android Expert

    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.
     
  3. Louen

    Louen Lurker
    Thread Starter

    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 :(.
     
    puppykickr likes this.
  4. puppykickr

    puppykickr Android Expert

    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.)
     
  5. Louen

    Louen Lurker
    Thread Starter

    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 :(.
     
  6. puppykickr

    puppykickr Android Expert

    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.
     
Loading...

Share This Page

Loading...