I have tried to implement over 10-15 different download mechanisms for android java, I have not been able to succeed at all.
I don't care about progress bars or background processes.
I just want one functional download code in fewest lines possible
and I want it to download a binary file (foreground) to the directory in the device wherever it can be accessed as
File pf = new File("filename");
if (pf.exists()) { ... }
Try this (modified from here):
try {
URL url = new URL("http://url.com");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
urlConnection.connect();
//THIS IS WHERE YOU GET THE DIRECTORY TO SAVE TO
File SDCardRoot = Environment.getExternalStorageDirectory();
//THIS IS WHERE YOU WILL SET THE FILE NAME
File file = new File(SDCardRoot,"somefile.txt");
FileOutputStream fileOutput = new FileOutputStream(file);
InputStream inputStream = urlConnection.getInputStream();
//create a buffer...
byte[] buffer = new byte[1024];
int bufferLength = 0;
while ( (bufferLength = inputStream.read(buffer)) > 0 ) {
fileOutput.write(buffer, 0, bufferLength);
}
fileOutput.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
You may also need to add permissions to access the phone directory:
<manifest ...>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
For information on accessing certain folders on the internal directory, see the android developer page: http://developer.android.com/training/basics/data-storage/files.html#WriteInternalStorage
In fact, the solution on that page is also fairly short:
String filename = "myfile";
String string = "Hello world!";
FileOutputStream outputStream;
try {
outputStream = openFileOutput(filename, Context.MODE_PRIVATE);
outputStream.write(string.getBytes());
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
Related
I have an API that provides me with InputStream of a pdf file. And my objective is to allow user to view this file with another pdf viewer application.
In order to acheive this, I copied the InputStream to a pdf file that has been created programmatically. Then I tried to open that pdf file.
However, I'm not able to open the pdf file through my application or file explorer. Drive PDF viewer tells in toast that it cannot open the pdf file, Adobe Acrobat tells that the pdf file cannot be accessed, and Mi PDF reader tells that the pdf is in invalid format.
Here's the code inside onResponse() of OkHttpClient's call:
if (response.isSuccessful()) {
InputStream inputStream = responseBody.byteStream();
runOnUiThread(new Runnable() {
#Override
public void run() {
File file = null;
try {
file = MyFileUtils.createPdfFile(PdfViewActivity.this);
} catch (IOException e) {
e.printStackTrace();
}
MyFileUtils.copyInputStreamToFile(inputStream, file);
String pdfFilePath = file.getAbsolutePath();
openPdf(pdfFilePath);
}
});
}
Here's the method responsible for opening pdf:
private void openPdf(String pdfFilePath) {
Intent pdfViewIntent = new Intent(Intent.ACTION_VIEW);
pdfViewIntent.setDataAndType(Uri.parse(pdfFilePath), "application/pdf");
Intent chooser = Intent.createChooser(pdfViewIntent, "Open this note with");
startActivity(chooser);
finish();
}
I created the pdf using MyFileUtils.createPdfFile() method. Here's how I implemented it:
public static File createPdfFile(Activity associatedActivity) throws IOException {
String timeStamp = new SimpleDateFormat("HHmmss").format(new Date());
String pdfFileName = "PDF_" + timeStamp + "_";
File storageDir = associatedActivity.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS);
Log.d(TAG, "createPdfFile: storageDir: " + storageDir.getAbsolutePath());
return File.createTempFile(
pdfFileName, /* prefix */
".pdf", /* suffix */
storageDir /* directory */
);
}
I copied the InputStream to that file using the following method in MyFileUtils class:
// Copy an InputStream to a File.
public static void copyInputStreamToFile(InputStream in, File file) {
OutputStream out = null;
try {
out = new FileOutputStream(file);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// Ensure that the InputStreams are closed even if there's an exception.
try {
if (out != null) {
out.close();
}
// If you want to close the "in" InputStream yourself then remove this
// from here but ensure that you close it yourself eventually.
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
I've implemented the provider in the following way:
AndroidManifest.xml :
<application>
...
...
...
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.example.xyz.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths" />
</provider>
</application>
file_paths.xml :
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-files-path name="my_images" path="Pictures" />
<external-files-path name="my_documents" path="Documents" />
</paths>
NOTE:
The application has necessary read-write permissions. I've tested it programmatically. I'm not including those codes here because it might not be relevant.
The absolute path of the created pdf file is something like this: /storage/emulated/0/Android/data/<package name>/files/Documents/PDF_164257_4832620770047519807.pdf
You need to download on device download directory.
Your directory is not visible to other's application that's by its not opening.
Only your application can use this directory.
Not able to comment due to less reputation
I am not sure if this helps but I see that the file you copy the InputStream into seems not be closed before you call openPdf(pdfFilePath); which means the pdf viewers get trouble opening it either because it is blocked or not all content has been written into the file.
This question already has answers here:
What exactly does URLConnection.setDoOutput() affect?
(4 answers)
Closed 12 months ago.
This is the code I wrote for downloading image from url, but receving response code 400 with java.io.FilenotFoundException
#Override
protected Void doInBackground(String... strings) {
try {
URL url = new URL(strings[0]);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestProperty("User-Agent", "Mozilla/5.0
(Macintosh; U; Intel Mac OS X 10.4; en-US; rv:1.9.2.2)
Gecko/20100316 Firefox/3.6.2");
con.setRequestMethod("GET");
con.setDoOutput(true);
con.connect();
File file = Environment.getExternalStorageDirectory();
File f1 = new File(file, "_Url download");
if(!f1.exists()){
f1.mkdir();
}
fileName = System.currentTimeMillis() + ".jpg";
File f2 = new File(f1, fileName);
f2.createNewFile();
InputStream er = con.getErrorStream();
Log.i("ErrorCode", con.getResponseCode()+"");
Log.i("ErrorMessage", con.getResponseMessage());
Log.i("ErrorStream", er+"");
InputStream in = con.getInputStream();
FileOutputStream out = new FileOutputStream(f2);
byte[] buffer = new byte[1024];
int len;
System.out.println(Arrays.toString(buffer));
while((len = in.read(buffer, 0, 1024)) > 0) {
out.write(buffer, 0, len);
}
out.close();
in.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (ProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
Log.i("IOException", e.toString());
}
return null;
}
LOG
2021-06-26 09:26:25.532 26760-26890/com.example.urldownload I/ErrorCode: 400
2021-06-26 09:26:25.533 26760-26890/com.example.urldownload I/ErrorMessage: Bad Request
2021-06-26 09:26:25.533 26760-26890/com.example.urldownload I/Errorstream: buffer(com.android.okhttp.internal.http.Http1xStream$FixedLengthSource#fbb2c70).inputStream()
2021-06-26 09:26:25.534 26760-26890/com.example.urldownload I/IOException: java.io.FileNotFoundException: https://instagram.fidr1-1.fna.fbcdn.net/v/t51.2885-15/e35/190664842_184685183538740_5039921250568173600_n.jpg?tp=1&_nc_ht=instagram.fidr1-1.fna.fbcdn.net&_nc_cat=108&_nc_ohc=RrEU4lTwYCwAX-vgVQ4&edm=AABBvjUBAAAA&ccb=7-4&oh=3ac34be54793fa59134380fd9e0bd617&oe=60DCB7E6&_nc_sid=83d603
Manifest
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>
Image of the file where the image is being saved
For more details look at this image
what should I do to resolve this error or is there any better way to do this
I got my mistake.
Thank you everyone for sharing your ideas
con.setDoOutput(true); is a POST method
And it doesn't fetches any data
con.setDoOutput(true); should not be used.
Use picasso to save images in external storage, you can do something like following
private Target mTarget = new Target() {
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
// Perform simple file operation to store this bitmap
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
}
...
Picasso.with(this).load("url").into(mTarget);
Here "Target" is a class provided by picasso, and it has very simple method to understand...
This is a easy way to do
It is hard to figure out what might be causing the error due to lack of provided code. My best guess would be to use DownloadManager instead of AsyncTask.
The download manager is a system service that handles long-running HTTP downloads. Clients may request that a URI be downloaded to a particular destination file. The download manager will conduct the download in the background, taking care of HTTP interactions and retrying downloads after failures or across connectivity changes and system reboots. (https://developer.android.com/reference)
I am trying to download a jar file from my server and put it into the AVD internal memory but it's not working. I tried this code in Java and it's working perfectly.
try
{
URL url = new URL(host);
URLConnection connection = url.openConnection();
int fileLength = connection.getContentLength();
if (fileLength == -1)
{
return;
}
input = connection.getInputStream();
String fileName = url.getFile().substring(url.getFile().lastIndexOf('/') + 1);
writeFile = new FileOutputStream(fileName);
byte[] buffer = new byte[1024];
int read;
while ((read = input.read(buffer)) > 0)
writeFile.write(buffer, 0, read);
writeFile.flush();
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
try
{
writeFile.close();
input.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
I add the following permission into my manifest.xml
<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" />
<uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
But on connection.getContentLength();, I got a NullPointerException return
I tried with HttpURLConnection and JarURLConnection, add a connection.connect() just after openConnection(), using DownloadManager but it can only download into external storage.
Maybe with HttpClient ? AndroidHttpClient ? But Android support recommend using HttpURLConnection for applications targeted at Gingerbread and higher.
There's a cumbersome but straightforward approach:
1. Use DownloadManager to get a JAR you need (store it in external storage);
2. Move that JAR from external storage to internal one.
I created a raw folder inside res (res/raw) and I also created my_text_file.txt file.
Now I want to write something in this file.
I wrote some code but I cannot write (for example) a simple string.
This is my code.
If anyone knows what is wrong in my code, please help me
try {
FileOutputStream fos = openFileOutput("my_text_file.txt",
Context.MODE_PRIVATE);
OutputStreamWriter osw = new OutputStreamWriter(fos);
osw.write("17");
osw.flush();
osw.close();
} catch (java.io.IOException e) {
// do something if an IOException occurs.
}
You can read your file but not alter the file on the resources folder.
What you can do is to save the file in the external storage then start to alter the file.
Dont forget to set the permission:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
You shouldn't write to resource files. It exist to store data that you put here before compilation. If you want to save some information in file, during runtime you can do something like this:
public static void writeToFile(String fileName, String encoding, String text) {
Writer writer = null;
try {
writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName), encoding));
writer.write(text);
} catch (IOException ex) {
Log.e(TAG, "", ex);
} finally {
try {
writer.close();
} catch (Exception ex) {
}
}
}
To find path to SD card you can use this method:
Environment.getExternalStorageState()
So you can use this method like this:
writeToFile(Environment.getExternalStorageState() + "/" + "my_text_file.txt", "UTF-8", "my_text");
And don't forgot to set permission
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
UPD:
You shouldn't use SD card to store some secure information! More information here.
To write data that will be available only for you application, use this code:
public static void writeToInternalFile(String fileName, String text) {
FileOutputStream fos = openFileOutput(fileName, Context.MODE_PRIVATE);
fos.write(text.getBytes());
fos.close();
}
To read from this file:
public static String readFromInternalFile(String fileName) {
FileInputStream fis = openFileInput(, Context.MODE_PRIVATE);
StringBuilder sb = new StringBuilder();
int ch;
while((ch = fis.read()) != -1){
sb .append((char)ch);
}
return sb.toString();
}
I have make an application in which I require to download an image from a given link . Its showing no errors an no error messages in logcat. Following is my code
public Drawable getImage(String ImagePath,String fileName) {
Log.v("download", "image downloading from net");
boolean bin = getBinaryWebFile(ImagePath,fileName);
Drawable draw = Drawable.createFromPath(SavePath+fileName); //..........(1)
return draw;
}//getImage ends here*/
private boolean getBinaryWebFile(String inURL, String filename) {
File file = new File(SavePath,filename);
try {
URL url = new URL(inURL);
HttpURLConnection con = (HttpURLConnection)url.openConnection();
con.setRequestMethod("GET");
con.setDoOutput(true);
con.connect();
InputStream is = con.getInputStream();
FileOutputStream fos = new FileOutputStream(file);
BufferedOutputStream bout = new BufferedOutputStream(fos,1024);
byte[] data =new byte[1024];
int x = 0;
while((x=is.read(data,0,1024))>=0){
bout.write(data,0,x);
}
fos.flush();
bout.flush();
fos.close();
bout.close();
is.close();
return true;
} catch (MalformedURLException e) {
Log.d("PowerSaver","getBinaryWebFile->MalformedURLException: "+e.getMessage());
//e.printStackTrace();
} catch (IOException e) {
Log.d("PowerSaver","getBinaryWebFile->I/O exception: "+e.getMessage());
}
return false;
}//getbinarywebfile ends here
On debugging everything is running fine and at last I am getting draw as null (commented as 1) . I have even written the following permmission in manifest .
<uses-permission
android:name = "android.permission.INTERNET"/>
<uses-permission
android:name = "android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission
android:name = "android.permission.ACCESS_WIFI_STATE" />
<uses-permission
android:name = "android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission
android:name = "android.permission.READ_PHONE_STATE"/>
still getting null in draw which is referenced as comment 1.
This code works for me:
private static long DownloadFromUrl(Context context, URL fileUrl,
String fileName) throws Exception { // this is the downloader method
try {
URL myFileUrl = null;
myFileUrl = fileUrl;
// *** Internet connection
HttpURLConnection conn = (HttpURLConnection) myFileUrl
.openConnection();
conn.setDoInput(true);
conn.connect();
// int length = conn.getContentLength();
// int[] bitmapData =new int[length];
// byte[] bitmapData2 =new byte[length];
InputStream is = conn.getInputStream();
// decodificar la imagen de internet en bmImg
Bitmap bmImg = BitmapFactory.decodeStream(is);
// ***Save in the the SD
FileOutputStream out = new FileOutputStream(
<path + filename>);
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) > 0) {
out.write(buffer, 0, len);
tam += len;
}
is.close();
// Save using the selected format and quality
bmImg.compress(Bitmap.CompressFormat.PNG,
<quality>, out);
out.flush();
out.close();
// tam=bmImg.getByteCount();
bmImg.recycle();
return tam;
} catch (IOException e) {
// showErrorMessage(context, "Error downloading");
e.printStackTrace();
return 0;
}
}
Are you running your app inside the emulator? Make sure it has a proper internet connection. Sometimes the emulator can loose internet connectivtiy, especially when you're changing networks without restarting the emulator.