Android download binary file problems
I don't know if it's the only problem, but you've got a classic Java glitch in there: You're not counting on the fact that read() is always allowed to return fewer bytes than you ask for. Thus, your read could get less than 1024 bytes but your write always writes out exactly 1024 bytes possibly including bytes from the previous loop iteration.
Correct with:
while ( (len1 = in.read(buffer)) > 0 ) {
f.write(buffer,0, len1);
}
Perhaps the higher latency networking or smaller packet sizes of 3G on Android are exacerbating the effect?
Retrofit fails to download binary file in an Android app – end result is a corrupted file that is larger than expected
Suppose problem is not with Retrofit, but with your OkHTTP3 interceptor, specifically here:
val bodyString = response.body()!!.string()
Here are string() contents:
/**
* Returns the response as a string.
*
* If the response starts with a
* [Byte Order Mark (BOM)](https://en.wikipedia.org/wiki/Byte_order_mark), it is consumed and
* used to determine the charset of the response bytes.
*
* Otherwise if the response has a `Content-Type` header that specifies a charset, that is used
* to determine the charset of the response bytes.
*
* Otherwise the response bytes are decoded as UTF-8.
*
* This method loads entire response body into memory. If the response body is very large this
* may trigger an [OutOfMemoryError]. Prefer to stream the response body if this is a
* possibility for your response.
*/
@Throws(IOException::class)
fun string(): String = source().use { source ->
source.readString(charset = source.readBomAsCharset(charset()))
}
You can check ResponseBody source code for more details.
Suppose using body.source() instead would help.
(or just avoid intercepting binary files)
Good interceptor implementation example is here:
HTTPLoggingInterceptor.
Android: How to download binary files from the internet
String FileName = "/LocalDisk/jm";
This is absolute path so you have to use it like this
String FileName = Environment.getExternalStorageDirectory() + "/jm"; // /sdcard/jm
More info about getExternalStorageDirectory().
Also there is no good idea to download a file in UI thread cause it's blocking operation and may cause Activity Not Responding. The best way will be to use AsyncTask to handle this operation in background and notify the gui when you're done.
java google drive API unable to download binary file
The file.get method does return the file data, however only for binary file types. that is what this error message its telling you.
Only files with binary content can be downloaded. Use Export with Docs Editors files.
String fileId = "0BwwA4oUTeiV1UVNwOHItT0xfa2M";
OutputStream outputStream = new ByteArrayOutputStream();
driveService.files().get(fileId)
.executeMediaAndDownloadTo(outputStream);
All other file types those being google docs, google sheets. check this page for more: mimetype
Need to be exported from the google mime type to a standard mime type. If you check the manage-downloads#java page you will find a documented example of how to use this method.
String fileId = "1ZdR3L3qP4Bkq8noWLJHSr_iBau0DNT4Kli4SxNc2YEo";
OutputStream outputStream = new ByteArrayOutputStream();
driveService.files().export(fileId, "application/pdf")
.executeMediaAndDownloadTo(outputStream);
The trick with this method is to ensure you are setting the correct mimetype
How to download binary file
Use response.bodyBytes
:
void downloadFile(File f) async {
var url = Uri.encodeFull('https://API_URL');
var response = await http.post(url, headers: {HttpHeaders.authorizationHeader: 'Bearer '},});
await f.writeAsBytes(response.bodyBytes);
}
I removed the Accept
header as it made no sense. You're hinting the server that you'll expect JSON, whereas you really want a PDF.
Running binary files
That is not supported on modern versions of Android, for security reasons. Quoting the documentation:
Untrusted apps that target Android 10 cannot invoke exec() on files within the app's home directory. This execution of files from the writable app home directory is a W^X violation. Apps should load only the binary code that's embedded within an app's APK file.
Please note that what you are doing may also violate the terms of service of your desired app distribution channel.
Downloading a single file with AsyncTask
AsyncTask just runs your code in the background thread. To download a pdf file is like any other file.
You will require to use HttpUrlConnection
, Create a FileOutputStream
and write the inputstream
. Refer this
Have the above code executed in doInBackground
of AsyncTask class and better pass the url in the constructor and do everything inside the doInBackground
method. Since you don't want to block the UI thread.
Related Topics
Double Decimal Formatting in Java
How to Avoid Installing "Unlimited Strength" Jce Policy Files When Deploying an Application
Replacing a Fragment with Another Fragment Inside Activity Group
How to Set Addsnapshotlistener and Remove in Populateviewholder in Recyclerview Item
Android Camera Will Not Work. Startpreview Fails
How to Make This Jbutton Visible? When I Have Progressive Scan Background Jwindow()
What Determines the Current Working Directory of Tomcat Java Process
How to Build Netty-Transport-Native-Epoll-4.0.32.Final-Linux-X86_64.Jar
Shuffle Multiple Files in Same Order
Could Not Create the Java Virtual MAChine
How to Parse Dates in Multiple Formats Using Simpledateformat
Java: How to Get a Class Literal from a Generic Type
Firestore - Merging Two Queries Locally
Recyclerview Horizontal Scrolling to Left
How to Get the First Day of the Current Week and Month
How to Start Using and Developing on Ubuntu Linux