joltup / rn-fetch-blob

A project committed to making file access and data transfer easier, efficient for React Native developers.
MIT License
2.81k stars 770 forks source link

RNFetchBlob download not working on android 9 #478

Open sheshnathiicmr opened 4 years ago

sheshnathiicmr commented 4 years ago

My code to download the file as below

RNFetchBlob
                .config({
                    path : path,
                    background: true,
                    cacheable:false,
                    timeout: 1000 * 60 * 15 //15 minutes
                })
                .fetch('GET', forFile.url, {
                    //some headers ..
                })
                .then((res) => {

                    Realm.open({schema: [ScheduleSchema,PlaylistSchema,FileSchema],schemaVersion: schema_version})
                    .then(realm => {
                        realm.write(() => {
                            localPath = Platform.OS === 'android' ? 'file://' + res.path() : `playlists/${playlistName}/${getFileName(forFile)}`
                            forFile.file_local_path = localPath
                            console.log('The file saved to ', res.path() + 'for remote url' +forFile.url)

                        })
                    }).catch((error) => {
                        alert("realm open error on file download service", error);
                        console.log(error);
                        reject(error)
                    })

                    resolve(forFile);
                }).catch((error)=>{
                    console.log("file download error " + error);
                    showToastMessage(I18n.t("ErrorMessage.ErrorInFileDownload"))
                })

This code works fine for android 7 but not on android 9. Error log from Android studio Logcat as below

java.lang.IllegalStateException: cannot make a new request because the previous response is still open: please call response.close()
        at okhttp3.internal.connection.Transmitter.newExchange(Transmitter.java:164)
        at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:41)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117)
        at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:94)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117)
        at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
        at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:88)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117)
        at com.RNFetchBlob.RNFetchBlobReq$2.intercept(RNFetchBlobReq.java:385)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117)
        at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:221)
        at okhttp3.RealCall$AsyncCall.execute(RealCall.java:172)
        at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:764)

Versions - "rn-fetch-blob": "0.11.2" react-native: 0.60.5 Android - buildToolsVersion = "28.0.3" minSdkVersion = 22 //min supported devices, android 5.1 lollipop compileSdkVersion = 28 targetSdkVersion = 28 supportLibVersion = "28.0.3"

Note - Before the call of rn-fetch-blob file download, I have one more API call i.e fetch(react-native) to download playlists JSON.

gustavorozolin commented 4 years ago

@sheshnathiicmr did you solve this issue?

sheshnathiicmr commented 4 years ago

now I use this approach

RNFetchBlob
    .config({
        addAndroidDownloads : {
            useDownloadManager : true, // <-- this is the only thing required
            // Optional, override notification setting (default to true)
            notification : false,
            // Optional, but recommended since android DownloadManager will fail when
            // the url does not contains a file extension, by default the mime type will be text/plain
            mime : 'text/plain',
            description : 'File downloaded by download manager.'
        }
    })
    .fetch('GET', 'http://example.com/file/somefile')
    .then((resp) => {
      // the path of downloaded file
      resp.path()
    })
JerakRus commented 4 years ago

Have this error on version 11.2 and 12.0 =(

JerakRus commented 4 years ago

Guys, I solved this problem. The approach with Download Manager works because it is a third-party application that already has the required permissions. If you want to download without manager in order to get download progress, it is important to get permissions in your application. And just adding <uses-permission android: name = "android.permission.WRITE_EXTERNAL_STORAGE" /> to AndroidManifest.xml is not enough. Additionally, you need to explicitly request permission like this: https://reactnative.dev/docs/permissionsandroid. If you do RNFetchBlob.fs.dirs - in every directory that starts with '/ storage' you will need it permission! I hope someone will be useful.

babeone commented 3 years ago

Anyone have solved? I don't want use the DownloadManager because Android DownloadManager can only store files to external storage. @JerakRus i have requested the WRITE_EXTERNAL_STORAGE but it still don't work.

The library crash when the app targetSdkVersion is set to 29, if i go back to 28 all work correctly.

Error: E/AndroidRuntime: FATAL EXCEPTION: OkHttp Dispatcher Process: com.test.test, PID: 6323 java.lang.IllegalStateException: cannot make a new request because the previous response is still open: please call response.close() at okhttp3.internal.connection.Transmitter.newExchange(Transmitter.java:164) at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:41) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117) at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:94) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117) at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142) at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:88) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117) at com.RNFetchBlob.RNFetchBlobReq$2.intercept(RNFetchBlobReq.java:433) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117) at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:229) at okhttp3.RealCall$AsyncCall.execute(RealCall.java:172) at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) at java.lang.Thread.run(Thread.java:919)

I think the problem is in the OkHttp library

JerakRus commented 3 years ago

Кто-нибудь решил? Я не хочу использовать DownloadManager, потому что Android DownloadManager может хранить файлы только во внешнем хранилище. @JerakRus Я запросил WRITE_EXTERNAL_STORAGE, но он все еще не работает.

Сбой библиотеки, когда приложение targetSdkVersion установлено на 29, если я возвращаюсь к 28, все работает правильно.

Ошибка: E/AndroidRuntime: FATAL EXCEPTION: OkHttp Dispatcher Process: com.test.test, PID: 6323 java.lang.IllegalStateException: cannot make a new request because the previous response is still open: please call response.close() at okhttp3.internal.connection.Transmitter.newExchange(Transmitter.java:164) at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:41) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117) at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:94) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117) at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142) at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:88) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117) at com.RNFetchBlob.RNFetchBlobReq$2.intercept(RNFetchBlobReq.java:433) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117) at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:229) at okhttp3.RealCall$AsyncCall.execute(RealCall.java:172) at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) at java.lang.Thread.run(Thread.java:919)

Я думаю, что проблема в библиотеке OkHttp

try adding to : android:requestLegacyExternalStorage="true"

babeone commented 3 years ago

@JerakRus yeah it work, thank you

hegdeMadan commented 3 years ago

+1 on this.

buildToolsVersion = "29.0.2" minSdkVersion = 19 compileSdkVersion = 29 targetSdkVersion = 29

but when I switched all 29's to 28 then it works fine I tried adding android:requestLegacyExternalStorage="true" as well. But in vain!

hegdeMadan commented 3 years ago

I found a workaround. I upgraded all sdk versions in node_modules/rn-fetch-blob/android/build.gradle to 29 and now it works fine

vishwas247 commented 3 years ago

Hi guys , found any solution for this ?

marinne commented 3 years ago

@JerakRus yeah it work, thank you

Adding

android:requestLegacyExternalStorage="true"

to AndroidManifest.xml also worked for me. Thanks!

The0racle commented 2 years ago

@JerakRus yeah it work, thank you

Adding

android:requestLegacyExternalStorage="true"

to AndroidManifest.xml also worked for me. Thanks!

Unfortunately this solution does not work when targeting android API 30, as per the documentation:

Caution: After you update your app to target Android 11 (API level 30), the system ignores the requestLegacyExternalStorage attribute when your app is running on Android 11 devices, so your app must be ready to support scoped storage and to migrate app data for users on those devices

If anyone finds a solution for this, please share here.

fondue-tech commented 2 years ago

Did anyone found any solution to this targeting API 30 + ?

fukemy commented 1 year ago

any solution? is this lib dead???

babeone commented 1 year ago

Try this fork

https://github.com/RonRadtke/react-native-blob-util