Android: Not able to access storage to save image - java

I have an imageview which is loaded using a url.
I want to download the image in the view and store it in internal/external drive of mobile. But i tried all possible method on Stackoverflow couldn't access the drive even with the premission given on the mobile to access read and write in the external memory. Nothing seems to work i don't know why?
This is my Code, can you please tell me where I am going wrong?
BitmapDrawable drawable = (BitmapDrawable) imageView.getDrawable();
Bitmap bitmap = drawable.getBitmap();
File sdCardDirectory = Environment.getDataDirectory();
File image = new File(sdCardDirectory, "test.png");
boolean success = false;
// Encode the file as a PNG image.
FileOutputStream outStream;
try {
outStream = new FileOutputStream(image);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream);
/* 100 to keep full quality of the image */
outStream.flush();
outStream.close();
success = true;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
if (success) {
Toast.makeText(getApplicationContext(), "Image saved with success",
Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(),
"Error during image saving", Toast.LENGTH_LONG).show();
}
Manifest permissions
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

File sdCardDirectory = Environment.getDataDirectory();
That is not the sd card directory.
Environment.getDataDirectory().getAbsolutePath() == /data
You have no write permission there. Better use
File sdCardDirectory = Environment.getExternalStorageDirectory();
That will work if you got your permissions right.
But it will not save to the SD card!

Related

Taking screenshot and saving into app's own directory

I know this question has been answered, but I would like to get a better explanation as I have tried implementing it but it doesn't seem to work.
I have the following code :
private void takeScreenshot() {
ContextWrapper cw = new ContextWrapper(getApplicationContext());
//Get screenshot
View v1 = getWindow().getDecorView().getRootView();
v1.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache());
v1.setDrawingCacheEnabled(false);
Date fileName = new Date();
android.text.format.DateFormat.format("yyyy-MM-dd_hh:mm:ss", fileName);
File directory = cw.getDir("imageDir", Context.MODE_PRIVATE);
File image = new File(directory,fileName+".jpg");
try {
FileOutputStream fos = new FileOutputStream(image);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
} catch (Exception e) {
e.printStackTrace();
}
}
What I would like to happen is to take a screenshot of the screen, save it to a folder with my app name, and have it be readable by the android phone's gallery. My code does none of the above. I do not see any folder w/ the name of my app when I use file explorer, and it doesn't appear in the gallery as well. It seems it doesn't even save the image. Can you please tell me what is wrong with my code?
The code below creates a directory called "AppName" and then stores the screenshot in that directory. This will be readable by the gallery as well. Your code (and the code below) will not work if you do not have the WRITE_EXTERNAL_STORAGE permission.
private static File getOutputMediaFile() {
// To be safe, you should check that the SDCard is mounted
// using Environment.getExternalStorageState() before doing this.
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "MyCameraApp"); //change to your app name
// This location works best if you want the created images to be shared
// between applications and persist after your app has been uninstalled.
// Create the storage directory if it does not exist
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d("MyCameraApp", "failed to create directory");
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"IMG_" + timeStamp + ".jpg");
return mediaFile;
}
private void takeScreenshot(){
//Get screenshot
View v1 = getWindow().getDecorView().getRootView();
v1.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache());
v1.setDrawingCacheEnabled(false);
File pictureFile = getOutputMediaFile();
if (pictureFile == null){
Log.d(TAG, "error creating media file, check storage permission");
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
bitmap.recycle();
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found" + e.getMessage());
} catch (Exception e) {
e.printStackTrace();
}
}
Ensure to add
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
to your manifest and ask for permissions on runtime with
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
00);
The code finds and/or creates a directory with the app name in the getOutputMediaFile() method, then returns a file in the directory with timestamp as its name. Then in the takeScreenshot() method, the screenshot bitmap is converted to a byte[] and a fileOutputStream is used to write this byte[] to the file returned by getOutputMediaFile().
The result is a screenshot saved to the gallery in the directory "MyCameraApp" (Change to whatever your app's name is)
Hope this helps!

Android not create a folder in gallery

I'm trying to save an image on JPG format on a specific folder from my gallery. But my code is not creating a directory, whenever i create a Toast it return for me /storage/emulated/0/DCIM/MyFodler,but when will i open the gallery, this foder not exist. I'm building the application direct of my devide with Android Marshmallow 6.0.
Code to create Bitmap:
private Bitmap getToBitmap(ImageView view, int Width, int Heigth){
Bitmap bitmap = Bitmap.createBitmap(Width,Heigth, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
return bitmap;
}
Code to try save the image on gallery:
private void TrySaveMediaStore(){
String path = Environment.getExternalStorageDirectory().toString();
OutputStream FileOut = null;
File file = new File(path,"DCIM/MyFolder");
file.mkdirs();
Toast.makeText(getApplicationContext(),file.getAbsolutePath(),Toast.LENGTH_SHORT).show();
try{
FileOut = new FileOutputStream(file);
FileOut.flush();
FileOut.close();
Bitmap bitmap = getToBitmap(img,img.getMaxWidth(),img.getMaxHeight());
bitmap.compress(Bitmap.CompressFormat.JPEG,100,FileOut);
MediaStore.Images.Media.insertImage(getContentResolver(), file.getAbsolutePath(), file.getName(), file.getName());
Toast.makeText(this,file.getAbsolutePath(),Toast.LENGTH_SHORT).show();
}catch (FileNotFoundException e){
return;
}catch (IOException e){
e.printStackTrace();
}
}
Androidmanifest permissions:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
DCIM/MyFolder is a directory. You create this as a directory using mkdirs().
You cannot then try using DCIM/MyFolder as a filename for saving a JPEG. You need to create a file inside the directory.
So, instead of:
FileOut = new FileOutputStream(file);
use something like:
File theActualImageFile=new File(file, "something.jpeg");
FileOut = new FileOutputStream(theActualImageFile);
Also:
You need to deal with runtime permissions, if your targetSdkVersion is 23 or higher
A gallery app will see neither the directory nor the file, until you tell the MediaStore to index the newly-created JPEG
i think a had the same problem, actually the image do insert just fine in the memory, but when i tried to watch it didn't show as i expected, i solved it refreshing the gallery with the scanner class, used this code:
MediaScannerConnection.scanFile(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);
}
});
See this link for more info: How can I refresh the Gallery after I inserted an Image in android?
You may use the below code for asking runtime storage permission:
final int MyVersion = Build.VERSION.SDK_INT;
if (MyVersion > Build.VERSION_CODES.LOLLIPOP_MR1) {
if (!checkIfAlreadyhavePermission()) {
ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
} else {
TrySaveMediaStore() ;
}
checkIfAlreadyhavePermission() method:
private boolean checkIfAlreadyhavePermission() {
int result = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
return result == PackageManager.PERMISSION_GRANTED;
}
Add onRequestPermission():
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case 1: {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
TrySaveMediaStore();
} else {
Toast.makeText(this, "Please give your permission.", Toast.LENGTH_LONG).show();
}
break;
}
}
}
After creating the file scan MediaStore:
public void scanFile(Context c, File file, String mimeType) {
MediaScannerConnection
.scanFile(c, new String[] {file.getAbsolutePath()},
new String[] {mimeType}, null);
}
Yes, the problem is the media scanner. Yo can simply check the file using a terminal (download the app if you don't have it) and go manually to the directory. I had the same problem, but at least I know the file is there.

Android: how to write a file locally and save it to the Downloads

How do you write files locally and save them to the Downloads App in Android?
Android version: Nougut
The file is not showing in Downloads though. Here's my code:
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOWNLOADS), "foo.txt");
try {
String exampleString = "bar\nfoo";
InputStream is = new ByteArrayInputStream(exampleString.getBytes(Charset.forName("UTF-8")));
OutputStream os = new FileOutputStream(file);
byte[] data = new byte[is.available()];
is.read(data);
os.write(data);
is.close();
os.close();
} catch (IOException e) {
throw new AssertionError(e.toString());
}
MediaScannerConnection.scanFile(
getContext(),
new String[]{file.getAbsolutePath()},
null,
new MediaScannerConnection.OnScanCompletedListener() {
#Override
public void onScanCompleted(String s, Uri uri) {
Log.d(TAG, "String: "+ s);
Log.d(TAG, "Uri: "+ uri );
}
});
It is logging this in onScanCompleted so it seems like the file should show in Downloads but it doesn't.
D/SignupFragment: String: /storage/emulated/0/Download/foo.txt
D/SignupFragment: Uri: content://media/external/file/84691
I have read the Android docs on saving files
AndroidManifest.xml
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
The standard AOSP Downloads app only shows what DownloadManager downloaded. It does not show files placed in the Downloads/ directory by other means.

How to download image in android?

I have an image to the right and a button "download" to the left. the image is from my drawable. now,when i try to click the download i want to put the image to my sdcard downloads. Please help me i only see about download in url. is there other solution for this . Thanks
public class ImageDownloader {
public void download(String url, ImageView imageView) {
BitmapDownloaderTask task = new BitmapDownloaderTask(imageView);
task.execute(url);
}
}
/* class BitmapDownloaderTask, see below */
}
First, you need to get your Bitmap. You can already have it as an object Bitmap, or you can try to get it from the ImageView such as:
BitmapDrawable drawable = (BitmapDrawable) ImageView.getDrawable();
Bitmap bitmap = drawable.getBitmap();
Then you must get to directory (a File object) from SD Card such as:
File sdCardDirectory = Environment.getExternalStorageDirectory();
Next, create your specific file for image storage:
File image = new File(sdCardDirectory, "test.png");
After that, you just have to write the Bitmap such as:
boolean success = false;
// Encode the file as a PNG image.
FileOutputStream outStream;
try {
outStream = new FileOutputStream(image);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream);
/* 100 to keep full quality of the image */
outStream.flush();
outStream.close();
success = true;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Finally, just deal with the boolean result if needed. Such as:
if (success) {
Toast.makeText(getApplicationContext(), "Image saved with success",
Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(),
"Error during image saving", Toast.LENGTH_LONG).show();
}
Don't forget to add the following permission in your Manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

Code not writing database to sdcard

I'm using the following code to export a copy of my database to my sdcard.
public class AgUtility extends AgActivity{
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.utility);
try {
backupDatabase(getBaseContext());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void backupDatabase(Context context) throws IOException {
// Open your local db as the input stream
String inFileName = "data/data/com.agmanagement.todaysstudent/databases/todaysstudent.db";
Toast.makeText(context, "FileName Is "+ inFileName, Toast.LENGTH_LONG).show();
Log.i("The File In Is ", inFileName);
File dbFile = new File(inFileName);
FileInputStream fis = new FileInputStream(dbFile);
File outputDirectory = new File(
Environment.getExternalStorageDirectory() + "/student/");
outputDirectory.mkdir();
Log.d("MAKE DIR", dbFile.mkdir() + "");
String backupFileName = "/TodaysStudentTest.db3";
String outFileName = outputDirectory + backupFileName;
Toast.makeText(context, "Database backup names is " + outFileName , Toast.LENGTH_LONG)
.show();
// Open the empty db as the output stream
OutputStream output = new FileOutputStream(outFileName);
// transfer bytes from the inputfile to the outputfile
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(context, "Database backup complete", Toast.LENGTH_LONG)
.show();
}
}
The code seems to work properly, in that I don't get any errors the first Toast shows the correct database name, the second toast shows the output directory should be mnt/sdcard/student and the third shows the final target should be mnt/sdcard/student/TodaysStudentTest.db3
After that Toast fades, nothing, the final Toast never appears.
In my manifest I have
I am testing this on a Samsung Tablet and not on the emulator, i've also run it on a DroidX with the same result, no errors, but no folder is created.
Any ideas on what I'm doing wrong?
TIA
The permissions I'm using are
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.premission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.SET_DEBUG_APP" />
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.READ_CALENDAR"/>
<uses-permission android:name="android.permission.WRITE_CALENDAR"/>
I get the same results when running in the emulator - watching with the DDMS - Logcat show MAKE DIR fails.
I've tested for state with this
if (Environment.MEDIA_MOUNTED.equals(state)) {
// We can read and write the media
mExternalStorageAvailable = mExternalStorageWriteable = true;
Toast.makeText(getBaseContext(), "We Can Read And Write To The SDCARD", Toast.LENGTH_LONG).show();
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
// We can only read the media
mExternalStorageAvailable = true;
mExternalStorageWriteable = false;
Toast.makeText(getBaseContext(), "We Can Read The SDCARD", Toast.LENGTH_LONG).show();
} else {
// Something else is wrong. It may be one of many other states, but all we need
// to know is we can neither read nor write
mExternalStorageAvailable = mExternalStorageWriteable = false;
Toast.makeText(getBaseContext(), "We Can't read or write", Toast.LENGTH_LONG).show();
}
And it shows I'm supposed to be able to read and write, so there's something wrong with how I'm writing. I added this to also text
boolean success = false;
if(!outputDirectory.exists()){
Toast.makeText(getBaseContext(), "Folder Doesn't Exist ", Toast.LENGTH_LONG)
.show();
success = outputDirectory.mkdirs();
}
if (!success){
Toast.makeText(getBaseContext(), "Folder Not Created ", Toast.LENGTH_LONG)
.show();
}
else{
Toast.makeText(getBaseContext(), "Folder Created ", Toast.LENGTH_LONG)
.show();
}
Results are folder does not exist, and then mkdirs() fails.
REWRITE
Here is a different approach to coping a database file, without using SQL itself or a looping buffer.
NOTE: This isn't actually copied to the sdcard, the backup is stored in the original databases folder (which I like because you do not need WRITE_EXTERNAL_STORAGE permission).
public class FileIO extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
DBHelper db = new DBHelper(this);
try {
copyFile();
} catch (IOException ioe) {
ioe.printStackTrace();
} finally {
Log.i("Main", "Complete");
db.close();
finish();
}
}
public void copyFile() throws IOException {
File data = Environment.getDataDirectory();
String state = Environment.getExternalStorageState();
/* Create file first
FileOutputStream created = openFileOutput("copyFile.db", MODE_WORLD_READABLE);
created.close();
*/
String currentDBPath = "/data/<your_path>/databases/data.db";
String backupDBPath = "/data/<your_path>/databases/copyByFile.db";
File currentDB = new File(data, currentDBPath);
File backupDB = new File(data, backupDBPath);
if (currentDB.exists()) {
FileChannel src = new FileInputStream(currentDB).getChannel();
FileChannel dst = new FileOutputStream(backupDB).getChannel();
dst.transferFrom(src, 0, src.size());
src.close();
dst.close();
}
else
Log.i("Main", "Current db does not exist");
}
}
Try to manually create file before trying to write to it.
please make sure you have already created folder named "student" as you are using mkdir(). it will create directory by abstract path name..so if folder "student" does not exist it wont create new folder.. or try instead mkdirs(). it will created parent folder if necessary.
Important to remember to check spelling. uses-permission was mis-spelled as uses-premission, I had read the code so many times I read it as I wanted it to be. valuable lesson, walk away and take a break.

Categories