this is a peace of code I've created to save a "library" of images to external storage in order to use that file in another application. This is a binary file which contains ArrayList of objects.
this is method what makes main job.
public void createLib()
{
File fl = new File("/mnt/sdcard/imgs");
File[] rawLib = fl.listFiles();
TextView text = (TextView) findViewById(R.id.txt1);
ArrayList<Block> myList = new ArrayList<Block>();
try{
for (int i = 0; i < rawLib.length; i++)
{
FileInputStream fis = new FileInputStream(rawLib[i]);
Bitmap bmp = BitmapFactory.decodeStream(fis);
Block tmpBlock = new Block();
tmpBlock.bmp = bmp;
tmpBlock.mozColor = findMidColor(bmp);
myList.add(tmpBlock);
}
}
catch(Exception exc)
{
exc.printStackTrace();
}
try
{
String root = Environment.getExternalStorageDirectory().toString();
File myDir = new File(root + "/saved_images");
myDir.mkdirs();
File file = new File (myDir, "library.lib");
FileOutputStream fos = new FileOutputStream(file);
ObjectOutputStream save = new ObjectOutputStream(fos);
save.writeObject(myList);
save.close();
}
catch (Exception exc)
{
exc.printStackTrace();
}
here is the class I am working with
class Block
{
Bitmap bmp;
int mozColor;
}
findMidColor() is my method and it work pretty fine, so there is no problem with that.
When I pull created file from the emulators external storage, I see that file's size is about two and a half kilobytes, but original folder with images is about 2-3 megabytes.
Conslusion is that program saves only pointers to that bmp's. Is there any way to create bynary file of objects which contain images and ints, and reuse that file in another application like a ArrayList or any other array?
Yes Bitmap's data (pixels) are not saved in the Bitmap object. They live somewhere in the heap. You are now saving only references to wrong locations.
In your Block class instead of having a Bitmap object you can have a path to the Bitmap and a method that returns a Bitmap from that path.
class Block{
String bitmapPath;
int mozColor;
Bitmap bmp(){
//do something here to encode bitmap from file
}
}
You have to save the bitmap to a specific path and store it to Block.bitmapPath every time
You can easily find how to save a Bitmap to a File and retrieve from File
Related
I am developing an Android app. In my app, I am uploading multiple images to server using Retrofit network library. Before I uploading file I create a temporary file from bitmaps. Then delete them after uploaded.
photoFiles = new ArrayList<File>();
MultipartBody.Builder requestBodyBuilder = new MultipartBody.Builder().setType(MultipartBody.FORM);
int index = 0;
for(Bitmap bitmap: previewBitmaps)
{
File file = null;
try{
String fileName = String.valueOf(System.currentTimeMillis())+".jpeg";
file = new File(Environment.getExternalStorageDirectory(), fileName); // create temporary file start from here
if(file.exists())
{
file.delete();
}
OutputStream os = new BufferedOutputStream(new FileOutputStream(file));
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);
os.close();
photoFiles.add(file);
requestBodyBuilder.addFormDataPart("files",file.getName(), RequestBody.create(MediaType.parse("image/png"),file));
}
catch (Exception e)
{
Toast.makeText(getBaseContext(),e.getMessage(),Toast.LENGTH_SHORT).show();
}
index++;
}
//Upload process goes here and delete files back after upload
Using above code, all working fine. But the problem is I have to create temporary files. I do not want to create temporary files. What I want to do is I create array list of Uri string when I pick up the file. Then on file upload, I will convert them to file back and do the upload process.
photoFiles = new ArrayList<File>();
MultipartBody.Builder requestBodyBuilder = new MultipartBody.Builder().setType(MultipartBody.FORM);
int index = 0;
for(Bitmap bitmap: previewBitmaps)
{
File file = null;
try{
Uri uri = Uri.parse(photosUriStrings.get(index));
file = new File(getPathFromUri(uri));
Toast.makeText(getBaseContext(),getPathFromUri(uri),Toast.LENGTH_SHORT).show();
photoFiles.add(file);
requestBodyBuilder.addFormDataPart("files",file.getName(), RequestBody.create(MediaType.parse("image/png"),file));
}
catch (Exception e)
{
Toast.makeText(getBaseContext(),e.getMessage(),Toast.LENGTH_SHORT).show();
}
index++;
}
As you can see in the above, I am converting the URI string back to file and then upload it. But this time retrofit unable to upload the file. File is not null as well. So I am pretty sure the error is with converting uri string back to image file back because my old code above working fine. Why can I not do that? How can I successfully convert from URI to image file back please?
I found this
Convert file: Uri to File in Android
and
Create File from Uri type android
both not working.
I am not clear about your question but I think this may help you. This single line code will help you to convert URI to file and show in your view.
Picasso.with(getContext()).load("URI path").into(holder.imgID);
I wasn't sure how to word this, but in iOS terms, if I download an image, and save it in the documents directory, it saves it in the Apps Container, which is not visible to other apps, and camera roll etc.
The way I have it in Android currently, all of these images are visible in the File Explorer and Gallery.
I was wondering how I could save these images in a similar way to iOS and have them hidden in the Apps own container.
Is there a way to create a folder, with context.MODE_PRIVATE or something similiar?
This is what I have currently, does it do the trick?
public static Boolean saveToInternalStorage(Context context, Bitmap bitmap, String filename) {
ContextWrapper cw = new ContextWrapper(context);
//Path to /data/data/yourapp/app_data/imageDir
File directory = cw.getDir("imageDir", Context.MODE_PRIVATE);
//Create imageDir
File mypath = new File(directory, filename);
FileOutputStream fos = null;
try {
fos = new FileOutputStream(mypath);
//Use the compress method on the BitMap object to write image to the OutputStream
if (bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos)) {
return true;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (fos != null) {
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return false;
}
public static Bitmap loadImageFromStorage(Context context, String filename) {
ContextWrapper cw = new ContextWrapper(context);
//Path to /data/data/yourapp/app_data/imageDir
File directory = cw.getDir("imageDir", Context.MODE_PRIVATE);
try {
File f = new File(directory, filename);
Bitmap b = BitmapFactory.decodeStream(new FileInputStream(f));
return b;
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return null;
}
Read this article. This will help..
You can save files directly on the device's internal storage. By default, files saved to the internal storage are private to your application and other applications cannot access them (nor can the user). When the user uninstalls your application, these files are removed.
I was wondering how I could save these images in a similar way to iOS and have them hidden in the Apps own container.
Write them to getFilesDir(), getCacheDir(), or another location on internal storage.
This is what I have currently, does it do the trick?
The ContextWrapper is useless. If you are downloading an image, I do not know why you have a Bitmap that you are trying to write to storage — download straight to storage.
But, with respect to keeping the images private to your app, getDir() also points to locations in internal storage.
The Android Application which I am developing is basically a shopping application, which has a Cart option, where user can add items.
The Items has Image, Name, Price etc..
I get all these data from server.
When user click "Add to Cart " option then a sqlite database is created where I store the name, price and image path.
Basically Imgaes are stored in the internal memory when add to cart is clicked and only image path is stored in the database.
Problem:
To store images in the internal memory I use the below code where I will give the file name myself (In this case I give file name as profile.jpg).
SaveToMemory:
private String saveToInternalSorage(Bitmap bitmapImage){
ContextWrapper cw = new ContextWrapper(getApplicationContext());
// path to /data/data/yourapp/app_data/imageDir
directory = cw.getDir("imageDir", Context.MODE_PRIVATE);
// Create imageDir
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();
}
LoadFromMemory:
private Bitmap loadImageFromStorage(String path)
{
try {
File f=new File(path, "");
f.canRead();
b = BitmapFactory.decodeStream(new FileInputStream(f));
return b;
}
If I do so, latest image is overridden by the previous image. Iam not able to store multiple images in the internal memory.
For Example If I add two items inside the cart I dont know how to store those two images and get it.
Aim
Need to store any number of images with random file name in the internal memory
Store the file name in sqlite database.
Retrieve it back to display in Imageview.
Any help would be greatly thankfull.
Try
mypath=new File(directory,System.currentTimeMillis()+"_profile.jpg");
instead of
mypath=new File(directory,"profile.jpg");
System.currentTimeMillis() will returns the current time in milliseconds since January 1, 1970 00:00:00.0 UTC. so it is different each time
You can use UUID
new File(directory,"profile_" + UUID.randomUUID().toString() + ".jpg");
it would be
profile_e85c5115-eea6-4b0d-98e3-9e09c2d505b3.jpg
Use new Date().toString() instead of "profile.jpg"
The problem is that in the first start of my app i load some images from the drawable folder and then put them into my storage using this function:
1- I first make them as bitmap
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.autobus);
and then I convert them using this function
private String saveToInternalSorage(Bitmap bitmapImage, String imagename) throws IOException{
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,imagename);
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 {
fos.close();
}
return directory.getAbsolutePath();
}
But now I need to do the same for a sound , I need to store the sound fields in the raw section in the internal memory in order to use them later .
So if some one can help me that would be gentle of him ,
PS: I store the path to those files in my SQLite data base.
If you use an InputStream to read, use an OutputStream to write, i.e. a BufferedOutputStream-wrapped FileOutputStream. Also, your code is pretty inefficient, as it only copies one byte at a time. I'd suggest creating a byte array buffer and using these relevant read/write methods:
int BufferedInputStream.read(byte[] buffer, int offset, int length)void BufferedOutputStream.write(byte[] buffer, int offset, int length)
For more detail use this link it is help you
I have numerous images in my resource folder of my android application. I would like to copy the files from the resource folder to storage and maintain their original image type (bitmap, jpg, png, etc) I would also like to have the original file name.
I am attempting to do something along the lines of...
public static void CopyImagesFromResourceToStorage(Context c,int[] resources,String path)
{
File dir = new File(path);
for(int i=0;i<resources.length;i++)
{
File file = new File(path+"???Filename???");
Bitmap bm = BitmapFactory.decodeResource(c.getResources(), resources[i]);
//Copy Bitmap to the file here...
}
}
To get the filename, I would use an extra paramter, the original path. Than you can loop over all the files in the original directory, to get the filenames. If you have the filenames, you can either one of the links mentioned in the comments...
This would be your final solution (UNTESTED):
public static void CopyImagesFromResourceToStorage(Context c,int[] resources,String path, String originalpath)
{
// Get the directory of your original files
File dir = new File(originalpath);
// List all files in that directory
File[] files = dir.listFiles();
// Loop through all the files in your original directory
for(File original: files)
{
// Create a filename: <target_directory> + original.getName();
String filename = path + "\\" + original.getName();
Bitmap bm = BitmapFactory.decodeResource(c.getResources(), resources[i]);
try {
FileOutputStream out = new FileOutputStream(filename);
bmp.compress(Bitmap.CompressFormat.PNG, 90, out);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Be sure to also close the FileOutputStream, and do some extra checks to see the the File[] files is actually holding files and not directories.
NOTE: If you really work with the resouces folder, you can use something like this as well:
Field[] drawables = android.R.drawable.class.getFields();
for (Field f : drawables) {
try {
System.out.println("R.drawable." + f.getName());
} catch (Exception e) {
e.printStackTrace();
}
}
To loop over the resources