Вызов службы переднего плана перед загрузкой на s3 - PullRequest
0 голосов
/ 14 октября 2019

Я создаю приложение для загрузки фотографий в фоновом режиме в корзину s3 с помощью TransferUtility. Я реализовал службу переднего плана, которая использует метод загрузки s3 TranferUtility, и служба должна быть остановлена ​​только после завершения всех загрузок.

При тестировании на реальных устройствах выгрузка фотографий работает в режиме ожидания (экономия батареи включена), при удалении из задач и отключении экрана. Тем не менее, загрузка фотографий иногда не срабатывает, так как сервис рано убивается. (Все тестирующие и производственные устройства - Samsungs)

Журналы показывают, что stopSelf() и stopForeground(true) не были вызваны, а служба переднего плана показывает, что вызывался только onDestroy. Ни один из TransferObservers не достиг состояния отказа. Состояния, в которых они находились до вызова onDestroy, были «Ожидание», «Выполняется» или «Завершено». Я могу подтвердить, что все попытки инициирования загрузки были успешными, основываясь на журналах.

Я попытался поместить TransferStility Service TransferUtility и мой UploadService в один и тот же процесс, получить блокировку wakelocks и убедиться, что уведомление переднего плана не отменяется.

Любая помощь будет полезна для определения того, что убивает мою службу переднего плана.

UploadService:


public class UploadService extends Service {

    private final static String TAG = UploadService.class.getSimpleName();
    private TransferUtility transferUtility;

    public final static String INTENT_TRANSFER_OPERATION = "transferOperation";
    public final static String INTENT_PHOTOS_UPLOAD = "UploadPhotos";
    public final static String TRANSFER_OPERATION_UPLOAD = "upload";
    public final static String TRANSFER_OPERATION_DOWNLOAD = "download";
    public final static int MAX_ERROR_COUNT = 100;
    public final String CHANNEL_ID = "upload_foreground_channel";

    public ArrayList<TransferObserver> uploadTransferObservers;
    private ArrayList<PhotoUploadModel> photosToUpload;

    public static boolean uploadServiceRunning;
    private static boolean uploadsCompleted;
    public static int uploadCounter = 0;
    public static long bytesLeftToTransfer = 0;
    private static float uploadProgress = 0;
    private static float uploadsInTotal = 0;
    private static int onErrorCalled = 0;

    private TransferObserver transferObserver;
    private NotificationManagerCompat notificationManager;
    private NotificationCompat.Builder notification;
    private S3Util util;
    private PowerManager.WakeLock wakeLock;


    @Override
    public void onCreate() {
        super.onCreate();
        Bugfender.d(TAG, "Upload Service Started : ON CREATE");

        //reset values
        uploadsCompleted = false;
        uploadCounter = 0;
        bytesLeftToTransfer = 0;
        uploadProgress = 0;
        uploadsInTotal = 0;
        onErrorCalled = 0;
        uploadTransferObservers = new ArrayList<>();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Bugfender.d(TAG, "Upload Service Started : ON START COMMAND");

        // Foreground notification
        if (Build.VERSION.SDK_INT >= 26) {
            NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
                    "Upload Foreground Service",
                    NotificationManager.IMPORTANCE_LOW);

            ((NotificationManager) Objects.requireNonNull(getSystemService(Context.NOTIFICATION_SERVICE))).createNotificationChannel(channel);

            notificationManager = NotificationManagerCompat.from(getBaseContext());

            notification = new NotificationCompat.Builder(getBaseContext(), CHANNEL_ID)
                    .setContentTitle("Uploading project images")
                    .setContentText("starting..")
                    .setSmallIcon(R.mipmap.symbiotic_image_logo);

            // Issue the initial notification with zero progress
            int PROGRESS_MAX = 100;
            int PROGRESS_CURRENT = 0;
            notification.setProgress(PROGRESS_MAX, PROGRESS_CURRENT, true);
            notificationManager.notify(1, notification.build());
            startForeground(1, notification.build());

            PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
            if (powerManager != null) {
                wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                        "MyApp::MyWakelockTag");
                wakeLock.acquire(1800000);
                Bugfender.d(TAG, "Wake lock acquired");
            }


        }

        //Initiating Uploads

        util = new S3Util();
        transferUtility = util.getTransferUtility(getBaseContext());

        final String transferOperation = intent.getStringExtra(INTENT_TRANSFER_OPERATION);
        final ArrayList<PhotoUploadModel> photosToUpload = intent.getParcelableArrayListExtra("UploadPhotos");

        switch (transferOperation) {
            case TRANSFER_OPERATION_UPLOAD:

                // Initiate Upload for every photo
                for (PhotoUploadModel photoUploadModel : photosToUpload) {

                    Bugfender.d(TAG, "Uploading " + photoUploadModel.getUploadKey());
                    File fileToUpload = new File(photoUploadModel.getFileToUploadPath());

                    try {
                        transferObserver = transferUtility.upload("symbioticlabs", photoUploadModel.getUploadKey(), fileToUpload);
                        transferObserver.setTransferListener(new UploadListener());
                        uploadTransferObservers.add(transferObserver);
                        Bugfender.d(TAG, "Upload Initiated Successful for : " + photoUploadModel.getFileToUploadPath());
                        uploadCounter++;
                        uploadServiceRunning = true;
                        uploadsInTotal++;
                    } catch (IllegalArgumentException e) {
                        Bugfender.e(TAG, e.toString());
                        Crashlytics.logException(e);
                        e.printStackTrace();
                    } catch (AmazonClientException e) {
                        // Retry upload if failed to initiate due to Timeout
                        transferObserver = transferUtility.upload("symbioticlabs", photoUploadModel.getUploadKey(), fileToUpload);
                        transferObserver.setTransferListener(new UploadListener());
                        uploadTransferObservers.add(transferObserver);
                        uploadCounter++;
                        uploadServiceRunning = true;
                        uploadsInTotal++;

                        Bugfender.e(TAG, e.toString());
                    }

                }
                Bugfender.d(TAG, "After upload initiated, upload observer has size of : " + uploadTransferObservers.size());
                break;
        }


        return START_STICKY;
    }


    @Override
    public void onDestroy() {
        Bugfender.d(TAG, "On Destroyed Called");
        transferUtility.cancelAllWithType(TransferType.UPLOAD);
        uploadServiceRunning = false;
        super.onDestroy();
    }

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

    private class UploadListener implements TransferListener {

        @Override
        public void onError(int id, Exception e) {
            onErrorCalled++;
        }

        @Override
        public void onProgressChanged(int id, long bytesCurrent, long bytesTotal) {
            Log.d(TAG, String.format("onProgressChanged: %d, total: %d, current: %d",
                    id, bytesTotal, bytesCurrent));
            Bugfender.d(TAG, String.format("onProgressChanged: %d, total: %d, current: %d",
                    id, bytesTotal, bytesCurrent));
        }

        @Override
        public void onStateChanged(int id, TransferState state) {

            Bugfender.d(TAG, "onStateChanged: for id : " + id + ", STATE : " + state);

            if (state == TransferState.COMPLETED) {
                // Update Progress Notification
                uploadProgress++;
                float result = (uploadProgress / uploadsInTotal) * 100;
                Log.d(TAG, "setProgressBarState: result " + result);
                Bugfender.d(TAG, "setProgressBarState: result " + result);
                int progress = Math.round(result);
                notification.setProgress(100, progress, false);
                notification.setContentText(String.valueOf((int) uploadProgress) + "/" + String.valueOf((int) uploadsInTotal) + " Uploaded");
                notificationManager.notify(1, notification.build());
                uploadCounter--;

                Bugfender.d(TAG, "onStateChanged: upload progress is " + uploadProgress);
                Bugfender.d(TAG, "onStateChanged: upload counter " + uploadCounter);

                // Check if uploads are completed
                isAllUploadCompleted();

            } else if (state == TransferState.FAILED && onErrorCalled <= MAX_ERROR_COUNT) {
                Bugfender.d(TAG, "onStateChanged: uploading failed " + id);

                // Remove failed transferobserver with a new one when retrying
                TransferObserver observerToRemove = null;
                for (TransferObserver observer : uploadTransferObservers) {
                    if (observer.getId() == id) {
                        Bugfender.d(TAG, "onStateChanged: failed - observer with id : " + id + " to be removed found");
                        observerToRemove = observer;
                    }
                }

                if (observerToRemove != null) {
                    observerToRemove.cleanTransferListener();
                    uploadTransferObservers.remove(observerToRemove);
                    Bugfender.d(TAG, "onStateChanged: failed - observer with id : " + id + " removed successfully");
                }

                Bugfender.d(TAG, "onStateChanged: attempting reupload of id " + id);
                TransferObserver newTransferObserver = transferUtility.resume(id);
                newTransferObserver.setTransferListener(new UploadListener());
                uploadTransferObservers.add(newTransferObserver);

                Bugfender.d(TAG, "onStateChanged: new transfer observer of id " + newTransferObserver.getId() + " has been added");
            }
        }
    }

    private void isAllUploadCompleted() {
        uploadsCompleted = true;

        // Check if all upload observer states are Completed
        for (TransferObserver observer : uploadTransferObservers) {
            observer.refresh();
            Bugfender.d(TAG, "onStateChanged: observer list size " + uploadTransferObservers.size());
            if (observer.getState() != TransferState.COMPLETED) {
                uploadsCompleted = false;
            }
        }

        Bugfender.d(TAG, "onStateChanged: after checking all observer, uploadsCompleted : " + uploadsCompleted);
        if (uploadsCompleted) {
            Bugfender.d(TAG, "isAllUploadCompleted: Stop service called");
            stopUploadService();
        }
    }

    private void stopUploadService() {
        if (wakeLock != null)  {
            Bugfender.d(TAG, "Wake lock released");
            wakeLock.release();
        }
        uploadServiceRunning = false;
        stopForeground(true);
        stopSelf();
    }

}

Начало загрузки:

private void beingUploadInBackground() {
//start upload service
            Context context = mActivity.getBaseContext();
            Intent intent = new Intent(context, UploadService.class);
            intent.putParcelableArrayListExtra(UploadService.INTENT_PHOTOS_UPLOAD, photosToUpload);
            intent.putExtra(UploadService.INTENT_TRANSFER_OPERATION, UploadService.TRANSFER_OPERATION_UPLOAD);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                ContextCompat.startForegroundService(context, intent);
            } else {
                context.startService(intent);
            }
}
...