StorageReference.getFile() crashes when device is offline

When I try to download file from Firebase Storage by using method StorageReference.getFile(File) it crashes when device is offline and timeout is reached. Logcat shows NPE in DynamicModulesC:

java.lang.NullPointerException: null reference
at asn.a(:com.google.android.gms.DynamiteModulesC:27)                                                                                     

The same code works properly and file is downloaded when internet connection is available. I've tested it on devices and emulators with Android 4.1 and 6.0. Firebase SDK version 9.6.1. Is this a bug in firebase SDK? Did I miss something?

Code simple:

FirebaseStorage firebaseStorage = FirebaseStorage.getInstance();
//firebaseStorage.setMaxDownloadRetryTimeMillis(15 * 1000);
StorageReference remoteDir= firebaseStorage.getReference().child("dir-with-files");
File destinationFile= new File("file-in-app-internal-storage");
StorageReference fileRef = remoteDir.child("file-from-firebase");
fileRef.getFile(destinationFile);

Full crash log:

10-02 10:49:57.577 9429-9464/com.github.lecho.mobilization W/System: ClassLoader referenced unknown path: /system/priv-app/PrebuiltGmsCore/lib/x86_64
10-02 10:49:57.610 9429-9464/com.github.lecho.mobilization I/DynamiteModule: Considering local module com.google.android.gms.firebasestorage:0 and remote module com.google.android.gms.firebasestorage:1
10-02 10:49:57.610 9429-9464/com.github.lecho.mobilization I/DynamiteModule: Selected remote version of com.google.android.gms.firebasestorage, version >= 1
10-02 10:49:57.628 9429-9464/com.github.lecho.mobilization W/System: ClassLoader referenced unknown path: /data/user/0/com.google.android.gms/app_chimera/m/00000002/n/x86_64

10-02 10:50:11.599 9429-9462/com.github.lecho.mobilization W/ExponenentialBackoff: network unavailable, sleeping.
10-02 10:50:11.599 9429-9462/com.github.lecho.mobilization E/StorageUtil: error getting token java.util.concurrent.ExecutionException: com.google.firebase.FirebaseApiNotAvailableException: firebase-auth is not linked, please fall back to unauthenticated mode.
10-02 10:50:12.234 9429-9464/com.github.lecho.mobilization W/ExponenentialBackoff: network unavailable, sleeping.
10-02 10:50:12.234 9429-9464/com.github.lecho.mobilization E/StorageUtil: error getting token java.util.concurrent.ExecutionException: com.google.firebase.FirebaseApiNotAvailableException: firebase-auth is not linked, please fall back to unauthenticated mode.

                                                                      --------- beginning of crash
10-02 10:50:12.236 9429-9464/com.github.lecho.mobilization E/AndroidRuntime: FATAL EXCEPTION: FirebaseStorage-Download-3
                                                                         Process: com.github.lecho.mobilization, PID: 9429
                                                                         java.lang.NullPointerException: null reference
                                                                             at asn.a(:com.google.android.gms.DynamiteModulesC:27)
                                                                             at bul.d(:com.google.android.gms.DynamiteModulesC:261)
                                                                             at buf.onTransact(:com.google.android.gms.DynamiteModulesC:76)
                                                                             at android.os.Binder.transact(Binder.java:387)
                                                                             at com.google.android.gms.internal.zzans$zza$zza.aE(Unknown Source)
                                                                             at com.google.android.gms.internal.zzanv.aE(Unknown Source)
                                                                             at com.google.firebase.storage.FileDownloadTask.run(Unknown Source)
                                                                             at com.google.firebase.storage.StorageTask$5.run(Unknown Source)
                                                                             at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
                                                                             at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
                                                                             at java.lang.Thread.run(Thread.java:818)
10-02 10:50:12.237 1540-1997/system_process W/ActivityManager:   Force finishing activity com.github.lecho.mobilization/.ui.MainActivity

                                                           [ 10-02     10:50:12.246  1540: 1997 D/         ]
                                                           HostConnection::get() New Host Connection established 0x7f39f896fc00, tid 1997

It turns out to be a bug in Google Play services. Firebase team has already fixed it. The fix is available in version 9.8.77 of Google Play services.

Now StorageReference.getFile(File) will not crash the app when device is offline. Instead you will receive following response:

E/StorageException: StorageException has occurred. 
The operation retry limit has been exceeded. 
Code: -13030 HttpResult: -2

Try this:

try{
    fileRef.getFile(destinationFile).addOnSuccessListener(new OnSuccessListener<FileDownloadTask.TaskSnapshot>() {
        @Override
        public void onSuccess(FileDownloadTask.TaskSnapshot taskSnapshot) {
            // Local temp file has been created
        }
    }).addOnFailureListener(new OnFailureListener() {
        @Override
        public void onFailure(@NonNull Exception exception) {
            // Handle any errors
        }
    });
} catch (Exception e){
// Error
}

Additionally, we can do below things: 1. add try catch block to handle any exception while downloading file is called. 2. Save storage ref as a reference in onSaveInstanceState. 3. Later, we can call onRestoreInstanceState.

StorageReference mStorageRef;  //mStorageRef was previously used to transfer data.

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    // If there's a download in progress, save the reference so you can query it later
    if (mStorageRef != null) {
        outState.putString("reference", mStorageRef.toString());
    }
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);

    // If there was a download in progress, get its reference and create a new StorageReference
    final String stringRef = savedInstanceState.getString("reference");
    if (stringRef == null) {
        return;
    }
    mStorageRef = FirebaseStorage.getInstance().getReferenceFromUrl(stringRef);

    // Find all DownloadTasks under this StorageReference (in this example, there should be one)
    List tasks = mStorageRef.getActiveDownloadTasks();
    if (tasks.size() > 0) {
        // Get the task monitoring the download
        DownloadTask task = tasks.get(0);

        // Add new listeners to the task using an Activity scope
        task.addOnSuccessListener(this, new OnSuccessListener() {
          @Override
          public void onSuccess(DownloadTask.TaskSnapshot state) {
             handleSuccess(state); //call a user defined function to handle the event.
          }
        });
    }
}

You need to download the file once you are online using the getFile() method and save the file locally. Then use the locally saved file once you go offline. You cannot download the file using getFile() method when you are offline. Please read the documentation: https://firebase.google.com/docs/storage/android/download-files

链接地址: http://www.djcxy.com/p/36484.html

上一篇: Navbar悬停没有显示

下一篇: 设备脱机时,StorageReference.getFile()会崩溃