How to publish image files using Firebase storage in offline mode?

Hello, I am developing a code within Android Studio that allows data registration in a form with text fields and an image file offline (mobile without any internet connection). Works great with FirebaseDatabase.getInstance() but with the FirebaseStorage.getInstance(), that is, with the two together, (text and image) errors occur.

The idea is to save the data (texts and their attached image) locally on the Smartphone (including consult) and when the same connects on some network the same synchronize the data on the Firebase server.

I did tests using only texts and it works very well, but if I take a photo and attach it to the form, nothing happens.

Any suggestions? Has anyone ever faced any problem similar to this?

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //
        mFirebaseData = FirebaseDatabase.getInstance();
        mDatabaseReference = mFirebaseData.getReference("Data");
        mDatabaseReference.keepSynced(true);
        //storage
        mStorageReference = FirebaseStorage.getInstance().getReference();

Author: ademirs, 2019-09-04

2 answers

Save your images using local database and use the Workmanager library that works in the background to sync with firebase when internet is available.

 -1
Author: André alas, 2019-09-04 01:14:34

Here's a practical example of what you asked:

In this example, we will upload an image to FirebaseStorage. For this, I suppose that the steps to acquire the image via camera or gallery is known in advance.

You can start background thread from a button:

     saveStoreData.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            if (isFormFieldsFilled()) {

                DocumentReference docRef = DatabaseRouter.getStoresCollectionRef().document();
                String key = docRef.getId();

                // Create a Constraints object that defines when the task should run
                Constraints constraints = new Constraints.Builder()
                        .setRequiredNetworkType(NetworkType.CONNECTED)
                        .build();

                // Passing data to the worker class
                Data.Builder builder = new Data.Builder();
                builder.putString("image_uri", profileImageUri.toString());
                builder.putString("image_pushkey", key);
                Data inputData = builder.build();

                // ...then create a OneTimeWorkRequest that uses those constraints
                OneTimeWorkRequest uploadWorkRequest = new OneTimeWorkRequest
                        .Builder(UploadImageToServerWorker.class)
                        .setConstraints(constraints)
                        .setInputData(inputData)
                        .build();

                // Execute and Manage the background service
                WorkManager workManager = WorkManager.getInstance(getActivity());
                workManager.enqueue(uploadWorkRequest);

            }

        }
    });

Now just create the worker class: UploadImageToServerWorker

public class UploadImageToServerWorker extends Worker {

    // https://www.raywenderlich.com/6040-workmanager-tutorial-for-android-getting-started

    private static final String TAG = "debinf UploadWorker";

    public UploadImageToServerWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
        super(context, workerParams);
    }

    @NonNull
    @Override
    public Result doWork() {
        String imageUriInput = getInputData().getString("image_uri");
        String imagePushKey = getInputData().getString("image_pushkey");
        Log.i(TAG, "doWork: BACKGROUND WORK STARTED FOR KEY: "+imagePushKey);

        final Result[] result = {Result.retry()};
        CountDownLatch countDownLatch = new CountDownLatch(1);
        StorageReference storageRef = DatabaseRouter.getStoresStorageRef(imagePushKey).child(imagePushKey+".jpg");
        storageRef.putFile(Uri.parse(imageUriInput)).addOnCompleteListener(new OnCompleteListener<UploadTask.TaskSnapshot>() {
            @Override
            public void onComplete(@NonNull Task<UploadTask.TaskSnapshot> task) {
                if (task.isSuccessful()) {
                    Log.i(TAG, "onComplete: image uploaded successfuly!");
                    result[0] = Result.success();
                } else {
                    Log.i(TAG, "onComplete: image NOT uploaded - RETRYING");
                    result[0] = Result.retry();
                }
                countDownLatch.countDown();
            }
        });

        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return result[0];
    }
}

Hello! I do not know if this is the most appropriate method, but it accounts for the service.

"problems" I found:

1) sending the image is done without an internet connection, but the internet connection is reestablished before the internet connection timeoutFirebaseStorage: the doWork() method is executed 2 times.

2) sending the image is done without an internet connection and the internet connection is reestablished after the internet connection timeoutFirebaseStorage: the medoto doWork() does not run as soon as the internet return.

Well... Hope I helped and good luck!

 0
Author: Aliton Oliveira, 2019-12-23 00:32:03