I am new to android and JSON using retrofit. I am using retrofit 2 with my project.
This is one of post API and it gives a pdf as the response.
#POST("examples/campaign_report_new.php")
Call<ResponseBody> getAddressTrackingReport(#Body ModelCredentialsAddressTracking credentials);
I used the below code to do this function and I stuck in the response method to download and show that pdf.
private void downloadPdf() {
ModelCredentialsAddressTracking
credentials = new ModelCredentialsAddressTracking(campaign,
dateFrom, dateTo);
ApiService apiService = RetroClient.getApiService();
Call<ResponseBody> call = apiService.getAddressTrackingReport(credentials);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
try {
Log.d(TAG, String.valueOf(response.body().bytes()));
} catch (IOException e) {
e.printStackTrace();
}
boolean writtenToDisk = writeResponseBodyToDisk(response.body());
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
}
});
}
Below link is the response I got from Postman:
click here
writeResponseBodyToDisk() function :
private boolean writeResponseBodyToDisk(ResponseBody body) {
try {
File mediaStorageDir = new File(
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
"Door Tracker");
// Create the storage directory if it does not exist
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d("door tracker", "Oops! Failed create "
+ "door tracker" + " directory");
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss",
Locale.getDefault()).format(new Date());
File mediaFile = new File(mediaStorageDir.getPath() + File.separator
+ "AddressTrackingReport "+ timeStamp + ".pdf");
InputStream inputStream = null;
OutputStream outputStream = null;
try {
byte[] fileReader = new byte[4096];
long fileSize = body.contentLength();
long fileSizeDownloaded = 0;
inputStream = body.byteStream();
outputStream = new FileOutputStream(mediaFile);
while (true) {
int read = inputStream.read(fileReader);
if (read == -1) {
break;
}
outputStream.write(fileReader, 0, read);
fileSizeDownloaded += read;
Log.d(TAG, "file download: " + fileSizeDownloaded + " of " + fileSize);
}
outputStream.flush();
return true;
} catch (IOException e) {
return false;
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}
} catch (IOException e) {
return false;
}
}
Somebody, please help a solution. This may contain errors Because I am new to it.Thanks.
Your API using form-data as input, So change #Body to #Multipart Type. This will give you a response. Add below snippet inside onResponse()
if (response.isSuccessful()) {
progressDialog.dismiss();
new AsyncTask<Void, Void, Void>() {
boolean writtenToDisk = false;
#Override
protected Void doInBackground(Void... voids) {
try {
writtenToDisk = writeResponseBodyToDisk(AddressTrackingActivity.this,
response.body());
} catch (IOException e) {
Log.w(TAG, "Asynch Excep : ", e);
}
Log.d(TAG, "file download was a success? " + writtenToDisk);
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
if (writtenToDisk) {
String pdfPath = Environment.getExternalStorageDirectory().toString()
+ "/Door Tracker/" + fileName;
Log.d(TAG, "file name : " + fileName);
File file = new File(pdfPath);
Uri bmpUri;
if (Build.VERSION.SDK_INT < 24) {
bmpUri = Uri.fromFile(file);
Log.d(TAG, "bmpUri : " + bmpUri);
} else {
bmpUri = FileProvider.getUriForFile(AddressTrackingActivity.this,
getApplicationContext().getPackageName() + ".provider", file);
Log.d(TAG, "bmpUri : " + bmpUri);
}
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(bmpUri, "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
try {
startActivity(intent);
} catch (ActivityNotFoundException e) {
Log.d(TAG, "ActivityNotFoundException : ", e);
}
}
}
}.execute();
} else {
progressDialog.dismiss();
Toast.makeText(AddressTrackingActivity.this, "Network error, Please retry", Toast.LENGTH_SHORT).show();
Log.d(TAG, "server contact failed");
}
I think this will help you.
String fileName = "";
boolean writtenToDisk = writeResponseBodyToDisk(response.body(),fileName);
if(writtenToDisk){
String pdfPath = Environment.getExternalStorageDirectory().toString() + "/Door Tracker/"+fileName;
File file = new File(pdfPath);
Uri bmpUri;
if (Build.VERSION.SDK_INT < 24) {
bmpUri = Uri.fromFile(file);
} else {
bmpUri = FileProvider.getUriForFile(this,getApplicationContext().getPackageName() + ".provider", file);
}
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(bmpUri, "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
try {
startActivity(intent);
}
catch (ActivityNotFoundException e) {
}
}
Just get the File Name from method writeResponseBodyToDisk :
File mediaFile = new File(mediaStorageDir.getPath() + File.separator
+ "AddressTrackingReport "+ timeStamp + ".pdf");
fileName = mediaFile.getName();
Just Debug and Check your file name is correct.
Related
when I upload db file to server using php and recover that file, the database date in android device explorer is updated. but the contents is not updated. I dont understand...
time is updated but not contents... what's going on? using retrofit2 for upload/download, the result log is success, and the file size is right "4kb". is there anyone? I'm so alone.... because when I ask a question, there is no one who answered to me....
ps : the file permissions are like this "-rw-rw----"
and here is my code to dump downloaded file to original file
private boolean writeResponseBodyToDisk(ResponseBody body) {
try {
// todo change the file location/name according to your needs
File futureStudioIconFile = new File(file.getPath());
InputStream inputStream = null;
OutputStream outputStream = null;
try {
byte[] fileReader = new byte[4096];
long fileSize = body.contentLength();
long fileSizeDownloaded = 0;
inputStream = body.byteStream();
outputStream = new FileOutputStream(futureStudioIconFile);
while (true) {
int read = inputStream.read(fileReader);
if (read == -1) {
break;
}
outputStream.write(fileReader, 0, read);
fileSizeDownloaded += read;
Log.d("TAG", "file download: " + fileSizeDownloaded + " of " + fileSize);
}
outputStream.flush();
return true;
} catch (IOException e) {
return false;
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}
} catch (IOException e) {
return false;
}
}
and here is response about download. please help me....
responseBodyCall = retrofitInterface.download("savelocation");
responseBodyCall.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
Log.d("Success", "success "+response.code());
Log.d("Success", "success "+response.message());
Log.d("Success", "downloaded");
boolean isSuccess = writeResponseBodyToDisk(response.body());
if(isSuccess) Toast.makeText(getApplicationContext(),"Success",Toast.LENGTH_LONG).show();
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.d("failure", "message = " + t.getMessage());
Log.d("failure", "cause = " + t.getCause());
}
});
I am trying to create a separate folder in internal storage of a phone for an app to download files on it. But the folder is not created in the phone. What is the reason? Also I have another issue in my app that is photos are not downloaded when I click thee download button.
Here is the download function
public void download() {
for (MediaModel item : Items) {
if (item.isSelected) {
Log.d("check", "download");
final String url = item.getFullDownloadURL();
BaseDownloadTask task = FileDownloader.getImpl().create(url);
task.setListener(mFileDownloadListener)
.setPath(Environment.getDataDirectory() + "/" + Constants.STORED_FOLDER, true)
.setAutoRetryTimes(1)
.setCallbackProgressTimes(0)
.asInQueueTask()
.enqueue();
if (FileDownloader.getImpl().start(mFileDownloadListener, true)) {
item.setTaskId(task.getId());
item.setStatus(ItemStatus.DOWNLOADING);
Logging.e(TAG, "start download task: " + task.getId());
} else {
item.setTaskId(task.getId());
item.setStatus(ItemStatus.NORMAL);
Logging.e(TAG, "error download task: " + task.getId());
}
}
}
}
In Android studio to use internal Storage First of all add permission in manifest
Like this:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
then to make new directory in internal storage use this line of code:
File sdCardRoot = new File(Environment.getExternalStorageDirectory(), "MyProfile");
if (!sdCardRoot.exists()) {
sdCardRoot.mkdirs();
}
Log.e("check_path", "" + sdCardRoot.getAbsolutePath());
This is my full code:
In this code check directory is exist or not if directory is not exist then create directory
and use asyntask to download images from url
In this example i have use Java Language
Code
MyAsyncTasks asyncTasks = new MyAsyncTasks();
asyncTasks.execute(Imageurl);
and AsyncClass:
class MyAsyncTasks extends AsyncTask<String, String, String> {
File sdCardRoot;
#Override
protected String doInBackground(String... strings) {
HttpURLConnection urlConnection = null;
try {
URL url = new URL(strings[0]);
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
urlConnection.connect();
sdCardRoot = new File(Environment.getExternalStorageDirectory(), "MyProfile");
if (!sdCardRoot.exists()) {
sdCardRoot.mkdirs();
}
Log.e("check_path", "" + sdCardRoot.getAbsolutePath());
String fileName =
strings[0].substring(strings[0].lastIndexOf('/') + 1, strings[0].length());
Log.e("dfsdsjhgdjh", "" + fileName);
File imgFile =
new File(sdCardRoot, fileName);
if (!sdCardRoot.exists()) {
imgFile.createNewFile();
}
InputStream inputStream = urlConnection.getInputStream();
int totalSize = urlConnection.getContentLength();
FileOutputStream outPut = new FileOutputStream(imgFile);
int downloadedSize = 0;
byte[] buffer = new byte[2024];
int bufferLength = 0;
while ((bufferLength = inputStream.read(buffer)) > 0) {
outPut.write(buffer, 0, bufferLength);
downloadedSize += bufferLength;
Log.e("Progress:", "downloadedSize:" + Math.abs(downloadedSize * 100 / totalSize));
}
Log.e("Progress:", "imgFile.getAbsolutePath():" + imgFile.getAbsolutePath());
Log.e(TAG, "check image path 2" + imgFile.getAbsolutePath());
mImageArray.add(imgFile.getAbsolutePath());
outPut.close();
} catch (IOException e) {
e.printStackTrace();
Log.e("checkException:-", "" + e);
}
return null;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
imagecount++;
Log.e("check_count", "" + totalimagecount + "==" + imagecount);
if (totalimagecount == imagecount) {
pDialog.dismiss();
imagecount = 0;
}
Log.e("ffgnjkhjdh", "checkvalue checkvalue" + checkvalue);
}
}
Try This code:
private class DownloadingTask extends AsyncTask<Void, Void, Void> {
File apkStorage = null;
File outputFile = null;
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog=new ProgressDialog(context);
progressDialog.setMessage("Downloading...");
progressDialog.show();
}
#Override
protected void onPostExecute(Void result) {
try {
if (outputFile != null) {
progressDialog.dismiss();
CDToast.makeText(context, context.getResources().getString(R.string.downloaded_successfully), CDToast.LENGTH_SHORT, CDToast.TYPE_SUCCESS).show();
Notification();
vibrateDevice(100);
} else {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
}
}, 3000);
CDToast.makeText(context, context.getResources().getString(R.string.download_failed), CDToast.LENGTH_SHORT, CDToast.TYPE_ERROR).show();
}
} catch (Exception e) {
e.printStackTrace();
//Change button text if an exception occurs
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
}
}, 3000);
Log.e(TAG, "Download Failed with Exception - " + e.getLocalizedMessage());
}
super.onPostExecute(result);
}
#Override
protected Void doInBackground(Void... arg0) {
try {
URL url = new URL(downloadUrl);//Create Download URl
HttpURLConnection c = (HttpURLConnection) url.openConnection();//Open Url Connection
c.setRequestMethod("GET");//Set Request Method to "GET" since we are grtting data
c.connect();//connect the URL Connection
//If Connection response is not OK then show Logs
if (c.getResponseCode() != HttpURLConnection.HTTP_OK) {
Log.e(TAG, "Server returned HTTP " + c.getResponseCode()
+ " " + c.getResponseMessage());
}
//Get File if SD card is present
if (new CheckForSDCard().isSDCardPresent()) {
apkStorage = new File(
Environment.getExternalStorageDirectory() + "/"
+ "New_Folder_Name_Here");
} else
Toast.makeText(context, "Oops!! There is no SD Card.", Toast.LENGTH_SHORT).show();
//If File is not present create directory
if (!apkStorage.exists()) {
apkStorage.mkdir();
Log.e(TAG, "Directory Created.");
}
outputFile = new File(apkStorage, downloadFileName);//Create Output file in Main File
//Create New File if not present
if (!outputFile.exists()) {
outputFile.createNewFile();
Log.e(TAG, "File Created");
}
FileOutputStream fos = new FileOutputStream(outputFile);//Get OutputStream for NewFile Location
InputStream is = c.getInputStream();//Get InputStream for connection
byte[] buffer = new byte[1024];//Set buffer type
int len1 = 0;//init length
while ((len1 = is.read(buffer)) != -1) {
fos.write(buffer, 0, len1);//Write new file
}
//Close all connection after doing task
fos.close();
is.close();
} catch (Exception e) {
//Read exception if something went wrong
e.printStackTrace();
outputFile = null;
Log.e(TAG, "Download Error Exception " + e.getMessage());
}
return null;
}
}
For Checking SD card :
public class CheckForSDCard {
//Check If SD Card is present or not method
public boolean isSDCardPresent() {
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
return true;
}
return false;
}
}
For creating folder
String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Your Folder Name";
File folder = new File(path);
if (!folder.exists()) {
folder.mkdir();
}
also refer to this answer: https://stackoverflow.com/a/35471045/9060917
Update
public void download() {
for (MediaModel item : Items) {
if (item.isSelected) {
File file = new File(getFilesDir(),"Your directory name");
if(!file.exists()){
file.mkdir();
}
try{
Log.d("check", "download");
final String url = item.getFullDownloadURL();
BaseDownloadTask task = FileDownloader.getImpl().create(url);
task.setListener(mFileDownloadListener)
.setPath(file.getAbsolutePath(), true)
.setAutoRetryTimes(1)
.setCallbackProgressTimes(0)
.asInQueueTask()
.enqueue();
}catch (Exception e){
e.printStackTrace();
}
if (FileDownloader.getImpl().start(mFileDownloadListener, true)) {
item.setTaskId(task.getId());
item.setStatus(ItemStatus.DOWNLOADING);
Logging.e(TAG, "start download task: " + task.getId());
} else {
item.setTaskId(task.getId());
item.setStatus(ItemStatus.NORMAL);
Logging.e(TAG, "error download task: " + task.getId());
}
}
}
}
I hope you add these permissions in manifests
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Update
When saving a file to internal storage, you can acquire the appropriate directory as a File by calling method
getFilesDir()
File directory = context.getFilesDir();
File file = new File(directory, filename);
Alternatively, you can call openFileOutput() to get a FileOutputStream that writes to a file in your internal directory. For example, here's how to write some text to a file:
String filename = "myfile";
String fileContents = "Hello world!";
FileOutputStream outputStream;
try {
outputStream = openFileOutput(filename, Context.MODE_PRIVATE);
outputStream.write(fileContents.getBytes());
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
More reference
https://developer.android.com/training/data-storage/files#java
pass the URL of the image you want to download in this method.
/*--Download Image in Storage--*/
public void downloadImage(String URL) {
final Long reference;
downloadManager = (DownloadManager) getActivity().getSystemService(Context.DOWNLOAD_SERVICE);
Uri uri = Uri.parse(URL);
DownloadManager.Request request = new DownloadManager.Request(uri);
request.setTitle("AppName");
request.setDestinationInExternalPublicDir(String.format("%s/%s", Environment.getExternalStorageDirectory(),
getString(R.string.app_name)), "FileName.jpg");
Log.i("myi", "downloadImage: " + request.setDestinationInExternalPublicDir(String.format("%s/%s", Environment.getExternalStorageDirectory(),
getString(R.string.app_name)), "FileName.jpg"));
request.setVisibleInDownloadsUi(true);
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
reference = downloadManager.enqueue(request);
Log.d("download", "Image Download : " + reference);
BroadcastReceiver onComplete = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
try {
Toast.makeText(this, "Image Downloaded Successfully ", Toast.LENGTH_LONG);
} catch (Exception e) {
}
}
};
getApplicationContext().registerReceiver(onComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
}
Add the required permissions to the AndroidManifest.xml file.
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Add requestLegacyExternalStorage for the application.
<application
android:requestLegacyExternalStorage="true">
</application>
Add the following snippet to the MainActivity.java
File f = new File(Environment.getExternalStorageDirectory(), "My folder");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
try {
Files.createDirectory(Paths.get(f.getAbsolutePath()));
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(), e.getLocalizedMessage(), Toast.LENGTH_LONG).show();
}
} else {
f.mkdir();
f.mkdirs();
Toast.makeText(getApplicationContext(), f.getPath(), Toast.LENGTH_LONG).show();
}
Now, the code to trigger the download would be something like:
String url="Here download Url paste";
DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url.toString()));
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI);
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.allowScanningByMediaScanner();
request.setDestinationInExternalPublicDir("/My folder", fileName);
downloadManager.enqueue(request);
I am working on an app in which I want to get image from gallery or camera and then send it to server using multipart. I am able to send picture from gallery to server but when I tried to send image from camera it shows me failure.
// code for the same
// code fro open camera
private void cameraIntent() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, REQUEST_CAMERA);
}
// on activity result
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CAMERA) {
Bitmap thumbnail = (Bitmap) data.getExtras().get("data");
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
thumbnail.compress(Bitmap.CompressFormat.JPEG, 90, bytes);
File destination = new File(Environment.getExternalStorageDirectory(),
System.currentTimeMillis() + ".jpg");
Log.d("TAG", "onActivityResult: "+Uri.fromFile(destination));
FileOutputStream fo;
try {
destination.createNewFile();
fo = new FileOutputStream(destination);
fo.write(bytes.toByteArray());
fo.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
filePath = destination.toString();
if (filePath != null) {
try {
execMultipartPost();
} catch (Exception e) {
e.printStackTrace();
}
} else {
Toast.makeText(getActivity(), "Image not capturd!", Toast.LENGTH_LONG).show();
}
}
// send to server code
private void execMultipartPost() throws Exception {
File file = new File(filePath);
String contentType = file.toURL().openConnection().getContentType();
Log.d("TAG", "file new path: " + file.getPath());
Log.d("TAG", "contentType: " + contentType);
RequestBody fileBody = RequestBody.create(MediaType.parse(contentType), file);
final String filename = "file_" + System.currentTimeMillis() / 1000L;
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("date", "21-09-2017")
.addFormDataPart("time", "11.56")
.addFormDataPart("description", "hello")
.addFormDataPart("image", filename + ".jpg", fileBody)
.build();
Log.d("TAG", "execMultipartPost: "+requestBody);
okhttp3.Request request = new okhttp3.Request.Builder()
.url("http://myexample/api/user/lets_send")
.post(requestBody)
.build();
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, final IOException e) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getActivity(), "nah", Toast.LENGTH_SHORT).show();
}
});
}
#Override
public void onResponse(Call call, final okhttp3.Response response) throws IOException {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
try {
Log.d("TAG", "response of image: " + response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
});
}
// I am getting onFailure executed while try to upload image from camera.
okHttpClient.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, final IOException e) {
As per comments :
Get image from gallery or camera like this :
File mainFile = null;
Bitmap bitmap = (Bitmap) data.getExtras().get("data");
String partFilename = currentDateFormat();
mainFile = storeCameraPhotoInSDCard(bitmap, partFilename);
public String currentDateFormat() {
String currentTimeStamp = null;
try {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HH_mm_ss");
currentTimeStamp = dateFormat.format(new Date());
} catch (Exception e) {
e.printStackTrace();
}
return currentTimeStamp;
}
public File storeCameraPhotoInSDCard(Bitmap bitmap, String currentDate) {
File outputFile = new File(Environment.getExternalStorageDirectory(), "photo_" + currentDate + ".jpg");
try {
FileOutputStream fileOutputStream = new FileOutputStream(outputFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fileOutputStream);
fileOutputStream.flush();
fileOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return outputFile;
}
Use mainFile to send in RequestBody and pass like execMultipartPost(File file)
I am getting a URL in response. I want to download the html of that URL so that user can see it offline also. Its a recyclerView in which each items contain a URL. So when user clicks on the URL of one item it should save it in external disk.
Below is the code:
NewsAdapter:
case R.id.save:
Gson gson = new GsonBuilder()
.setLenient()
.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://www.nytimes.com/")
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
Log.i("Retrofit build", "initiated");
ApiInterface retrofitInterface = retrofit.create(ApiInterface.class);
final Call< ResponseBody > call = retrofitInterface.downloadFileWithDynamicUrlSync("2017/09/13/us/nursing-home-deaths-florida.html");
Log.i("Retrofit req execute", "initiated");
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... voids) {
boolean writtenToDisk = false;
try {
writtenToDisk = writeResponseBodyToDisk(call.execute().body());
} catch (IOException e) {
e.printStackTrace();
}
;
Log.d("success", "file download was a success? " + writtenToDisk);
return null;
}
}.execute();
break;
private boolean writeResponseBodyToDisk(ResponseBody body) {
try {
// todo change the file location/name according to your needs
File futureStudioIconFile = new File(Environment.DIRECTORY_DOWNLOADS + File.separator + "Future Studio Icon.png");
InputStream inputStream = null;
OutputStream outputStream = null;
try {
byte[] fileReader = new byte[4096];
long fileSize = body.contentLength();
long fileSizeDownloaded = 0;
inputStream = body.byteStream();
outputStream = new FileOutputStream(futureStudioIconFile);
while (true) {
int read = inputStream.read(fileReader);
if (read == -1) {
break;
}
outputStream.write(fileReader, 0, read);
fileSizeDownloaded += read;
Log.d("filedownload", "file download: " + fileSizeDownloaded + " of " + fileSize);
}
outputStream.flush();
return true;
} catch (IOException e) {
return false;
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}
} catch (IOException e) {
return false;
}
}
ApiInterface:
// option 2: using a dynamic URL
#Streaming
#GET
Call<ResponseBody> downloadFileWithDynamicUrlSync(#Url String fileUrl);
I am also getting the error:
Failed to invoke public com.squareup.okhttp.ResponseBody() with no args
Can someone tell me how to implement it correctly.
Use URL with domain name to download file.Remove streaming annotation don't need that.
You are not receiving file body as you are not using complete URL.
Create an interface like this
#GET
Call<ResponseBody> downloadFile(#Url String url);
Then use this code :
public void onResponse(Call<ResponseBody> call, Response<ResponseBody>
response)
{
if (response.isSuccessful()) {
String filePath = Utils.downloadFile(response.body(),"filename");
}
}
public String downloadFile(ResponseBody body, String fileName) {
String filePath = null;
try {
int count;
byte data[] = new byte[1024 * 4];
InputStream bis = new BufferedInputStream(body.byteStream(), 1024 * 8);
File storageDir = new File(Environment.getExternalStorageDirectory(), "AppName");
if (!storageDir.exists()) {
storageDir.mkdirs();
}
File outputFile = new File(storageDir, fileName);
OutputStream output = new FileOutputStream(outputFile);
while ((count = bis.read(data)) != -1) {
output.write(data, 0, count);
}
output.flush();
output.close();
bis.close();
filePath = outputFile.getAbsolutePath();
} catch (Exception e) {
e.printStackTrace();
}
return filePath;
}
I try to download file from server and save it in internel storage and then install it.
I downloaded it using retrofit by this code
Call<ResponseBody> call = apiService.getNewVersion();
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call,
Response<ResponseBody> response) {
if (response.isSuccessful() ) {
Log.d("1", "server contacted and has file");
boolean writtenToDisk =
writeResponseBodyToDisk(response.body());
Log.d("2", "file download was a success? " + writtenToDisk);
} else {
Log.d("3", "server contact failed");
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.e("4", "error");
}
});
and I saved it by this code
private boolean writeResponseBodyToDisk(ResponseBody body) {
try {
// todo change the file location/name according to your needs
File futureStudioIconFile = new
File(context.getExternalFilesDir(null) + File.separator + "app-debug.apk");
InputStream inputStream = null;
OutputStream outputStream = null;
try {
byte[] fileReader = new byte[4096];
long fileSize = body.contentLength();
long fileSizeDownloaded = 0;
inputStream = body.byteStream();
outputStream = new FileOutputStream(futureStudioIconFile);
while (true) {
int read = inputStream.read(fileReader);
if (read == -1) {
break;
}
outputStream.write(fileReader, 0, read);
fileSizeDownloaded += read;
Log.d("TAG", "file download: " + fileSizeDownloaded + " of "
+ fileSize);
}
outputStream.flush();
return true;
} catch (IOException e) {
return false;
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}
} catch (IOException e) {
return false;
}
}
its original 4.56MB but it shows 6.08MB in Android storage.
When I open it to install it shows
version N /A size N/ A
and when I try to install it, it shows this parse problem
Do you have any idea to solve this problem?
How to remove extra bytes?
You should make sure that you use HttpResponseMessage.content in your web service method because a normal return will not be a standard size for the file that you want:
[HttpGet]
[Route("api/Depository/DownloadFileFTP")] // /{pass}
public HttpResponseMessage DownloadFileFTP() //string pass
{
HttpResponseMessage result = null;
string ftphost = "*******";
string ftpfilepath = "/app-debug.apk";
byte[] fileData;
string ftpfullpath = "ftp://" + ftphost + ftpfilepath;
using (WebClient request = new WebClient())
{
request.Credentials = new NetworkCredential("**", "****");
fileData = request.DownloadData(ftpfullpath);
}
byte[] bytes = fileData;
result = Request.CreateResponse(HttpStatusCode.OK);
result.Content = new ByteArrayContent(bytes);
result.Content.Headers.ContentDisposition = new
System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
result.Content.Headers.ContentDisposition.FileName = "app.apk";
return result;
}