saving downloaded file to internal storage java/android fails - java

I have an app who has to download some generated images (PNG).
I tried the standard approach ImageDownloader extends AsyncTask, doInBackground() retrieves the image and the onPostExecute() will try to save it to internal image.
(Part of the) code is below:
public class HandleImages extends AppCompatActivity {
String filename = "";
public boolean saveImageToInternalStorage(Bitmap image) {
try {
FileOutputStream fos = openFileOutput(filename, Context.MODE_PRIVATE);
image.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.close();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
public Bitmap retrieveImage(String url){
ImageDownloader task = new ImageDownloader();
Bitmap image = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
try {
image = task.execute(url).get();
} catch (InterruptedException e) {
MainActivity.debb("InterruptedException - " + e.getMessage() + " in " + new Object(){}.getClass().getEnclosingMethod().getName());
e.printStackTrace();
} catch (ExecutionException e) {
MainActivity.debb("ExecutionException - " + e.getMessage() + " in " + new Object(){}.getClass().getEnclosingMethod().getName());
e.printStackTrace();
}
return image;
}
public class ImageDownloader extends AsyncTask<String, Void, Bitmap> {
#Override
protected Bitmap doInBackground(String... urls) {
try {
String[] filenames = urls[0].split("/");
filename = filenames[filenames.length-1] + ".jpg";
URL url = new URL(urls[0]);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.connect();
InputStream inputStream = connection.getInputStream();
return BitmapFactory.decodeStream(inputStream);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
if (bitmap != null)
saveImageToInternalStorage(bitmap);
}
}
}
and the error that I get is: java.lang.NullPointerException: Attempt to invoke virtual method 'java.io.FileOutputStream android.content.Context.openFileOutput(java.lang.String, int)' on a null object reference.
It seems that the FileOutputStream fos = openFileOutput(..) fails, but have no idea why.
Also tried to prepend a path (sdCard.getPath() + "/" +) to the filename. As expected it did not make any difference.
Images are ok, I can see them in the browser. Also tried with uploaded images - instead of the generated ones, same result.
This is pretty odd, does anyone have any idea?
Thanks!

private String saveToInternalStorage(Bitmap bitmapImage){
ContextWrapper cw = new ContextWrapper(getApplicationContext());
// path to /data/data/yourapp/app_data/imageDir
File directory = cw.getDir("imageDir", Context.MODE_PRIVATE);
// Create imageDir
File mypath=new File(directory,"profile.jpg");
FileOutputStream fos = null;
try {
fos = new FileOutputStream(mypath);
// Use the compress method on the BitMap object to write image to the OutputStream
bitmapImage.compress(Bitmap.CompressFormat.PNG, 100, fos);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return directory.getAbsolutePath();
}
Hope this function helps you. If this doesn't help feel free to ask

Related

Android: Saving .png from URL into app internal storage

I'm relatively new to android, and I'm trying to modify an android app such that it downloads a profile picture (preferably in PNG) from a URL, and saves it in the com.companyName.AppName.whatever/files. It should be noted that the app was initially created in Unity, and just built and exported.
Here's my initial code:
URL url = null;
try {
url = new URL(playerDO.getProfileURL());
} catch (MalformedURLException e) {
e.printStackTrace();
}
InputStream input = null;
try {
input = url.openStream();
} catch (IOException e) {
e.printStackTrace();
}
String fileName = playerDO.getId() + ".png";
FileOutputStream outputStream = null;
try {
outputStream = openFileOutput(fileName, Context.MODE_PRIVATE);
byte[] buffer = new byte[256];
int bytesRead = 0;
while ((bytesRead = input.read(buffer, 0, buffer.length)) >= 0) {
outputStream.write(buffer, 0, bytesRead);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
outputStream.close();
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
EDIT: Here's my other code, as suggested by #Ashutosh Sagar
InputStream input = null;
Bitmap image = null;
try {
input = url.openStream();
image = BitmapFactory.decodeStream(input);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
String fileName = playerDO.getId() + ".png";
FileOutputStream outputStream = null;
File myDir = getFilesDir();
try {
Log.wtf("DIRECTORY", myDir.toString());
File imageFile = new File(myDir, fileName);
if (!imageFile.exists()){
imageFile.createNewFile();
Log.wtf("ANDROID NATIVE MSG: WARN!", "File does not exist. Writing to: " + imageFile.toString());
}
outputStream = new FileOutputStream(imageFile, false);
image.compress(Bitmap.CompressFormat.PNG, 90, outputStream);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
outputStream.close();
input.close();
} catch (IOException e) {
e.printStackTrace();
Log.wtf("AWWW CRAP", e.toString());
}
}
(It doesn't write either).
Unfortunately, I've had several problems with this. My primary issue is that when it (on the cases that it does) runs, it actually doesn't save anything. I'll go and check com.companyName.AppName.whatever/files directory only to find no such .png file. I will also need it to overwrite any existing files of the same name, which is hard to check when it doesn't work.
My secondary issue is that it fails to take into account delays in internet connection. Although I've put in enough try-catch clauses to stop it from crashing (as it used to), the end result is that it also doesn't save.
How can I improve upon this? Anything I'm missing?
EDIT:
Printing out the directory reveals it should be in:
/data/user/0/com.appName/files/5965e9e4a0f0463853016e2b.png
However, using ES File explorer, the only thing remotely close to that is
emulated/0/Android/data/com.appName/files/
Are they the same directory?
try this first get bitmap image from url
Bitmap mIcon11 = null;
try {
InputStream in = new java.net.URL(url).openStream();
mIcon11 = BitmapFactory.decodeStream(in);
} catch (Exception e) {
Log.d("Error", e.getStackTrace().toString());
}
and to save bitmap image please check the ans of GoCrazy
Try this
void getImage(String string_url)
{
//Generate Bitmap from URL
URL url_value = new URL(string_url);
Bitmap image =
BitmapFactory.decodeStream(url_value.openConnection().getInputStream());
//Export File to local Directory
OutputStream stream = new FileOutputStream("path/file_name.png");
/* Write bitmap to file using JPEG or PNG and 80% quality hint for JPEG. */
bitmap.compress(CompressFormat.PNG, 80, stream);
stream.close();
}

Load image as a File

How can I load an image ".jpg for example" as a File ?
To be precise this file was saved using :
public static void saveFile(Context context, Bitmap bitmap, String picName) {
FileOutputStream fileOutputStream;
try {
fileOutputStream = context.openFileOutput(picName, Context.MODE_PRIVATE);
bitmap.compress(Bitmap.CompressFormat.JPEG, 30, fileOutputStream);
fileOutputStream.close();
} catch (FileNotFoundException e) {
Log.d(TAG, "file not found");
e.printStackTrace();
} catch (IOException e) {
Log.d(TAG, "io exception");
e.printStackTrace();
}
}
So I only have the name as reference
I tried that :
public static Bitmap loadBitmap(Context context, String picName) {
Bitmap bitmap = null;
FileInputStream fileInputStream;
try {
fileInputStream = context.openFileInput(picName);
bitmap = BitmapFactory.decodeStream(fileInputStream);
fileInputStream.close();
} catch (FileNotFoundException e) {
Log.d(TAG, "file not found");
e.printStackTrace();
} catch (IOException e) {
Log.d(TAG, "io exception");
e.printStackTrace();
}
return bitmap;
}
It works but I need it to be a file
If you wish to work with File objects, I recommend that you do so consistently. Use getFilesDir() or getCacheDir() as the base for building a File of where you want the file to go (e.g., new File(getCacheDir(), picName)). Then, use FileOutputStream and FileInputStream for your I/O, replacing openFileOutput() and openFileInput().

Downloading images from AWS gives me corrupt files

I'm trying to download images that are hosted on Amazon Web Services. My methods work fine on any other host, but downloading an image off this url for example http://s3-eu-west-1.amazonaws.com/static.melkweg.nl/uploads/images/scaled/event_header/18226 is giving me trouble. It does download, but the file is only 49kb big and cannot be opened.
I've tried different methods such as Apache's FileUtils copyURLToFile, BufferedInputStream, ImageIO, etc. Some throw errors, most just download a corrupt file.
Here are the methods I've tried:
public static void downloadApache(String imageurl, String target)
{
try
{
File file = new File(target);
URL url = new URL(imageurl);
FileUtils.copyURLToFile(url, file);
}
catch(Exception e)
{
System.err.println("[3]Something went wrong.");
}
}
public static void downloadImage(String imageurl, String name)
{
try
{
URL url = new URL(imageurl);
InputStream in = new BufferedInputStream(url.openStream());
OutputStream out = new BufferedOutputStream(new FileOutputStream(name));
for ( int i; (i = in.read()) != -1; ) {
out.write(i);
}
in.close();
out.close();
}
catch(Exception e)
{
e.printStackTrace();
System.err.println("[0]Something went wrong.");
}
}
public static void downloadImageIO(String imageurl, String target)
{
try
{
URL url = new URL(imageurl);
BufferedImage image = ImageIO.read(url);
ImageIO.write(image, "jpg", new File(target));
}
catch(Exception e)
{
e.printStackTrace();
System.err.println("[1]Something went wrong.");
}
}
public static void downloadImageCopy(String imageurl, String target)
{
try
{
try (InputStream in = new URL(imageurl).openStream()) {
Files.copy(in, Paths.get(target), StandardCopyOption.REPLACE_EXISTING);
}
}
catch(Exception e)
{
e.printStackTrace();
System.err.println("[2]Something went wrong.");
}
}
And here's the main method if that is of any interest
public static void main(String[] args)
{
String imageurl = "http://s3-eu-west-1.amazonaws.com/static.melkweg.nl/uploads/images/scaled/event_header/18226";
String name = "downloaded_image.jpg";
String target = "C:/Users/Robotic/Downloads/" + name;
Download.downloadImage(imageurl, name);
Download.downloadImageCopy(imageurl, target);
Download.downloadImageIO(imageurl, target);
Download.downloadApache(imageurl, target);
}
Thanks in advance.
The file that you are getting from S3 is gzip compressed, you need to decompress it before trying to read it.
$ wget http://s3-eu-west-1.amazonaws.com/static.melkweg.nl/uploads/images/scaled/event_header/18226
$ file 18226
18226: gzip compressed data, from Unix
As pointed out in the earlier answer, it is in gzip format.
You can use the following method and get the file unzipped
public static void downloadApache(String imageurl, String target) {
try {
File file = new File(target+".gzip");
URL url = new URL(imageurl);
FileUtils.copyURLToFile(url, file);
byte[] buffer = new byte[1024];
try {
java.util.zip.GZIPInputStream gzis = new java.util.zip.GZIPInputStream(new FileInputStream(file));
FileOutputStream out = new FileOutputStream(target);
int len;
while ((len = gzis.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
gzis.close();
out.close();
} catch (IOException ex) {
ex.printStackTrace();
}
} catch (Exception e) {
System.err.println("[3]Something went wrong.");
}
}

How to write html to a file in android

I know this has been asked a few times here, but I'm not sure which way I should go. This code downloads the html file okay, but I get an IOException when trying to write the html to a file. I've tried many suggestions on sof, but none seem to work for me and I'm at a loss as it seems it should be working.
class Downloader extends AsyncTask<URL, Void, Void> {
String site = getResources().getString(R.string.sched_hd_url);
File sdCard = Environment.getExternalStorageDirectory();
File dir = new File(sdCard.getAbsolutePath() + "/directory/");
File file = new File(dir, "file.html");
#Override
protected Void doInBackground(URL... urls) {
try {
URL url = new URL(site);
URLConnection yc = url.openConnection();
BufferedInputStream in = new BufferedInputStream(new URL(site).openStream());
OutputStream out = new FileOutputStream(file);
int total = 0;
int count;
byte data1[] = new byte[1024];
while ((count = in.read(data1)) != -1) {
out.write(data1);
total += count;
}
in.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(Void result) {
progress.setVisibility(View.INVISIBLE);
finish();
}
}
I run this code and no file appears in the directory that I specified. The directory already exists, and I do have the permissions in my manifest. Any suggestions would be greatly appreciated.
So my problem was a couple of things. First, I want to thank those that commented. In my question, I did neglect to put in the out.close(); method. When that didn't work, I was looking at the string which held the URL I wanted to use. That had errors in it. This fixed the download problem, but I wanted to download from a place where the .html file was not in the URL (example: http://www.example.com/ instead of http://www.example.com/index.html). It worked for the latter but not the former. So instead of using URLConnection I used HttpURLConnection. Here is my working code:
class Downloader extends AsyncTask<URL, Void, Void> {
String site = getResources().getString(R.string.sched_hd_url);
File sdCard = Environment.getExternalStorageDirectory();
File dir = new File(sdCard.getAbsolutePath() + "/directory/");
File file = new File(dir, "file.html");
#Override
protected Void doInBackground(URL... uri) {
FileOutputStream out = null;
if (file.exists()) {
try {
file.delete();
file.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
URL url = new URL(site);
HttpURLConnection yc = (HttpURLConnection) url.openConnection();
BufferedInputStream in = new BufferedInputStream(
new URL(site).openStream());
out = new FileOutputStream(file);
int total = 0;
int count;
byte data1[] = new byte[1024];
while ((count = in.read(data1)) != -1) {
out.write(data1);
total += count;
}
in.close();
out.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(Void result) {
progress.setVisibility(View.INVISIBLE);
finish();
}
}
Also another error in my question was in regards to no implementation checking to see if the file had already existed. Thanks again for the help.

Writing/Reading gif internal storage

I'm trying to load a gif from a url to be displayed in an Imageview, store it in the internal storage and then later read it again. But it refuses to either store the image or reading it, not sure which one because I get no exceptions. Loading the image to the imageview works. The first method below (loadImage())
public Bitmap loadImage(String url){
Bitmap bm = null;
URL request;
try {
if(url!=null){
request = new URL(url);
InputStream is = request.openStream();
bm = BitmapFactory.decodeStream(is);
is.close();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return bm;
}
public String writeGifToInternalStorage (Bitmap outputImage) {
try {
String fileName = String.valueOf(Calendar.getInstance().getTimeInMillis());
ByteBuffer byteBuffer = ByteBuffer.allocate(outputImage.getByteCount());
outputImage.copyPixelsToBuffer(byteBuffer);
byteBuffer.flip();
byte[] data = new byte[byteBuffer.limit()];
byteBuffer.get(data);
FileOutputStream fos = ctx.openFileOutput(fileName, Context.MODE_PRIVATE);
fos.write(data);
fos.close();
return fileName;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public Bitmap readFileFromInternalStorage(String filename) {
if (filename == null) return null;
FileInputStream fis;
try {
fis = ctx.openFileInput(filename);
return BitmapFactory.decodeStream(fis);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return null;
}
Any ideas of whats wrong?
Your method readFileFromInternalStorage read an encoded image from the file system. This image file should be what you receive from the server.
For that, you need to save the image when you receive it from the server, for example like so:
InputStream is = new BufferedInputStream(request.openStream());
String fileName = String.valueOf(Calendar.getInstance().getTimeInMillis());
FileOutputStream fos = ctx.openFileOutput(fileName, Context.MODE_PRIVATE);
byte[] buffer = new byte[1024];
int red = 0;
while ((red = is.read(buffer)) != -1) {
fos.write(buffer,0, red);
}
fos.close();
is.close();
Then, your image is saved to the disk, and you can open it using your readFileFromInternalStorage method.
Also, if you use HttpClient instead of URL, I wrote a one-liner for downloading a file: Android download binary file problems

Categories

Resources