I'm trying to save my images to a folder into my Samsung galaxy s6 edge. I'm a beginner and have created an application to practice take an intent image and return the image to my application where I then choose an image filter and further want to save it to my device. I cant understand why it doesn't work. The error I get is:
W/System.err: java.io.FileNotFoundException: /storage/emulated/0/Pictures/Pictures.jpg: open failed: EACCES (Permission denied)
And here is the code:
public void savePhoto(View view) {
if(currentBitmap != null) {
File storageLoc = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File file = new File(storageLoc, "Pictures.jpg");
try {
FileOutputStream fos = new FileOutputStream(file);
currentBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.flush();
fos.close();
Context context = getApplicationContext();
Intent scanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
scanIntent.setData(Uri.fromFile(file));
context.sendBroadcast(scanIntent);
Toast.makeText(getApplicationContext(), "Your image has been saved!", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
}
} else {
Toast.makeText(getApplicationContext(), "No image taken!", Toast.LENGTH_SHORT).show();
}
}
Im using API15 if it have something with that to do. The rest of my code works good without saving images. If someone can see the problem I would be grateful.
Your android version seems to be above Marshmallow. Means you need to check permission at runtime. As log shows Permission denied.
You can do it in two ways
Checking permission by ContextCompat.checkSelfPermission() way
By declaring ANDROID_BUILD_TARGET_SDK_VERSION=22 in gradle
Related
I have followed a lot of guides of how to save and reload images to the phone and came to this:
In the videos it works but for some reason it does not work for me.
Is there maybe a better version of doing this? And how can I read from this later so I can paste it with Picasso into another ImageView?
(Update: Logcat is saying : Logcat says this: java.io.FileNotFoundException: /storage/emulated/0/LiFit/profileimage.jpg (No such file or directory) but I am clearly creating this folder wiht the mkdir command so why isn´t it workiing ?)
BitmapDrawable drawable = (BitmapDrawable) profilBild.getDrawable();
Bitmap bitmap = drawable.getBitmap();
File sdCard = Environment.getExternalStorageDirectory();
File directory = new File(sdCard.getAbsolutePath()+ "/LiFit");
directory.mkdir();
String fileName = String.format("%d.jpg", System.currentTimeMillis());
File outFile = new File(directory, fileName);
Toast.makeText(getActivity(), "Pic saved", Toast.LENGTH_LONG).show();
try {
outputStream = new FileOutputStream(outFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
try {
outputStream.flush();
outputStream.close();
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intent.setData(Uri.fromFile(outFile));
getContext().sendBroadcast(intent);
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Apparently you need to change the permissions in the app settings to....
I am developing an app for filling pdf forms, I am saving the pdf to the internal storage and then sharing it using the intent ACTION_CREATE_DOCUMENT. This intent returns a URI which i then copy my local pdf into.
All this works fine however the intent opens a file explorer popup so that the user can choose where to save the pdf, and here in lies the problem, when the user presses SAVE; the app creates a 0b file in that location (as it should), but then it reopens the file explorer prompting the user to SAVE again, this happens two or three times and then it finally close for real at which point the pdf data overwrites the latest of the now numerous 0b files.
public int WRITE_REQUEST_CODE=45;
...
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
public void buttonExport(View view) {
Toast.makeText(this, "Exporting - This will take around 1min", Toast.LENGTH_LONG).show();
// Template of PDF with acrofields (template.pdf).
// TRY to open the pdf stored in the raw res directory
// then convert it to a file object by copying it
try {
//
InputStream inputStream =null;
if (template.equals("crfminortemplate")){
inputStream = getResources().openRawResource(R.raw.crfminorpdftemplat);
}
else if (template.equals("crfmajortemplate")){
inputStream = getResources().openRawResource(R.raw.crfmajorpdftemplat);
}
File tempFile = new File(getFilesDir(),template);
//
copyFile(inputStream, new FileOutputStream(tempFile));
// Now Questions res is tempFile ..
} catch (IOException e) {
throw new RuntimeException("Can't create temp file ", e);
}
try {
PDFManipulation.fillPDF(view, template, fileName, Answers);
} catch (IOException e) {
e.printStackTrace();
}
catch (NullPointerException e)
{
e.printStackTrace();
}
Toast.makeText(this, "Export Complete - save to drive or email", Toast.LENGTH_LONG).show();
sharePDF(getFilesDir()+"/"+fileName+".pdf");
}
private void sharePDF(String PDFPPath) {
Uri path = FileProvider.getUriForFile(this, "com.example.cst_app_v3", new File(getFilesDir(),fileName+".pdf"));
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_TEXT, "Sent from CST App Android " + PDFPPath);
shareIntent.putExtra(Intent.EXTRA_STREAM, path);
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
shareIntent.setType("application/pdf");
startActivityForResult(shareIntent,0);
Intent saveIntent = new Intent();
saveIntent.setAction(Intent.ACTION_CREATE_DOCUMENT);
saveIntent.putExtra(Intent.EXTRA_TITLE,fileName+".pdf");
saveIntent.addCategory(Intent.CATEGORY_OPENABLE);
saveIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
saveIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
saveIntent.setType("application/pdf");
startActivityForResult(saveIntent,WRITE_REQUEST_CODE);
Intent chooserIntent = Intent.createChooser(shareIntent, "Share or Save ...");
Intent[]arrayofintent = {saveIntent};
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS,arrayofintent);
startActivityForResult(chooserIntent,0);
startActivity(chooserIntent);
Log.d("Alert",path.getAuthority()+" "+ path.getPath());
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
if (resultCode == RESULT_OK && requestCode == WRITE_REQUEST_CODE) {
//DO THE COPY PASTE FROM LOCAL to THE URI data
}
}
Again
I want the user to start the save intent and have the file selector popup once let the user name the file and choose the save location, press save and then return to my the my app where the pdf is copied to the location they specified
if anyone knows/has experienced this issue or thinks they know what might be happening it would be great to hear from you.
Every time you call startActivityForResult or startActivity it will start a new Activity.
So I count 4 of these in your example code but with only 2 calls that will actually return a result that would cause a file to be written.
To fix this just remove all the startActivityForResult or startActivity EXCEPT for the third one which you change to startActivityForResult(chooserIntent,WRITE_REQUEST_CODE);
This works (was tested) BUT provides a very bad UI experience as you have to know to select the Files App to save the document.
It would be much better to split these to different types of action in to separate menu items, Buttons, Floating Action Buttons, or however you getting the user to "Share or Save" as you can provide a better UI than the Intent chooser.
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!
I have the following code to launch application chooser to open any type of file, but when ever I try to open the file I get the message file cannot be opened.
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(path));
if(type.contains("image")) {
intent.setDataAndType(Uri.parse(path),type);
}else if(extension.equalsIgnoreCase("txt")){
intent.setDataAndType(Uri.parse(path),"text/plain");
}else{
intent.setDataAndType(Uri.parse(path),type);
}
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
Intent intentOpen = Intent.createChooser(intent, "Open File");
try {
activity.startActivity(intentOpen);
} catch (ActivityNotFoundException e) {
}
any help will be appreciated, thanks in advance
I solved it, i had to add file:// at the start of the path to open the file.
path="file://"+Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath()+"/"+myFileName;
I've searched for a while on the internet but I didnt find a solution!
In my project I put a PDF file inside the drawable folder (I dont know where else to put it, honestly). That PDF is a menù that shows the user all the food he can find in that restaurant.
There is a button that enables the user to open that PDF file. By clicking over it I receive a error message. More or less it says that the App cant file my file: "Impossibile to open menuristorante.pdf".
I created a method to open that file and this is the code I wrote:
public void openMenuRistorante(View view)
{
File pdfFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/menuristorante.pdf");
Uri path = Uri.fromFile(pdfFile);
Intent pdfIntent = new Intent(Intent.ACTION_VIEW);
pdfIntent.setDataAndType(path, "application/pdf");
pdfIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
try{
startActivity(pdfIntent);
}catch(ActivityNotFoundException e){
Toast.makeText(this, "Nessuna Applicazione per leggere i pdf", Toast.LENGTH_SHORT).show();
}
}
Probably I am wrong putting my file in the wrong directory.. But where have I to put it? Keep in mind that my PDF file must be already into the app, so it must be inside the phone when the user installs this App.
Thanks
Put the PDF file in the assets folder and try using the following code:
Uri file= Uri.parse("file:///android_asset/mypdf.pdf");
String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(file.toString()));
try {
Intent i;
i = new Intent(Intent.ACTION_VIEW);
i.setDataAndType(file,mimeType);
startActivity(i);
} catch (ActivityNotFoundException e) {
Toast.makeText(this,
"No Application Available to view this file type",
Toast.LENGTH_SHORT).show();
}
I'm doing a similar thing in my app, I have my files though in the download folder of my mobile in a sub-folder called "Documents", I guess you could do the same, it's better than keeping it in drawable. here's the code I use :
try {
File file = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS + "/Documents/" + fileName);
Intent intent = new Intent("com.adobe.reader");
intent.setType("application/pdf");
intent.setAction(Intent.ACTION_VIEW);
Uri uri = Uri.fromFile(file);
intent.setDataAndType(uri, "application/pdf");
startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(Documents.this, "Erreur d'ouverture du fichier", Toast.LENGTH_LONG).show();
}