I am trying to write and read a bitmap following the suggestions on other topics about this, the thing is i never get the bitmap when i try to read on the path where i saved the image:
So i have this to write the bitmap:
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,"captured");
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.JPEG, 100, fos);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return directory.getAbsolutePath();
}
}
i pass the returned path to another activity and then i pass it as parameter to get the bitmap like this:
private void loadImageFromStorage(String path)
{
try {
File f=new File(path, "captured.jpg");
Log.d("filehe",f.toString());
b = BitmapFactory.decodeStream(new FileInputStream(f));
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
}
i feel i am doing something wrong here, but can't figure out what, the b variavel has no value :/.
Any help?
Thanks
So i have this to write the bitmap:
The file that you save is named captured.
i pass the returned path to another activity and then i pass it as parameter to get the bitmap like this
Here, you are trying to load captured.jpg, which is not captured.
You could avoid this sort of problem by having the first method return the File that the second method then uses.
Also:
Use an image-loading library (e.g., Picasso, Glide) that has an in-memory cache, so you do not waste the user's time re-loading the same bitmap from disk
Get rid of ContextWrapper from the first method, as you do not need it
Related
When I am using webp files for animated sticker packs it get rejected but if use same files for static stickers it get excepted. After looking all the codes I came to know that this is the last point where those files becomes problematic. But don not know how to identify if webp files stays as animated webp after saving. Please share your thought.
ps: I am using these webp files for whatsapp sticker packs. there is flag "animated_sticker_pack". we have to tell whatsapp that this pack contains only animated webp with proper fomrat. If I set it false then sticker pack get added (let it be static or animated webp). But if I set that flag true then those animated webp get rejected for pack showing error that There's problem with this pack.... So it might be that frames are lesser then it required. It get accepted as static means it might have single frame only.
To avoid issues regarding file type,format,size and all I am using the sample files from WhatsApp sample app
Code:
public static void SaveImage(Bitmap finalBitmap, String name, String identifier) {
String root = path + "/" + identifier;
File myDir = new File(root);
myDir.mkdirs();
String fname = name;
File file = new File(myDir, fname);
if (file.exists()){
file.delete();
}
try {
// FileOutputStream
FileOutputStream out = new FileOutputStream(file);
// Bitmap.compress
finalBitmap.compress(Bitmap.CompressFormat.WEBP, 100, out);
// close
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
////////////////////Other methods before saving images
private Bitmap downloadImageBitmap(String sUrl, String sIdentifier, String sName) {
imageFileName = getLastBitFromUrl(sUrl).replace(".png", ".webp");
identifier = sIdentifier;
name = sName;
Bitmap bitmap = null;
try {
InputStream inputStream = new URL(sUrl).openStream(); // Download Image from URL
bitmap = BitmapFactory.decodeStream(inputStream); // Decode Bitmap
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}
#Override
protected Bitmap doInBackground(String... params) {
return downloadImageBitmap(params[0], params[1], params[2]);
}
protected void onPostExecute(Bitmap result) {
SaveImage(result, imageFileName, identifier);
}
You can download and save in doInBackground()
InputStream inputStream = new URL(sUrl).openStream(); // Download Image from URL
FileOutputStream out = new FileOutputStream(file);
Then make a loop where you read bytes in a buffer from input stream and write to output stream.
Don't forget to close all streams when done.
I'm making an Android application that captures images and stores them in the internal memory, but to save the images are compressed and I want to be saved in its original size without any compression.
This is the code I am using to store images, as I do so not me compress ??
ContextWrapper cw = new ContextWrapper(context);
File directory = cw.getDir("imageDir", Context.MODE_PRIVATE);
File mypath = new File(directory, "TheChat" + (System.currentTimeMillis()/1000) + "Avatar.jpg");
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(mypath);
bitmapImage.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
}
catch (Exception e) {
e.printStackTrace();
}
finally {
try {
if (fileOutputStream != null) {
fileOutputStream.flush();
fileOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
Save it as a BLOB (bytearray), then reconvert it to a bitmap upon loading it. If it's for internal use only it should work fine. If you're not compressing it at all you might as well save it in a straight-forward format.
This is the code I have in my onCreate() method in the starting activity for my app
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_startup);
Bitmap bm = BitmapFactory.decodeResource(getApplicationContext().getResources(), R.drawable.img);
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.PNG, 40, bytes);
//you can create a new file name "test.jpg" in sdcard folder.
File f = new File(Environment.getExternalStorageDirectory()
+ File.separator + "test.jpg");
try {
f.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
//write the bytes in file
FileOutputStream fo = null;
try {
fo = new FileOutputStream(f);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
fo.write(bytes.toByteArray());
} catch (IOException e) {
e.printStackTrace();
}
try {
fo.close();
} catch (IOException e) {
e.printStackTrace();
}
It is meant to load an image into a bitmap and then make a file on the SD card named "test.jpg" with the image inside, however this is not what is happening.
Instead, I get a null pointer exception on the line
fo.write(bytes.toByteArray());
The error message is:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.daniel.firstapp/com.example.daniel.firstapp.startup}: java.lang.NullPointerException: Attempt to invoke virtual method 'void java.io.FileOutputStream.write(byte[])' on a null object reference
First: Why so many try/catch?
Second: Your fo variable is null.
Probably because the file could not be created.
Make sure you have this in your manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
You can drop the ByteArrayOutputStream and replace it with a FileOutputStream instead.
NB: try/catch blocks omitted for clarity.
File f = new File(Environment.getExternalStorageDirectory() + File.separator + "test.jpg");
// 'this' in the following line refers to an instance of your Activity, if you're doing your output from a fragment or helper class, get a reference to your activity.
FileOutputStream fos = this.openFileOutput(f.getName(), Context.MODE_PRIVATE);
Bitmap bm = BitmapFactory.decodeResource(getApplicationContext().getResources(), R.drawable.img);
//PNG doesn't compress because it's lossless
bm.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.flush();
fos.close();
bm.recycle();
also make sure you have the appropriate write external storage permission set in your manifest.
starting from android 4.4, normal applications are not allowed to access secondary external storage devices, i.e. sd card, except in their package-specific directories, even if you have requested WRITE_EXTERNAL_STORAGE permission.
The WRITE_EXTERNAL_STORAGE permission must only grant write access to
the primary external storage on a device. Apps must not be allowed to
write to secondary external storage devices, except in their
package-specific directories as allowed by synthesized permissions.
Restricting writes in this way ensures the system can clean up files
when applications are uninstalled.
https://source.android.com/devices/storage/
Actually your application has thrown exception in the line below, because of the restriction.
FileOutputStream fo = null;
try {
fo = new FileOutputStream(f);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
I am trying to use the AndroidImageSlider library and populate it with images that I have downloaded as a base64 string.
The library only accepts URLs, R.drawable values, and the File object as parameters.
I am trying to convert the image string to a File object in order to be passed to the library function. I have been able to decode from base_64 and convert to a byte[] so far.
String imageData;
byte[] imgBytesData = android.util.Base64.decode(imageData, android.util.Base64.DEFAULT);
You'll need to save the File object to disk for that to work. This method will save the imageData string to disk and return the associated File object.
public static File saveImage(final Context context, final String imageData) {
final byte[] imgBytesData = android.util.Base64.decode(imageData,
android.util.Base64.DEFAULT);
final File file = File.createTempFile("image", null, context.getCacheDir());
final FileOutputStream fileOutputStream;
try {
fileOutputStream = new FileOutputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
final BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(
fileOutputStream);
try {
bufferedOutputStream.write(imgBytesData);
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
try {
bufferedOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return file;
}
It creates a temporary file in your applications 'cache' directory. However, you are still responsible for deleting the file once you no longer need it.
The problem:
I'm getting a Base64-Encoded String of raw PDF data from a web service (this data is housed in my String array pdfData). I have to use this data display the PDF in a PDF viewer (I happen to be using the included 'ThinkFree PDF Viewer' since I'm working on an Android application, but lets generalize and say any PDF viewer will do). Note that I'm accessing the 0th element of this array just for testing purposes (to make sure I can at least pull up 1 PDF before writing the code to pull up all the PDFs).
The code is within a class. First the method createFile is called, then intentOpenPDF:
import org.apache.commons.codec.binary.Base64;
File file;
FileOutputStream outputStream;
private byte[] decodedContent;
private String[] pdfData;
private String[] pdfFileName;
public void createFile() {
decodedContent = Base64.decodeBase64(pdfData[0].getBytes());
try {
File path = new File(getFilesDir(), "PDFs");
if (!path.exists()) {
path.mkdirs();
}
file = new File(path, pdfFileName[0]);
outputStream = new FileOutputStream(file);
outputStream.write(decodedContent);
outputStream.close();
}
catch (FileNotFoundException ex) {
ex.printStackTrace();
}
catch (IOException ex) {
ex.printStackTrace();
}
finally {
// Make absolutely certain the outputStream is closed
try {
if (outputStream != null) {
outputStream.close();
}
}
catch (IOException ex) {
ex.printStackTrace();
}
}
}
public void intentOpenPDF() {
// Make sure the file exists before accessing it:
if (file.exists()) {
Uri targetUri = Uri.fromFile(file);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(targetUri, "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
}
}
The error:
Error opening file. It does not exist or cannot be read.
I have a break point set inside the conditional statement that checks if the file exists (within the intentOpenPDF method), and it IS passing this check.
The path produced by calling getFilesDir() leads a protected directory (file:///data/data/), where only files created with openFileOutput(String, int) are stored. I am not creating the file this way. The solution in my case is to use getExternalFilesDir(null).getAbsolutePath() instead, which will give you a path a directory internal to the application (/storage/emulated/0/Android/data/). No permissions are required to read or write to this path.
Considering your error message:
It does not exist or cannot be read.
as you verified it exists (first possible cause), it's certainly not readable (second possible cause).