Android Service stops broadcasting progress after a while

Mehdi Satei :

I have an Activity where the user can download a video. Upon user's click, the Download Service starts to download the content. There is a progress bar in the Activity UI which I would like to update according to download progress in the service which broadcasts the progress periodically.

Everything works fine but after a certain time the service stops sending any broadcast progress, hence, the UI does not update anymore.

Additionally, how I can resume receiving the progress broadcast when the user goes to another Activity and comes back to this Activity? I mean, even if the above issue is solved, when the user presses back button and go to other activity and comes back to this activity, the progress gets lots. How can I check for any existing broadcast and receive it whenever the user comes to this activity.

In the ACTIVITY:

private BroadcastReceiver receiver = new BroadcastReceiver() {
    @Override public void onReceive(Context context, Intent intent) {
        Bundle bundle = intent.getExtras();
        if (bundle != null) {
            Log.d("DownloadService", "Progress Received In Activity");
            Double progress = bundle.getDouble("PROGRESS");
            updateDownloadProgressBar(progress);
        }
    }
};

private void startDownloadService() {
    final String videoId = mItem.getAttributes().get(KEY_ASSET_ID);
    Intent intent = new Intent(this, DownloadService.class);
    intent.putExtra("VIDEOID", videoId);
    startService(intent);
}

in the onResume():

registerReceiver(receiver, new IntentFilter(DownloadService.NOTIFICATION_SERVICE));

in the onPause():

unregisterReceiver(receiver);

In the SERVICE:

private void publishProgress(double progress) {
    Log.d(TAG, "Broadcasting progress from Service");
    Intent intent = new Intent(NOTIFICATION_SERVICE);
    intent.putExtra("PROGRESS", progress);
    sendBroadcast(intent);
}

enter image description here

The download and progress work fine to 38% then stop.

Farouq Afghani :

It seems that the service is being stopped/killed from the OS, to avoid that use foreground service so you can make sure it will not be killed from the OS.

See the sample code below:

Service

public class PendingService extends Service {

    private final static String TAG = "PendingService";
    public final static int NOTIFICATION_ID = 94;


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        startInForeground();

        // Do your work here ...

        return START_STICKY;
    }

    private void startInForeground() {
        String NOTIFICATION_CHANNEL_ID = "default";
        String NOTIFICATION_CHANNEL_NAME = "My Pending Service";
        String NOTIFICATION_CHANNEL_DESC = "This notification holding a pending task";

        Intent notificationIntent = new Intent(this, SplashActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
                .setSmallIcon(R.drawable.notification)
                .setOngoing(true)
                .setAutoCancel(true)
                .setContentIntent(pendingIntent);

        if (Build.VERSION.SDK_INT >= 26) {
            NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_NAME, NotificationManager.IMPORTANCE_LOW);
            channel.setDescription(NOTIFICATION_CHANNEL_DESC);
            channel.setSound(null, null);
            NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            if (notificationManager != null) {
                notificationManager.createNotificationChannel(channel);
            }
        }

        Notification notification = builder.build();
        startForeground(NOTIFICATION_ID, notification);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        removeNotification(NOTIFICATION_ID);
        // ....
    }

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

    private void removeNotification(int notificationId) {
        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        if (notificationManager != null) {
            notificationManager.cancel(notificationId);
        }
    }
}

Utils you may need

class ServiceUtils {

    /**
     * @param service: Service to run
     */
    fun startService(context: Context, service: Class<out Service>) {
        val serviceIntent = Intent(context, service)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            context.startForegroundService(serviceIntent)
        } else {
            context.startService(serviceIntent)
        }
    }

    /**
     * @return True: if the service is running
     */
    fun isServiceRunning(context: Context, serviceClass: Class<*>): Boolean {
        val manager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
        for (service in manager.getRunningServices(Integer.MAX_VALUE)) {
            if (serviceClass.name == service.service.className) {
                return true
            }
        }
        return false
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=154542&siteId=1