rn-fetch-blob icon indicating copy to clipboard operation
rn-fetch-blob copied to clipboard

App is crashing when i try to download in realme devices (Android 9)

Open subbareddyandr opened this issue 5 years ago • 6 comments

Hi Please help me to solve the problem , When i try to download file, app is crashing it is happening in realme devices (Android 9 & 10) only "rn-fetch-blob": "^0.12.0", "react-native": "0.63.2", SAmple Code .

                RNFetchBlob
                    .config({
                        fileCache: true,
                        addAndroidDownloads: {
                            useDownloadManager: true,
                            notification: true,
                            mediaScannable: true,
                            title: fileName,
                            path: `${downloadDest}/${fileName}`,
                        },
                    })
                    .fetch("GET", url, {}).then(result => {
                      
                        );
                    })

Crash Log

com.facebook.react.bridge.CallbackImpl.invoke CallbackImpl.java, line 26 java.lang.RuntimeException: Illegal callback invocation from native module. This callback type only permits a single invocation from native code.

com.facebook.react.bridge.CallbackImpl.invoke CallbackImpl.java:26 com.RNFetchBlob.RNFetchBlobReq.onReceive RNFetchBlobReq.java:778 android.app.LoadedApk$ReceiverDispatcher$Args.lambda$getRunnable$0 LoadedApk.java:1501 android.app.LoadedApk$ReceiverDispatcher$Args.lambda$getRunnable$0 LoadedApk.java:1532 android.app.-$$Lambda$LoadedApk$ReceiverDispatcher$Args$_BumDX2UKsnxLVrE6UJsJZkotuA.run android.os.Handler.handleCallback Handler.java:873 android.os.Handler.dispatchMessage Handler.java:99 android.os.Looper.loop Looper.java:226 android.app.ActivityThread.main ActivityThread.java:7178 java.lang.reflect.Method.invoke Method.java com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run RuntimeInit.java:503 com.android.internal.os.ZygoteInit.main ZygoteInit.java:942

Thanks in Advance

subbareddyandr avatar Nov 11 '20 12:11 subbareddyandr

+1, also the error occurs on Huawei Devices:

The error would be: java.lang.ClassCastException okhttp3.internal.http.RealResponseBody cannot be cast to com.RNFetchBlob.Response.RNFetchBlobFileResp RNFetchBlobReq.java:544 com.RNFetchBlob.RNFetchBlobReq.done RNFetchBlobReq.java:67 com.RNFetchBlob.RNFetchBlobReq.access$100 RNFetchBlobReq.java:445 com.RNFetchBlob.RNFetchBlobReq$3.onResponse RealCall.java:174 okhttp3.RealCall$AsyncCall.execute NamedRunnable.java:32 okhttp3.internal.NamedRunnable.run ThreadPoolExecutor.java:1113 java.util.concurrent.ThreadPoolExecutor.runWorker ThreadPoolExecutor.java:588 java.util.concurrent.ThreadPoolExecutor$Worker.run Thread.java:818 java.lang.Thread.run

xsephtion avatar Dec 01 '20 06:12 xsephtion

any solution to issue mentioned by @xsephtion ?

batcodegen avatar May 31 '21 07:05 batcodegen

any solution to issue mentioned by @xsephtion ?

As far as I remember I used

android:requestLegacyExternalStorage="true"

on my Android Manifest.

Hope that would help you.

Just to add:

RNFetchBlob.fetch('POST', 'http://192.168.1.6:8001/media2', {
    'Content-Type' : 'multipart/form-data',
    }, [data]).then((resp) => {
      console.log("Server Image Response", resp);
  }).catch((err) => {
    console.error("There's an error:", error)
  })

Previously I was using the same code structure with OP. I had to change it same as above. If you are needing notifications, I suggest that you bind a local notification every time the fetch returns a response.

xsephtion avatar May 31 '21 07:05 xsephtion

thanks @xsephtion

batcodegen avatar May 31 '21 07:05 batcodegen

I has same issue. In my case, every download time, i change name of file.

auduongvanhieu avatar Mar 22 '23 12:03 auduongvanhieu

it is solved by changing file name of downloadble. ✅

here is code :

    const randomNum = Math.floor(Math.random() * 100000);
    // Generate a unique filename for the downloaded image
    const filename = url.split('/').pop();
    const imagePath = `${cacheDir}/${randomNum+filename}`;

Here is full code of common function

import RNFetchBlob from 'rn-fetch-blob';
import { Platform, PermissionsAndroid } from 'react-native';

/// grant permission in android
export const getDownloadPermissionAndroid = async () => {
    try {
        const granted = await PermissionsAndroid.request(
            PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
            {
                title: 'File Download Permission',
                message: 'Your permission is required to save Files to your device',
                buttonNegative: 'Cancel',
                buttonPositive: 'OK',
            },
        );
        if (granted === PermissionsAndroid.RESULTS.GRANTED) return true;
    } catch (err) {
        console.log('err', err);
    }
};

export const downloadFile = async url => {
    // Get the app's cache directory
    const { config, fs } = RNFetchBlob;
    const cacheDir = fs.dirs.DownloadDir;
    const randomNum = Math.floor(Math.random() * 100000);
    // Generate a unique filename for the downloaded image/file
    const filename = url.split('/').pop();
    const imagePath = `${cacheDir}/${randomNum+filename}`;

    try {
        // Download the file and save it to the cache directory
        const configOptions = Platform.select({
            ios: {
                fileCache: true,
                path: imagePath,
                appendExt: filename.split(`-${randomNum}.`).pop(),
            },
            android: {
                fileCache: false,
                path: imagePath,
                appendExt: filename.split(`${randomNum}.`).pop(),
                addAndroidDownloads: {
                    // Related to the Android only
                    useDownloadManager: true,
                    notification: true,
                    path: imagePath,
                    description: 'File',
                },
            },
        });

        const response = await RNFetchBlob.config(configOptions).fetch('GET', url);

        console.log("Response of download", response)
        // Return the path to the downloaded file
        return response;
    } catch (error) {
        console.error(error);
        return null;
    }
};

I have called here this code:

     <TouchableOpacity style={{
            backgroundColor: '#36BA98',
            padding: heightPercentageToDP(0.7),
            borderRadius: 100,
            position: 'absolute',
            bottom: 0,
            right: 0
        }}
            onPress={() => {
                console.log("pressed")
                if (Platform.OS === 'android') {
                    getDownloadPermissionAndroid().then(granted => {
                        if (granted) {
                            downloadFile(fileUrl);
                        }
                    });
                } else {
                    downloadFile(fileUrl).then(res => {
                        RNFetchBlob.ios.previewDocument(res.path());
                    });
                }
            }}
        >
            <AntDesign name='download' size={heightPercentageToDP(2.35)} color={'#fff'} />
        </TouchableOpacity>

getsettalk avatar Jul 06 '24 08:07 getsettalk