How to save a bitmap in the gallery? - java

So I have a bitmap and after I edit it I want that the User can save it and see it in the gallery. I was searching in google and a found many Ideas but all I tried didn't work. This is my code:
((ImageButton) findViewById(R.id. imageButton)).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String root = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString();
File myDir = new File(root + "/saved_images");
myDir.mkdirs();
Random generator = new Random();
int n = 10000;
n = generator.nextInt(n);
String fname = "Image-" + n + ".jpg";
File file = new File(myDir, fname);
if (file.exists())
file.delete();
try {
FileOutputStream out = new FileOutputStream(file);
mutableBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
}
catch (Exception e) {
e.printStackTrace();
}
// Tell the media scanner about the new file so that it is
// immediately available to the user.
MediaScannerConnection.scanFile(MainActivity7.this, new String[] { file.toString() }, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.i("ExternalStorage", "Scanned " + path + ":");
Log.i("ExternalStorage", "-> uri=" + uri);
}
});
}
});
So whats wrong or do you have any other solutions how I can save my bitmap in the gallery?

Go to Settings > App and find Storage permission is allowed for your app or not. If not, allow it and try again.

Related

How to get the name of image from url in this saveMyImage method

I use this code to save the image in the divice and it is working good
but I have problem with image name, I don't know what to tape here (I download the image from url with picasso).
Here is the code:
void saveMyImage (String appName, String imageUrl, String imageName) {
Bitmap bmImg = loadBitmap(imageUrl);
File filename;
try {
String path1 = android.os.Environment.getExternalStorageDirectory()
.toString();
File file = new File(path1 + "/" + appName);
if (!file.exists())
file.mkdirs();
filename = new File(file.getAbsolutePath() + "/" + imageName
+ ".jpg");
FileOutputStream out = new FileOutputStream(filename);
bmImg.compress(Bitmap.CompressFormat.JPEG, 100, out);
out.flush();
out.close();
ContentValues image = new ContentValues();
image.put(Images.Media.TITLE, appName);
image.put(Images.Media.DISPLAY_NAME, imageName);
image.put(Images.Media.DESCRIPTION, "App Image");
image.put(Images.Media.DATE_ADDED, System.currentTimeMillis());
image.put(Images.Media.MIME_TYPE, "image/jpg");
image.put(Images.Media.ORIENTATION, 0);
File parent = filename.getParentFile();
image.put(Images.ImageColumns.BUCKET_ID, parent.toString()
.toLowerCase().hashCode());
image.put(Images.ImageColumns.BUCKET_DISPLAY_NAME, parent.getName()
.toLowerCase());
image.put(Images.Media.SIZE, filename.length());
image.put(Images.Media.DATA, filename.getAbsolutePath());
Uri result = getContentResolver().insert(
Images.Media.EXTERNAL_CONTENT_URI, image);
Toast.makeText(getApplicationContext(),
"download in " + filename, Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
}
}
This is the call method in onCreate:
/* button to download the image */
download_image = findViewById(R.id.button_download);
checkPermission();
download_image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (checkPermission()) {
String URL = intent.getStringExtra("imageUrl");
saveMyImage ("my app",URL,"i want to get the image name from the url");
}
}
});
I want to get the image name from the url, so how can I do that?
Try this:
URI uri = new URI(URL);
URL videoUrl = uri.toURL();
File tempFile = new File(videoUrl.getFile());
String fileName = tempFile.getName();

Why doesn't image saving work anymore on API 29

In my App the user is able to save images from a pciture gallery to the local device by clicking on a DL Button.
The Code does work on old devices but on API 29 it has the following behaviour:
While saving I tried to open the Gallery to have a look what happens: the gallery gets updated and for 1 second an empty images appears and disappears immediately after. I get noticed, that the image got saved but it doesn't appear, not even in the device explorer.
//DEXTER HERE
Picasso.get().load(dummyimage.getLarge()).placeholder(R.drawable.ic_img_error).error(R.drawable.ic_red).into(saveImageToDirectory);
final Target saveImageToDirectory = new Target() {
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
ProgressDialog mydialog = new ProgressDialog(getActivity());
mydialog.setMessage("saving Image to phone");
mydialog.show();
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
try {
String fileName = "myApp_" + timeStamp + ".JPG";
String dirName= "/myApp";
File file = new File(requireActivity().getApplicationContext().getExternalFilesDir(null).getAbsolutePath() + dirName, fileName);
//new File(path for the file to be saved, saving file name)
if (!file.exists()) {
//check if the file already exist or if not create a new file
//if exist the file will be overwritten with the new image
File filedirectory = new File(requireActivity().getApplicationContext().getExternalFilesDir(null).getAbsolutePath() + dirName);
filedirectory.mkdirs();
}
if (file.exists()) {
file.delete();
}
FileOutputStream ostream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, ostream);
Toast.makeText(getActivity(), "Picture saved to Gallery" + file.getAbsolutePath(), Toast.LENGTH_SHORT).show();
ostream.close();
mydialog.dismiss();
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, "My Images");
values.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");
values.put(MediaStore.MediaColumns.RELATIVE_PATH,"/myApp");
// API LEVEL Q: values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis());
values.put("_data", file.getAbsolutePath());
ContentResolver cr = getActivity().getContentResolver();
cr.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
} catch (Exception e) {
mydialog.dismiss();
Log.e("file creation error", e.toString());
}
}
#Override
public void onBitmapFailed(Exception e, Drawable errorDrawable) {
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
};
As you may see, instead of
File filedirectory = new File(Environment.getExternalStorageDirectory() + dirName);
I'm already using
File filedirectory = new File(requireActivity().getApplicationContext().getExternalFilesDir(null).getAbsolutePath() + dirName);
I hope this shouldn't be the problem, but I'm a little stuck on this strange behaviour.
This is the error I'm getting out of my Logcat:
E/file creation error: java.lang.IllegalArgumentException: Primary
directory (invalid) not allowed for
content://media/external/images/media; allowed directories are [DCIM,
Pictures]
PS: I'm using Dexter to avoid problems with the permissions
Try this
private Uri saveImage(Context context, Bitmap bitmap, #NonNull String folderName, #NonNull String fileName) throws IOException
{
OutputStream fos;
File imageFile = null;
Uri imageUri = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
ContentResolver resolver = context.getContentResolver();
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, fileName);
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/png");
contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, "DCIM" + File.separator + folderName);
imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
fos = resolver.openOutputStream(imageUri);
} else {
String imagesDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DCIM).toString() + File.separator + folderName;
imageFile = new File(imagesDir);
if (!imageFile.exists()) {
imageFile.mkdir();
}
imageFile = new File(imagesDir, fileName + ".png");
fos = new FileOutputStream(imageFile);
}
boolean saved = bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.flush();
fos.close();
if (imageFile != null) // pre Q
{
MediaScannerConnection.scanFile(context, new String[]{imageFile.toString()}, null, null);
imageUri = Uri.fromFile(imageFile);
}
return imageUri;
}
And add requestLegacyExternalStorage in your Manifest file
<application
android:allowBackup="true"
android:icon="#drawable/icon"
android:requestLegacyExternalStorage="true"
android:label="#string/app_name"
android:roundIcon="#drawable/icon"
android:supportsRtl="true"
android:theme="#style/AppTheme">
...
...
...
</application>

How to create a simple local backup and restore for an app?

I Have five sqlite databases and I want user to be able to have local backup in his phone and he can restore the backup file .
I don't know how to create these backups and restore them programatcally .
I used A github repo but it did not work at all,
I need your help to create this process of backup and restore .
Thank for your attention
In your Activity make backup and restore button and define local database variable like,
private MainDatabase localBackup = new MainDatabase(this);
Then perform backup and restore operation when it's just click
#Override
public void onClick(View v) {
final MainDatabase db = new MainDatabase(getApplicationContext());
switch (v.getId()) {
case R.id.tvBackUp:
String outFileName = Environment.getExternalStorageDirectory() +
File.separator + getResources().getString(R.string.app_name) + File.separator;
localBackup.performBackup(db, outFileName);
break;
case R.id.tvRestore:
File folder = new File(Environment.getExternalStorageDirectory() + File.separator + getApplicationContext().getResources().getString(R.string.app_name));
if (folder.exists()) {
final File[] files = folder.listFiles();
if (files.length == 0) {
Toast.makeText(this, "No any Backup", Toast.LENGTH_SHORT).show();
} else {
localBackup.performRestore(db);
}
}
break;
}
}
Make a method for backup in your database file
public void performBackup(final MainDatabase db, final String outFileName) {
File folder = new File(Environment.getExternalStorageDirectory() + File.separator
+ mContext.getResources().getString(R.string.app_name));
boolean success = true;
if (!folder.exists())
success = folder.mkdirs();
if (success) {
final Dialog dialog = new Dialog(mContext);
dialog.setContentView(R.layout.backup_dialog);
dialog.getWindow().getAttributes().windowAnimations =
R.style.PauseDialogAnimation;
dialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent);
dialog.show();
Button btnSave = dialog.findViewById(R.id.btnSave);
Button btnCancel = dialog.findViewById(R.id.btnCancel);
EditText etName = dialog.findViewById(R.id.etName);
etName.setInputType(InputType.TYPE_CLASS_TEXT);
btnSave.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String m_Text = etName.getText().toString();
String out = outFileName + m_Text + ".db";
db.backup(out);
dialog.dismiss();
}
});
btnCancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialog.dismiss();
}
});
} else
Toast.makeText(mContext, "Unable to create directory. Retry",
Toast.LENGTH_SHORT).show();
}
public void backup(String outFileName) {
//database path
final String inFileName = mContext.getDatabasePath(DATABASE_NAME).toString();
try {
File dbFile = new File(inFileName);
FileInputStream fis = new FileInputStream(dbFile);
// Open the empty db as the output stream
OutputStream output = new FileOutputStream(outFileName);
// Transfer bytes from the input file to the output file
byte[] buffer = new byte[1024];
int length;
while ((length = fis.read(buffer)) > 0) {
output.write(buffer, 0, length);
}
// Close the streams
output.flush();
output.close();
fis.close();
Toast.makeText(mContext, "Backup Completed", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Toast.makeText(mContext, "Unable to backup database. Retry",
Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}
As well as for restore do this thing,
ask to the user what backup to restore
public void performRestore(final MainDatabase db) {
File folder = new File(Environment.getExternalStorageDirectory() + File.separator
+ mContext.getResources().getString(R.string.app_name));
if (folder.exists()) {
final File[] files = folder.listFiles();
final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(mContext,
android.R.layout.select_dialog_item);
for (File file : files)
arrayAdapter.add(file.getName());
AlertDialog.Builder builderSingle = new AlertDialog.Builder(mContext);
builderSingle.setTitle("Select & Restore ");
builderSingle.setNegativeButton("cancle", (dialog, which) ->
dialog.dismiss());
builderSingle.setAdapter(arrayAdapter, (dialog, which) -> {
try {
db.importDB(files[which].getPath());
} catch (Exception e) {
Toast.makeText(mContext, "Unable to restore. Retry",
Toast.LENGTH_SHORT).show();
}
});
builderSingle.show();
} else
Toast.makeText(mContext, "Backup folder not present.\nDo a backup before a
restore!", Toast.LENGTH_SHORT).show();
}
public void importDB(String inFileName) {
final String outFileName = mContext.getDatabasePath(DATABASE_NAME).toString();
try {
File dbFile = new File(inFileName);
FileInputStream fis = new FileInputStream(dbFile);
// Open the empty db as the output stream
OutputStream output = new FileOutputStream(outFileName);
// Transfer bytes from the input file to the output file
byte[] buffer = new byte[1024];
int length;
while ((length = fis.read(buffer)) > 0) {
output.write(buffer, 0, length);
}
// Close the streams
output.flush();
output.close();
fis.close();
Toast.makeText(mContext, "Restore Completed", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Toast.makeText(mContext, "Unable to import database. Retry",
Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}
Android already supports system automatic backups if you have android:allowBackup="true" at your manifest. If it isn't enough and you want to manage backups manually between app reinstalls than you have to copy database from context.getDatabasePath("<your-database-name>") to external storage somewhere, and then copy it back when you want

Can't compress bitmap android studio

In my app I have a fragment which opens the device camera and allows the users to take photos and store them in a directory inside the gallery. This is the method that I use to create the dir and save the taken image:
private void saveImage(Bitmap finalBitmap, String image_name) {
final String appDirectoryName = "/Feel/";
String root = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES).toString() + appDirectoryName;
File myDir = new File(root);
myDir.mkdirs();
String fname = "Image-" + image_name + ".jpg";
File file = new File(myDir, fname);
if (file.exists()) file.delete();
Log.i("LOAD", root + fname);
try {
FileOutputStream out = new FileOutputStream(file);
finalBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Everything works fine except finalBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);. When it comes to this line it skips the process... The directory is not created too... What is causing this problem?
This is my CameraFragment, where I retrieve the photo that was shot:
final Button btnShoot = viewCamera.findViewById(R.id.btnShoot);
imgUltimaFoto.setVisibility(View.INVISIBLE);
btnShoot.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
cmrView.addCameraListener(new CameraListener() {
#Override
public void onPictureTaken(final byte[] picture) {
super.onPictureTaken(picture);
CameraUtils.decodeBitmap(picture, new CameraUtils.BitmapCallback() {
#Override
public void onBitmapReady(Bitmap bitmap) {
imgUltimaFoto.setImageBitmap(bitmap);
imgUltimaFoto.setVisibility(View.VISIBLE);
saveImage(bitmap,"imagem1");
}
});
}
});
cmrView.capturePicture();
}
});

android java.io.File.fixSlashes(File.java:185)

I got an error in console crashes & anrs. This error is showing sometimes and I couldn't find where the problem is.
java.lang.NullPointerException
at java.io.File.fixSlashes(File.java:185)
at java.io.File.<init>(File.java:134)
The function code to save picture is:
public static String sharePhoto(Context context, Bitmap bmp) {
File folder = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Pictures/Folder");
boolean success = true;
String file_path = null;
if (!folder.exists()) {
success = folder.mkdir();
}
if (success) {
file_path = folder + "/Img_" + System.currentTimeMillis() / 1000 + ".jpg";
}
OutputStream os = null;
try {
os = new FileOutputStream(file_path);
bmp.compress(Bitmap.CompressFormat.JPEG, 100, os);
} catch (IOException e) {
e.printStackTrace();
}
} else {
// Do something else on failure
}
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f = new File(file_path);
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
context.sendBroadcast(mediaScanIntent);
return file_path;
}
Try this:
File folder = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Pictures/MyFolder");
Thing is that getExternalStorageDirectory() returns File. You need to get absolute path of that file and concatenate with "/Pictures/MyFolder".

Categories