Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Class Cast exception #490

Open
learnyst opened this issue Nov 17, 2019 · 29 comments
Open

Class Cast exception #490

learnyst opened this issue Nov 17, 2019 · 29 comments

Comments

@learnyst
Copy link

  • please provide the version of installed library and RN project.
    React native: 0.60.4
    rnFetchBlob: 0.11.2

  • a sample code snippet/repository is very helpful to spotting the problem.
    We are not able to reproduce crash. Many of app users are facing issue.

rnFetchBlob is crashing with the below exception. We have got this exception in bugsnag

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

@learnyst learnyst changed the title Class Cast exceltiop Class Cast exception Nov 17, 2019
@z384647062
Copy link

Change RNFetchBlob.fs.dirs.MusicDir to RNFetchBlob.fs.dirs.DocumentDir in option path of RNFetchBlob.config helps me solve the problem

@oleksandr-dziuban
Copy link

oleksandr-dziuban commented Jan 23, 2020

Change RNFetchBlob.fs.dirs.MusicDir to RNFetchBlob.fs.dirs.DocumentDir in option path of RNFetchBlob.config helps me solve the problem

@z384647062 I have same issue, but don't use any RNFetchBlob.fs.dirs.MusicDir in app.

I use RNFetchBlob.fs.dirs.DocumentDir everywhere.
Inеeresting that this error is only throws on non-clean Android. On Native Android (simulator or device) everything is OK. On Xiaomi, for example I see this error in MiUI

@oleksandr-dziuban
Copy link

Question to maintainers, Is it possible to review this issue please?

@oleksandr-dziuban
Copy link

@Traviskn Hello, I have checked this issues in 0.10.16 and it is not reproducible!
Only the latest few versions throw this error for Android

@oleksandr-dziuban
Copy link

Any ideas guys?

@Sumit-Chakole
Copy link

Change RNFetchBlob.fs.dirs.MusicDir to RNFetchBlob.fs.dirs.DocumentDir in option path of RNFetchBlob.config helps me solve the problem

This worked in my case too :)

@brianinator
Copy link

Relates to recent PR #530 that is going to catch it and return back.

@olcayertas
Copy link

olcayertas commented Feb 5, 2020

I am getting the same error on Mac OS X with Android simulator (API 29 Google Play):

let dir = Platform.OS === "ios" ? 
    RNFetchBlob.fs.dirs.DocumentDir : 
    RNFetchBlob.fs.dirs.DownloadDir;
console.log("Download location: " + dir);
let headers = { Authorization: "Bearer " + token };
let options = { fileCache: true, path : dir + '/file' };
RNFetchBlob.config(options).fetch("GET", url, headers)

Error:

java.lang.ClassCastException: okhttp3.internal.http.RealResponseBody
cannot be cast to com.RNFetchBlob.Response.RNFetchBlobFileResp
	at com.RNFetchBlob.RNFetchBlobReq.done(RNFetchBlobReq.java:594)
	at com.RNFetchBlob.RNFetchBlobReq.access$100(RNFetchBlobReq.java:72)
	at com.RNFetchBlob.RNFetchBlobReq$3.onResponse(RNFetchBlobReq.java:493)
	at okhttp3.RealCall$AsyncCall.execute(RealCall.java:206)
	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)

Version: 0.12.0
React: 0.61.5

@nobady90
Copy link

nobady90 commented Feb 6, 2020

same error in Xiaomi with android 9 and MIUI Global 11.3.4.
in practice it seems that it does not resolve the gallery and therefore does not open the downloaded file with: RNFetchBlob.android.actionViewIntent (res.path (), item.mimeType);

instead everything works normally for example with pdf ... any help?

@hadare1
Copy link

hadare1 commented Feb 14, 2020

I have the same issue on Pixel 3 and,
where do I need to make this change?

Change RNFetchBlob.fs.dirs.MusicDir to RNFetchBlob.fs.dirs.DocumentDir in option path of RNFetchBlob.config helps me solve the problem

This worked in my case too :)

@funkyfourier
Copy link

I am having this issue too. If I catch the exception, like in PR #530, then it will just fail silently and not download and save the file.

I am trying to download lots of files at once. They are for the most part slippy map tiles, in other words tiny png files. I slice the list of files in portions, so I do for example 20 at a time with Promise.all. Then I will get maybe 3-4 ClassCastExceptions for about 800 files.

Noticeably, the ClassCastException is not thrown when I only do Promise.all with one promise at a time. If I do two or more, the exception almost certainly will be thrown during those 800 files.

So, to be clear, I have an array of promises, about 800 of them, like this:

const fetchFile = (fileMeta) => {
        return new Promise((resolve, reject) => {
            fetchBlobTask = RNFetchBlob.config({
                path: fileMeta.filename,
                fileCache: true,
            }).fetch(
                'GET', encodeURI(fileMeta.url)
            );
            fetchBlobTask.then((result) => {
                resolve(result);
            }).catch((error) => {
                reject(error);
            });
        });
}

I then do Promise.all on (for example) 20 of those at a time. On iOS this works without a hitch. If I do only one at a time, it works on both platforms, but is painfully slow.

This happens on the emulator, on a OnePlus 6 and on a Sony XZ1.

It is also worth mentioning that the previous version of the app, which was built with Cordova, also had a similar issue on Android.

@brianinator
Copy link

Although downgrading to 0.10.16 made this issue go away, I decided to stay on 0.12.0 and switched to use Android download manager. The config I used:

config.addAndroidDownloads = {
  useDownloadManager: true,
  notification: true,
  mediaScannable: false,
  path: /path/to/file
};

@oleksandr-dziuban
Copy link

oleksandr-dziuban commented Feb 20, 2020

@Traviskn Hello, any ideas how to fix this issue?
Possibly this PR breaks Android
https://github.com/joltup/rn-fetch-blob/pull/530/files

Can we revert it and publish new npm package?

@oleksandr-dziuban
Copy link

Is this library still maintained? Looks like no...

@Desintegrator
Copy link

same ussue ((( help wanted
Im don't use MusicDir in app

@oleksandr-dziuban
Copy link

@Traviskn Is it possible to revert PR related to this issue? We are blocked currently in out project with this issue

@punksta
Copy link

punksta commented Apr 2, 2020

I am having the same issue in production app.

@ahetesumspurtree
Copy link

ahetesumspurtree commented May 4, 2020

Any Update on this issue???
@Traviskn

@nguyenhoanglam
Copy link

nguyenhoanglam commented May 14, 2020

I think the reason this error occurred is related to Android 10's file access policy. So I temporaryly fixed it by add android:requestLegacyExternalStorage="true" attribute to the application tag in AndroidManifest.xml file, like this:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.android.example">
       ...
    <application
        android:name="com.android.example.MainApplication"
        android:allowBackup="false"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:requestLegacyExternalStorage="true"
        android:theme="@style/AppTheme">
      
        ...
    </application>

</manifest>

@nes123
Copy link

nes123 commented Jun 6, 2020

@nguyenhoanglam it does not work in my case, and i get the error also for android 9

@Muratoter
Copy link

@nguyenhoanglam Worked on Android 10, thanks.

@Yarkhan
Copy link

Yarkhan commented Jun 25, 2020

I was getting this error too in some Android devices. Some of the users of my app have denied the app permission to manage files, so when trying to downloading something the app would just crash. Checking the permissions before downloading have fixed this issue for me

Edit: While this fixed the issue for the majority of my users, there are some cases where the problem persists, even when the permissions are correctly set.

I will try to contact the user and send him a custom build using expo filesystem.

@timxyz
Copy link

timxyz commented Jul 6, 2020

Commenting here even though I can see PR #530 has been merged. I think that PR suppresses the crash but does not address the underlying cause, which is the custom OkHttp interceptor that is installed in RNFetchBlobReq.

This interceptor is responsible for wrapping the response body in an instance of RNFetchBlobDefaultResp. However I've noticed a crash can very occasionally occur like so:

  1. An initial request is made that fails with an exception. (e.g. SocketTimeoutException)
  2. The HTTP interceptor catches the exception. It has then been written to attempt the request again.
  3. If this request then succeeds, then the raw OkHttp response is returned to the caller. The interceptor does not wrap the response body as it is supposed to.
  4. The caller is expecting a response with a wrapped body and so crashes.

I have been able to reliably replicate the issue by programatically causing SocketTimeoutException to occur. I am then able to fix by modifying the code to propagate this exception, instead of making a second request. This causes RNFB to properly report a failure back to the RN code. An alternative fix would be to make sure the response from the second request is wrapped, but personally I don't think the interceptor should be implementing this kind of retry logic.

@zhirzh
Copy link

zhirzh commented Oct 21, 2020

This issue exists because the exported dirs constant is populated using getExternalStoragePublicDirectory() which is deprecated in android 10

static Map<String, Object> getSystemfolders(ReactApplicationContext ctx) {
Map<String, Object> res = new HashMap<>();
res.put("DocumentDir", ctx.getFilesDir().getAbsolutePath());
res.put("CacheDir", ctx.getCacheDir().getAbsolutePath());
res.put("DCIMDir", Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getAbsolutePath());
res.put("PictureDir", Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath());
res.put("MusicDir", Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC).getAbsolutePath());
res.put("DownloadDir", Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath());
res.put("MovieDir", Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES).getAbsolutePath());
res.put("RingtoneDir", Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_RINGTONES).getAbsolutePath());
String state;
state = Environment.getExternalStorageState();

@ebrahimmfadae
Copy link

I also had this problem in Android 8.1.0 Nexus 5X. Attribute android:requestLegacyExternalStorage="true" didn't fix it but downgrading to 0.10.16 solved the issue. thanks @oleksandr-dziuban

@tastyqbit
Copy link

tastyqbit commented Dec 24, 2020

If you install from the master branch using npm install --save git+https://github.com/joltup/rn-fetch-blob.git it has been fixed

@darron1217
Copy link

darron1217 commented Feb 12, 2021

I solved it by following @nguyenhoanglam 's answer for android above 10, and requesting permission for android above 6.
Here's my solution.

Android >= 10

add android:requestLegacyExternalStorage="true" on AndroidManifest.xml

Android >= 6

request permission before fetch

const requestExternalStoragePermissions = async () => {
  const read = await PermissionsAndroid.request(
    PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,
  );
  const write = await PermissionsAndroid.request(
    PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
  );
  return (
    read === PermissionsAndroid.RESULTS.GRANTED &&
    write === PermissionsAndroid.RESULTS.GRANTED
  );
};

@srbulovicdusan
Copy link

I solved this problem by modifying rn-fetch-blob and saving those changes permanently using patch-package.

  • Go to node_modules/rn-fetch-blob/.../Response/RNFetchBlobFileResp.java and add constructor =>
    public RNFetchBlobFileResp(ResponseBody body) {
    super();
    this.originalBody = body;
    }

  • Then find RNFetchBlobReq.java and change line ~594 RNFetchBlobFileResp rnFetchBlobFileResp = (RNFetchBlobFileResp) responseBody; to RNFetchBlobFileResp rnFetchBlobFileResp = new RNFetchBlobFileResp(responseBody);

  • Use patch-package to save this changes permanently.

QSuraj added a commit to QSuraj/rn-fetch-blob that referenced this issue Aug 10, 2022
QSuraj added a commit to QSuraj/rn-fetch-blob that referenced this issue Aug 12, 2022
@goldqwert
Copy link

goldqwert commented Oct 3, 2022

This lib not maintained. I used react-native-blob-util properly maintained. It's helped me to fix issues with Class Cast exception.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests