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
<?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
<?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
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
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 should try using WakeLock. From the official android documentation
This will prevent from letting the CPU going to sleep until a particular task is done.
In the onCreate() method of your service
Don't forget to release your wakelock when your purpose ends, or else you might end up draining your users battery pretty fast.