Save Image from res/drawable to Image Gallery Android - android

I want to Save Image from res/drawable to Image Gallery. I am using following code but it is doing nothing.
What is the wrong with my code ? String Drawable stands for Image Name which is there in drawable folder.
File direct = new File(Environment.getExternalStorageDirectory()
+ "/Images");
if (!direct.exists()) {
direct.mkdirs();
}
ByteArrayOutputStream bos = null;
FileOutputStream fos = null;
try {
Bitmap bitmap = BitmapFactory.decodeResource(
context.getResources(),
context.getResources().getIdentifier(
"#drawable/" + Drawable, "drawable",
context.getPackageName()));
bos = new ByteArrayOutputStream();
bitmap.compress(CompressFormat.JPEG, 95, bos);
byte[] bitmapdata = bos.toByteArray();
fos = new FileOutputStream(direct + "/" + "IMG-" + CurrentDateTime
+ ".jpg");
fos.write(bitmapdata);
} catch (Exception e) {
Log.e("Internal Image Save Error->", e.toString());
} finally {
try {
if (bos != null) {
bos.close();
}
if (fos != null) {
fos.close();
fos.flush();
}
} catch (IOException ignored) {
Log.e("Internal Image Save Error->", ignored.toString());
}
}
I just found that it is saving image but It is taking some time like 10 mins.
Copy Image from Drawable to Gallery : It is giving File Not Found Exception on Input Stream. String Drawable is image name, i.e. data1
public static void downloadInternalImage(String Drawable, Context context) {
Toast.makeText(context, "Downloading Image...\nPlease Wait.",
Toast.LENGTH_LONG).show();
File direct = new File(Environment.getExternalStorageDirectory()
+ "/Images");
if (!direct.exists()) {
direct.mkdirs();
}
InputStream input = null;
OutputStream output = null;
try {
input = new FileInputStream("android.resource://"
+ context.getPackageName() + "/drawable/" + Drawable + "");
output = new FileOutputStream(direct + "/" + "IMG-"
+ CurrentDateTime + ".jpg");
byte[] buf = new byte[1024];
int len;
while ((len = input.read(buf)) > 0) {
output.write(buf, 0, len);
}
Toast.makeText(context, "Image Saved.", Toast.LENGTH_LONG).show();
} catch (Exception e) {
Log.e("Internal Image Save Error->", e.toString());
Toast.makeText(context,
"Couldn't Save Image.\nError:" + e.toString() + "",
Toast.LENGTH_LONG).show();
} finally {
try {
if (input != null) {
input.close();
}
if (output != null) {
output.close();
}
} catch (IOException ignored) {
Log.e("Internal Image Save Error->", ignored.toString());
Toast.makeText(
context,
"Couldn't Save Image.\nError:" + ignored.toString()
+ "", Toast.LENGTH_LONG).show();
}
}
}

Related

How to properly extract files (out of memory)?

At start up of my app I want to extract my images (if they does not exists) from drawable folder to internal app folder to use later with FileProvider. Images have dimensions 2000*2000 and average size 380kb, format png.
Those images are not to be displayed (smaller ones are used to display). They are only for file sharing and I have to keep their original size.
I get out of memory at calling
Bitmap bm = BitmapFactory.decodeResource(getResources(), imageResID);
Code
private void extractImages() {
TypedArray imgs = getResources().obtainTypedArray(R.array.smile_list_share);
File imagePath = new File(getFilesDir(), "images");
File checkImage;
for (int i = 0; i < imgs.length(); i++) {
int imageResID = imgs.getResourceId(i, 0);
if (imageResID > 0) {
String name = getResources().getResourceEntryName(imageResID);
checkImage = new File(imagePath, name + ".png");
if (!checkImage.exists()) {
Bitmap bm = BitmapFactory.decodeResource(getResources(), imageResID);
boolean b = saveBitmapToFile(imagePath, name + ".png", bm, Bitmap.CompressFormat.PNG, 100);
Log.e("mcheck","saved "+b+", file "+name);
Log.e("mcheck", "file does not exists " + name);
} else {
Log.e("mcheck", "file exists " + name);
}
} else {
Log.e("mcheck", "ERROR " + i);
}
}
imgs.recycle();
}
public boolean saveBitmapToFile(File dir, String fileName, Bitmap bm,
Bitmap.CompressFormat format, int quality) {
File imageFile = new File(dir, fileName);
FileOutputStream fos = null;
try {
fos = new FileOutputStream(imageFile);
bm.compress(format, quality, fos);
bm.recycle();
fos.close();
return true;
} catch (IOException e) {
Log.e("app", e.getMessage());
if (fos != null) {
try {
fos.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
return false;
}
You have to call recycle on your bitmap object everytime you are done with it.
Here is a good guide on how to manipulate bitmaps efficiently
https://developer.android.com/training/displaying-bitmaps/load-bitmap.html
I found that I dont need to create bitmap object at all. It is possible to obtaine intput stream from getResourses directly.
public boolean saveBitmapToFile(File dir, String fileName, int imageResourse) {
File imageFile = new File(dir, fileName);
FileOutputStream fos = null;
InputStream inputStream = null;
try {
fos = new FileOutputStream(imageFile);
inputStream = getResources().openRawResource(imageResourse);
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
inputStream.close();
fos.close();
return true;
} catch (IOException e) {
Log.e("app", e.getMessage());
if (fos != null) {
try {
fos.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
return false;
}

File saving outputstream on android

I am making an android apps that can take photos. I have written some codes to save the photos taken by the app. The directory that I want to save the file is in the internal storage and in the folder named DCIM. However, the app crashes everytime I tried to save the photo. Below is my code:
FileOutputStream outStream = null;
try {
outStream = new FileOutputStream(String.format(
"sdcard/DCIM/jgjk.jpg", System.currentTimeMillis()));
outStream.write(data);
outStream.close();
Log.d("Log", "onPictureTaken - wrote bytes: " + data.length);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
Is there anything wrong with the code?
This will work fine
Getting Bitmap in onActivityResult
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
if(requestCode==PIC_CROP)
{
if(resultCode==RESULT_OK)
{
Bundle extras = data.getExtras();
if (extras != null) {
Bitmap bmp = extras.getParcelable("data");
savePhoto(bmp);
}
}
}
}
public void savePhoto(Bitmap bmp)
{
dir = Environment.getExternalStorageDirectory().toString() + "/DCIM/";
File newdir = new File(dir);
newdir.mkdirs();
FileOutputStream out = null;
//file name
Calendar c = Calendar.getInstance();
String date = fromInt(c.get(Calendar.MONTH))
+ fromInt(c.get(Calendar.DAY_OF_MONTH))
+ fromInt(c.get(Calendar.YEAR))
+ fromInt(c.get(Calendar.HOUR_OF_DAY))
+ fromInt(c.get(Calendar.MINUTE))
+ fromInt(c.get(Calendar.SECOND));
File imageFileName = new File(newdir, "crop_"+date.toString() + ".jpg");
try
{
out = new FileOutputStream(imageFileName);
bmp.compress(Bitmap.CompressFormat.JPEG, 100, out);
out.flush();
out.close();
out = null;
} catch (Exception e)
{
e.printStackTrace();
}
}
public String fromInt(int val)
{
return String.valueOf(val);
}

DataInputStream read(byte[] buffer) is returned irrelevant data

How to receive original content and file name from server side code.
Client Code
public void send1(Socket socket)
{
try
{
dataOutputStream = new DataOutputStream(socket.getOutputStream());
File file = new File(Environment.getExternalStorageDirectory().toString() + "/" + "temp.txt");
FileInputStream fis = new FileInputStream(file);
//write file length
dataOutputStream.writeLong(file.length());
Log.i("File Size", "" + file.length());
//write file names
dataOutputStream.writeUTF(file.getName());
Log.i("File Name", "" + file.getName());
//write file to dos
byte[] buf = new byte[4092];
int n = 0;
while((n = fis.read(buf)) != -1)
{
Log.i("length bytes", "" + n);
dataOutputStream.write(buf, 0, n);
}
dataOutputStream.flush();
dataOutputStream.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
File Name as temp.txt and Content as Hello
Server Code
public void receive1(Socket socket)
{
try
{
inputStream = socket.getInputStream();
dataInputStream = new DataInputStream(inputStream);
File file = new File(Environment.getExternalStorageDirectory().toString() + "/" + "test.txt");
FileOutputStream fos = new FileOutputStream(file);
int n = 0;
byte[] buf = new byte[4092];
//read file name
/*String fileName = "";
try
{
fileName = dataInputStream.readUTF();
}
catch (Exception e)
{
e.printStackTrace();
}
Log.i("File Name", "" + fileName);*/
//read file size
long fileSize = 0;
try
{
fileSize = dataInputStream.readLong();
}
catch (Exception e)
{
e.printStackTrace();
}
Log.i("File Size", "" + fileSize);
//read file
while((n = dataInputStream.read(buf)) != -1)
{
Log.i("length bytes", "" + n);
fos.write(buf, 0, n);
}
fos.flush();
fos.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
File Name as test.txt and Content as temp.txtHello.
In this test.txt file, contains temp.txt. I am not getting file name from dataInputStream.readUTF().
Where I mistaken code...
If I called readUTF() method, then I am getting the Exception
Exception as
java.io.EOFException
at libcore.io.Streams.readFully(Streams.java:83)
at java.io.DataInputStream.readFully(DataInputStream.java:99)
at java.io.DataInputStream.decodeUTF(DataInputStream.java:178)
at java.io.DataInputStream.decodeUTF(DataInputStream.java:173)
at java.io.DataInputStream.readUTF(DataInputStream.java:169)
You wrote the Long before the String in the inputStream of the send method. What you did in the server code is that you are expecting to recieve String before the Long which in reserved on what you did in your send method.
solution:
switch reading long first then string
sample:
//read file size
long fileSize = 0;
try
{
fileSize = dataInputStream.readLong();
}
catch (Exception e)
{
e.printStackTrace();
}
Log.i("File Size", "" + fileSize);
//read file name
String fileName = "";
try
{
fileName = dataInputStream.readUTF();
}
catch (Exception e)
{
e.printStackTrace();
}
Log.i("File Name", "" + fileName);

Android Save the image in sdcard

I am saving an image into sdcard, but I want that the directory folder will be automatically shown in the gallery and the image on the folder. Whenever I save the image I am rebooting my phone for the directory folder to be shown in the gallery. Is it my code that has a problem? or the phone? Please help me. Thank you so much. I dont know what to do
here's my code:
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss",
Locale.getDefault()).format(new Date());
mTempDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + "/" + "PixiePhotos" + "/";
prepareDirectory();
save.setOnClickListener(new View.OnClickListener() {
#SuppressLint("ShowToast")
#SuppressWarnings("deprecation")
public void onClick(View v) {
Log.v(TAG, "Save Tab Clicked");
viewBitmap = Bitmap.createBitmap(500, 500, Bitmap.Config.ARGB_8888);
canvas = new Canvas(viewBitmap);
tapimageview.draw(canvas);
canvas.drawBitmap(bp, 0, 0, paint);
canvas.drawBitmap(drawingBitmap, matrix, paint);
canvas.drawBitmap(bmpstickers, matrix, paint);
//tapimageview.setImageBitmap(mBitmapDrawable.getBitmap());
try {
mBitmapDrawable = new BitmapDrawable(viewBitmap);
mCurrent = "PXD_" + new SimpleDateFormat("yyyyMMdd_HHmmss",
Locale.getDefault()).format(new Date()) + ".jpg";
bp1 = mBitmapDrawable.getBitmap();
tapimageview.setImageBitmap(bp1);
mNewSaving = ((BitmapDrawable) mBitmapDrawable).getBitmap();
String FtoSave = mTempDir + mCurrent;
File mFile = new File(FtoSave);
mFileOutputStream = new FileOutputStream(mFile);
mNewSaving.compress(CompressFormat.JPEG, 100, mFileOutputStream);
mFileOutputStream.flush();
mFileOutputStream.close();
} catch (FileNotFoundException e) {
Log.v(TAG, "FileNotFoundExceptionError " + e.toString());
} catch (IOException e) {
Log.v(TAG, "IOExceptionError " + e.toString());
}
Toast.makeText(getApplicationContext(), "Your photo has been saved", Toast.LENGTH_LONG).show();
}
});
}
private boolean prepareDirectory() {
try {
if (makeDirectory()) {
return true;
} else {
return false;
}
} catch (Exception e) {
e.printStackTrace();
//Toast.makeText(this, getString(R.string.sdcard_error), 1000).show();
return false;
}
}
private boolean makeDirectory() {
File mTempFile = new File(mTempDir);
if (!mTempFile.exists()) {
mTempFile.mkdirs();
}
if (mTempFile.isDirectory()) {
File[] mFiles = mTempFile.listFiles();
for (File mEveryFile : mFiles) {
if (!mEveryFile.delete()) {
//System.out.println(getString(R.string.failed_to_delete) + mEveryFile);
}
}
}
return (mTempFile.isDirectory());
}
Try this:
private boolean storeImage(Bitmap imageData, String filename) {
//get path to external storage (SD card)
String iconsStoragePath = Environment.getExternalStorageDirectory() + "/myAppDir/myImages/"
File sdIconStorageDir = new File(iconsStoragePath);
//create storage directories, if they don't exist
sdIconStorageDir.mkdirs();
try {
String filePath = sdIconStorageDir.toString() + filename;
FileOutputStream fileOutputStream = new FileOutputStream(filePath);
BufferedOutputStream bos = new BufferedOutputStream(fileOutputStream);
//choose another format if PNG doesn't suit you
imageData.compress(CompressFormat.PNG, 100, bos);
bos.flush();
bos.close();
} catch (FileNotFoundException e) {
Log.w("TAG", "Error saving image file: " + e.getMessage());
return false;
} catch (IOException e) {
Log.w("TAG", "Error saving image file: " + e.getMessage());
return false;
}
return true;
}
Don't forget to add Storage Permissions
Since this is operation that saves data on external memory, it requires AndroidManifest.xml permissions:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
try it out
void saveImage() {
String root = Environment.getExternalStorageDirectory().toString();
File myDir = new File(root + "/saved_images");
String fname = "Image.jpg";
File file = new File (myDir, fname);
if (file.exists ()) file.delete ();
try {
FileOutputStream out = new FileOutputStream(file);
myBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
and add permission in your maniefest file
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
The problem is not with the code ...
what happens over here is
After downloading the file on the sdcard the gallery is not notified with new file added or downloaded to the system
What you need to do is you have to manually Notify the gallery that ...okhay gallery file is added please show ..:)
For that you have to use MediaScannerConnection
Download the file ,scan the particular file and it will be shown in the gallery
and you are done:)

Saving image overwrite in sdcard android

i'm using the following code for saving the image
FrameLayout mainLayout = (FrameLayout) findViewById(R.id.frame);
// File root = Environment.getExternalStorageDirectory();
// File file = new File(root, "androidlife.jpg");
// File file = new File(Environment.getExternalStorageDirectory()
// + File.separator + "/test.jpg");
Random fCount = new Random();
// for (int i = 0; i < 10; i++) { Comment by Lucifer
int roll = fCount.nextInt(600) + 1;
//System.out.println(roll);
File file = new File(Environment.getExternalStorageDirectory()
+ File.separator + "/test" + String.valueOf(roll) +".jpg" );
Bitmap b = Bitmap.createBitmap(mainLayout.getWidth(),
mainLayout.getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
mainLayout.draw(c);
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file);
if (fos != null) {
b.compress(Bitmap.CompressFormat.JPEG, 90, fos);
fos.close();
}
} catch (Exception e) {
e.printStackTrace();
}
// } Comment by Lucifer
it save the image perfectly but overwrite when i press the save button twice...What can be the issue? Any sugestion??
File file = new File(Environment.getExternalStorageDirectory()
+ File.separator + "/test.jpg");
if(!file.exists()){
try {
file.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else{
file.delete();
try {
file.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Bitmap b = Bitmap.createBitmap(mainLayout.getWidth(),
mainLayout.getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
mainLayout.draw(c);
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file);
if (fos != null) {
b.compress(Bitmap.CompressFormat.JPEG, 90, fos);
fos.close();
}
} catch (Exception e) {
e.printStackTrace();
}
You have given a static file name.
File file = new File(Environment.getExternalStorageDirectory()
+ File.separator + "/test.jpg");
So, Everytime it is going to create a image with test.jpg name and at a same location. The only logic you need to implement is to change your file name to be a dynamic file name. You can try it in this way
static int fCount = 0;
File file = new File(Environment.getExternalStorageDirectory()
+ File.separator + "/test" + String.valueOf(fCount++) +".jpg" );
Now above line is going to create a new file every time, starting with name test0.jpg, test1.jpg ... and so on.
But this could create a problem when you close your application and restart your application. Because it will going to start again from 0 counter.
So i suggest you to go with a random number contacatination with file name.
sticker_view.setLocked(true);
sticker_view.setDrawingCacheEnabled(true);
Bitmap bitmap = sticker_view.getDrawingCache();
Log.e("BITMAP", "onOptionsItemSelected: " + bitmap);
String root = Environment.getExternalStorageDirectory().toString();
File newDir = new File(root + "/Edited Image");
newDir.mkdirs();
Random gen = new Random();
int n = 10000;
n = gen.nextInt(n);
String photoName = "Image-" + n + ".jpg";
Log.e("PHOTONAME", "onOptionsItemSelected: " + photoName);
File file = new File(newDir, photoName);
String filePath = file.getAbsolutePath();
Log.e("FILEPATH", "onOptionsItemSelected: " + filePath);
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
Toast.makeText(EditActivity.this, "Image Already Exist.", Toast.LENGTH_SHORT).show();
} else {
file.delete();
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
FileOutputStream out = new FileOutputStream(file);
Log.e("OUT", "onOptionsItemSelected: " + out);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
out.flush();
out.close();
bitmap.recycle();
Toast.makeText(EditActivity.this, "Saved In Edited Image.", Toast.LENGTH_SHORT).show();
item.setVisible(false);
MediaScannerConnection.scanFile(EditActivity.this, new String[]{file.getAbsolutePath()},
null, new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.i("ExternalStorage", "Scanned " + path + ":");
Log.i("ExternalStorage", "-> uri=" + uri);
}
});
Intent intent = new Intent();
intent.setAction("URI");
intent.putExtra("uri", filePath);
sendBroadcast(intent);
finish();
} catch (Exception e) {
e.printStackTrace();
}
}
You can just add System.currentTimeMillis() in the name of your file name to get a complete unique file name. This will add current time in milliseconds since epoch to your file name and unless you can create more than one file in a single millisecond, no overwrite will be done.

Categories

Resources