首页 > 解决方案 > Android Studio:用于将数据上传到 Firebase 的工作类

问题描述

我正在寻找一种无需用户等待数据上传即可将数据上传到 Firebase 的解决方案,以便用户可以在离线模式下使用该应用。

假设该应用程序是关于场所的。在这个应用程序中,用户可以上传包含地址、城市、州、国家、纬度、经度、描述等的图像和对象。假设是一个大 POJO。

Firebase 实时数据库和 Firebase Firestore 可以等待(我不知道多长时间)稳定的互联网连接来发送数据。但是 Firebase 存储没有这个功能。

所以我找到了WorkManager。它似乎解决了这个问题,但我必须将我的 POJO 序列化为小的原始变量类型,以便将 POJO 发送到Worker类。

我想要达到的结果是:

1) 将图片上传到 Firebase 存储

2) 图片的下载地址

3) 将 POJO 发送到 Firebase Firestore,其中包含 ImageUrl。

问题

1)WorkManager最适合这种目的吗?

2) 在离线模式下,用户可以触发多少次后台作业而不会对应用程序造成任何问题?

3)如何正确地将POJO发送到Worker班级?

这是我到目前为止所做的:

获取新地点的 pushKey,启动后台作业并继续浏览活动:

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

            DocumentReference docRef = DatabaseRouter.getPlaceCollectionRef().document();
            String key = docRef.getId();
            uploadPlaceDataInBackground(key)
            Intent intent = new Intent(PlaceActivity.this, OtherActivity.class);
            startActivity(intent);

        }
    });

设置后台作业的请求:

    private void uploadPlaceDataInBackground(String placeKey) {
        // TESTING WORKMANAGER FOR UPLOADING IMAGES TO FIREBASE STORAGE
        // 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 uploadBuilder = new Data.Builder();
        uploadBuilder.putString("image_uri", placeImageUri.toString());
        uploadBuilder.putString("image_pushkey", placeKey);
        Data ImageUriInputData = uploadBuilder.build();

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

        OneTimeWorkRequest downloadWorkRequest = new OneTimeWorkRequest
                .Builder(DownloadImageUrlWorker.class)
                .setConstraints(constraints)
                .build();

        // Converting placeObject into Map
        Data.Builder uploadPlaceBuilder = new Data.Builder();
        Map<String, Object> placeMap = convertPlaceObjectIntoMap();
        uploadPlaceBuilder.putAll(placeMap);
        Data placeInfoInputData = uploadPlaceBuilder.build();

        OneTimeWorkRequest uploadPlaceWorkRequest = new OneTimeWorkRequest
                .Builder(UploadPlaceWorker.class)
                .setConstraints(constraints)
                .setInputData(placeInfoInputData)
                .build();

        // Execute and Manage the background service
        WorkManager workManager = WorkManager.getInstance(getActivity());
        workManager.beginWith(uploadWorkRequest)
                .then(downloadWorkRequest)
                .then(uploadPlaceWorkRequest)
                .enqueue();
    }

以下是Worker课程:

public class UploadImageWorker extends Worker {

    public UploadImageWorker(@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");

        final Result[] result = {Result.retry()};
        CountDownLatch countDownLatch = new CountDownLatch(1);
        StorageReference storageRef = DatabaseRouter.getPlaceStorageRef(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()) {
                    result[0] = Result.success(getInputData());
                } 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];
    }
}

public class DownloadImageUrlWorker extends Worker {

    public DownloadImageUrlWorker(@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");

        final Result[] result = {Result.retry()};
        CountDownLatch countDownLatch = new CountDownLatch(1);
        StorageReference storageRef = DatabaseRouter.getPlaceStorageRef(imagePushKey).child(imagePushKey+".jpg");
        storageRef.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
            @Override
            public void onSuccess(Uri uri) {
                String imageUrl = uri.toString();

                Data.Builder outputBuilder = new Data.Builder();
                outputBuilder.putString("image_url", imageUrl);
                outputBuilder.putString("image_pushkey", imagePushKey);
                Data outputData = outputBuilder.build();
                result[0] = Result.success(outputData);

                countDownLatch.countDown();
            }
        }).addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                Log.i(TAG, "onFailure: imageUrl NOT downloaded - RETRYING");
                result[0] = Result.retry();
                countDownLatch.countDown();
            }
        });



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

public class UploadPlaceWorker extends Worker {

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

    @NonNull
    @Override
    public Result doWork() {
        String imageUrl = getInputData().getString("image_url");
        String imagePushKey = getInputData().getString("image_pushkey");

        Map<String, Object> placeObject = getInputData().getKeyValueMap();

        PlaceModel placeModel = convertMapIntoPlaceObject(placeObject, imageUrl, imagePushKey);

        final Result[] result = {Result.retry()};
        CountDownLatch countDownLatch = new CountDownLatch(1);
        DocumentReference docRef = DatabaseRouter.getPlaceCollectionRef().document(imagePushKey);
        docRef.set(placeModel).addOnCompleteListener(new OnCompleteListener<Void>() {
            @Override
            public void onComplete(@NonNull Task<Void> task) {
                if (task.isSuccessful()) {
                    result[0] = Result.success();
                } else {
                    Log.i(TAG, "onComplete: place NOT uploaded - RETRYING");
                    result[0] = Result.retry();
                }
                countDownLatch.countDown();
            }
        });

        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return result[0];
    }

    private PlaceModel convertMapIntoPlaceObject(Map<String, Object> placeMap, String imageUrl, String placeKey) {
        PlaceModel place = new PlaceModel();
        place.setAddress(placeMap.get("a").toString());
        place.setCity(placeMap.get("b").toString());
        place.setCountry(placeMap.get("c").toString());
        place.setDistrict(placeMap.get("d").toString());
        place.setG(placeMap.get("e").toString());
        place.setId(placeMap.get("f").toString());
        place.setImage(imageUrl);
        place.setKey(placeKey);
        GeoPoint geoPoint = new GeoPoint((Double) placeMap.get("h"), (Double) placeMap.get("i"));
        place.setL(geoPoint);
        place.setDescription(placeMap.get("j").toString());

        return place;
    }
}

我很感激任何帮助!

标签: androidgoogle-cloud-firestorefirebase-storageandroid-workmanager

解决方案


推荐阅读