The code only works for some android versions - android

I wanted to save a picture from drawable. The application works, but only for android versions below API 22. In newer versions, the image is not saved in gallery.
My code:
public class MainActivity extends AppCompatActivity {
Bitmap anImage;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Drawable myDrawable = getResources().getDrawable(R.drawable.tapeta1, null);
anImage = ((BitmapDrawable) myDrawable).getBitmap();
}
public void addImageToGallery(View view) {
int e = view.getId();
switch (e) {
case R.id.button:
saveImageToExternalStorage(anImage);
Toast.makeText(getApplicationContext(), "Saved successfully, Check gallery", Toast.LENGTH_SHORT).show();
break;
}
}
private void saveImageToExternalStorage(Bitmap finalBitmap) {
String root = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString();
File myDir = new File(root + "/saved_images_1");
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);
finalBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
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);
}
});
}
}

Check if you have granted the storage permission to your app from
Settings -> Apps -> Your App Name ->Permissions
If this solution fixes your issue then please read - https://developer.android.com/training/permissions/requesting.html

Before you anthing else on oncreate method call requestpermissions by passing write external storage permission . This will show user to grant permission . You can override onpermissionsresult in the activity to see the result of permissions if granted you can go ahead with saving the file . If you dont want all that then save in internal storage . getfilesdir method will get you the path to app's internal directory and will not need runtime permissions .

You need to request RunTime permission from app.
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}

Related

Cannot save pdf files after updating my phone to Android 11

In one of my activities, I save an image in my App's directory subfolder and in the next activity I read the .png file and include it in a pdf file with some other data and save it in my App's directory, Everything worked fine until I updated my phone from Android 10 to 11. Now I get this error:
E/main: error java.io.FileNotFoundException: /storage/emulated/0/IranianMasonryBuildings/sjdnnd -- Fri Feb 12 11:49:36 GMT+03:30 2021.pdf: open failed: EPERM (Operation not permitted)
I tried many fixes online but none of them seem to work.
My manifest includes theses permissions and also the requestLegacyExternalStorage = true
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
android:requestLegacyExternalStorage="true"
compileSdkVersion and targetSdkVersion are set to 29, I tried to change the API level to 28 as mentioned in some answers to other questions but did not work.
This is how I try to create the pdf file:
private boolean isExternalStorageWritable(){
if(Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())){
Log.i("State", "Yes, it is writable");
return true;
}else{
return false;
}
}
public boolean checkPermission(String permission){
int check = ContextCompat.checkSelfPermission(this, permission);
return (check == PackageManager.PERMISSION_GRANTED);
}
public void checkPermission(String permission, int requestCode)
{
if (ContextCompat.checkSelfPermission(Results.this, permission)
== PackageManager.PERMISSION_DENIED) {
// Requesting the permission
ActivityCompat.requestPermissions(Results.this,
new String[] { permission },
requestCode);
}
else {
/*Toast.makeText(Results.this,
"Permission already granted",
Toast.LENGTH_SHORT)
.show();*/
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == STORAGE_PERMISSION_CODE){
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
/*Toast.makeText(Results.this,
"Storage Permission Granted",
Toast.LENGTH_SHORT)
.show();*/
}
else {
Toast.makeText(Results.this,
"Please grant access",
Toast.LENGTH_SHORT)
.show();
}
}
}
// Storage Permissions
private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
public static void verifyStoragePermissions(Activity activity) {
// Check if we have write permission
int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (permission != PackageManager.PERMISSION_GRANTED) {
// We don't have permission so prompt the user
ActivityCompat.requestPermissions(
activity,
PERMISSIONS_STORAGE,
REQUEST_EXTERNAL_STORAGE
);
}
}
public void writeExternalStorage (){
String state;
state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state) &&
checkPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
try {
//File storageDir2 = new File(Environment.getExternalStorageDirectory().toString(),
"/IranianMasonryBuildings/BluePrints");
File storageDir2 = new File(Environment.getExternalStorageDirectory().toString(),
"/IranianMasonryBuildings");
File f = new File(storageDir2, "BluePrint213.png");
Bitmap blueprint2 = BitmapFactory.decodeStream(new FileInputStream(f));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
PdfDocument myPdfDocument = new PdfDocument();
Paint myPaint = new Paint();
// Create a page description
PdfDocument.PageInfo myPageInfo1 = new PdfDocument.PageInfo.Builder(PageWidth,
PageHeight, PageNumber).create();
// start a page
PdfDocument.Page myPage1 = myPdfDocument.startPage(myPageInfo1);
Canvas canvas = myPage1.getCanvas();
myPaint = new Paint();
myPaint.setStyle(Paint.Style.STROKE);
myPaint.setStrokeWidth(3);
canvas.drawRect(200, 250, 1900, 2600, myPaint);
myPdfDocument.finishPage(myPage1);
File storageDir = new File(Environment.getExternalStorageDirectory().toString(),
"/IranianMasonryBuildings");
storageDir.mkdirs(); // make sure you call mkdirs() and not mkdir()
boolean wasSuccessful = storageDir.mkdirs();
if (!wasSuccessful) {
//Toast.makeText(getApplicationContext(), "mkdirs was not Successful ",
Toast.LENGTH_LONG).show();
}
File file2 = new File(storageDir, ProjectName + " -- " + Today + ".pdf");
try {
myPdfDocument.writeTo(new FileOutputStream(file2));
Toast.makeText(this, "The results are saved in" + "IranianMasonryBuildings",
Toast.LENGTH_LONG).show();
} catch (IOException e) {
Log.e("main", "error " + e.toString());
Toast.makeText(this, "Error!" + e.toString(), Toast.LENGTH_LONG).show();
}
// close the document
myPdfDocument.close();
Any ideas what is causing the problem and how to fix?
Android 11 (API level 30) further enhances the platform, giving better protection to app and user data on external storage. This release introduces several enhancements, such as opt-in raw file path access for media, batch edit operations for media, and an updated UI for the Storage Access Framework.
Follow this link
https://developer.android.com/about/versions/11/privacy/storage

Android 10 code to allow external directory access and grant permissions

Good day everyone,
I would like to ask a few questions, if I may.
I have an app that works on pre-Android 10 phones, but I see that various code changes have been made when accessing external directories. I don't have access to an Android 10 phone, so I have come up with the following code after perusal of many pages on Stackoverflow. I don't know of a way to test it myself, so could someone please kindly let me know what they think of this code:
String imageFileName;
String timestamp; // creation of the value omitted here
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
{
imageFileName = getApplicationContext().getExternalFilesDir(null).getAbsolutePath() + "/" + timeStamp + ".jpg";
}
else
{
imageFileName = Environment.getExternalStorageDirectory()+ "/" + timeStamp + ".jpg";
}
OutputStream fout = null; // Now write out the image to external directory
File imageFile = new File(imageFileName);
try {
fout = new FileOutputStream(imageFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, 95, fout);
fout.flush();
fout.close();
} catch (Exception e) {
// do stuff
}
// Now, "update" the directory using MediaScannerConnection.scanFile to refresh
// its contents when viewed on the device
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
{
MediaScannerConnection.scanFile(activityReference.get(), new String[]{getApplicationContext().getExternalFilesDir(null).getAbsolutePath().toString()}, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri)
{
}
});
}
else // Not Android 10
{
MediaScannerConnection.scanFile(activityReference.get(), new String[]{Environment.getExternalStorageDirectory().toString()}, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri)
{
}
});
}
The parts above that don't explicitly reference Android 10 work fine
The other questions are about permissions to access the filestore, which I would like to read/write to. I have these declared in the Manifest and currently my code, for pre-Android 10 is
if( (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
|| (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED))
{
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, PERMISSION_ALL);
}
if(ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, PERMISSION_ALL);
}
I am loading an image file and, again pre-Android 10, I have
findbutton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
startActivityForResult(intent, 7);
}
});
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
switch(requestCode){
case 7:
if(resultCode==RESULT_OK){
Uri PathHolder = data.getData();
try
{
img = BitmapFactory.decodeStream(getContentResolver().openInputStream(PathHolder));
}
catch(Exception e)
{
//
}
// Do more image related stuff here
}
break;
}
}
Is there anything here that needs to have an "if..then" statement to account for file access in Android 10?
Thanks in advance for any help given.

java.io.FileNotFoundException Permission Denied when saving image

private void saveImage(Bitmap bitmap){
try {
String path = Environment.getExternalStorageDirectory().toString();
Toast.makeText(getActivity(), path, Toast.LENGTH_SHORT).show();
OutputStream fOut = null;
File file = new File(path, mWallpaper.getId().toString() + ".jpg");
fOut = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 85, fOut); // saving the Bitmap to a file compressed as a JPEG with 85% compression rate
fOut.flush();
fOut.close();
MediaStore.Images.Media.insertImage(getActivity().getContentResolver(),file.getAbsolutePath(),file.getName(),file.getName());
} catch (MalformedURLException e) {
Toast.makeText(getActivity(), "Error saving wallpaper. MAL", Toast.LENGTH_SHORT).show();
} catch (IOException e1) {
Toast.makeText(getActivity(), "Error saving wallpaper.", Toast.LENGTH_SHORT).show();
e1.printStackTrace();
}
}
I added this to my AndroidManifests:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
I am trying to save an image to /storage/emulated/0/.
EDIT
int permissionCheck = ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(),
Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
} else {
ActivityCompat.requestPermissions(getActivity(),
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
permissionCheck);
}
}
I've added this to onCreate() for my fragment but I still not a request.
if (Build.VERSION.SDK_INT >= 23) {
int permissionCheck = ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
}
}
Do this if you are using >=api 23. After this add your code. With this code you ask run-time permission from the user.
Requesting Permissions at Run Time Documentation from official Android site
Another solution is to use
getApplicationContext().getFilesDir().getPath()
rather than
Environment.getExternalStorageDirectory()
If you implement this solution, you do not need to add any permission to Manifest because your files are saved in Application directory, not SD Card.
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
} else {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},23
);
}
}
try this also you can follow folling link
http://www.theappguruz.com/blog/runtime-permissions-in-android-marshmallow

How Android Saving Files?

I need to save some files into my Android phone.
So I used something like:
FileOutputStream os = null;
try{
os = new FileOutputStream("/root/sdcard/DCIM/1.jpg");
os.write(bytes);
os.close();
}catch(FileNotFoundException e){}
When I do this, it would say something like
java.io.FileNotFoundException: /root/sdcard/DCIM/1.jpg (Permission denied)
Btw, I already requestd permission in AndroidManifest.xml using something like:
<user-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
I also tried
getFilesDir().getAbsolutePath();
And it actually refers to
/data/user/0/come.package.xxx/files
Which I have no idea where this path is because I could not find it on my phone.
When I use ASUS File Manager, I see the path is /root/sdcard/..., but I don't even have a sdcard in my phone, I have been using iPhone for many years now, so I don't know how the Android file system works now.
This is really confusing for me, could someone explain it to me how the Android file system works? Thank you all!
if you are using android 6.0 Marsh or higher android version u need to give run time permission to access.try below code
if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
camera.setEnabled(false);
ActivityCompat.requestPermissions(getActivity(), new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE }, 0);
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == 0) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED
&& grantResults[1] == PackageManager.PERMISSION_GRANTED) {
//permission will get success here
//do what you want
}
else {
//Permission not granted
Toast.makeText(getActivity(),"You need to grant camera permission to use camera",Toast.LENGTH_LONG).show();
}
}
}
To save image on Android:
private String saveToInternalStorage(String name, Bitmap bitmapImage){
ContextWrapper cw = new ContextWrapper(context);
// path to /data/data/yourapp/app_data/imageDir
File directory = cw.getDir(IMAGE_TAG, Context.MODE_PRIVATE);
// Create imageDir
File mypath = new File(directory, name + ".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 (FileNotFoundException e) {
e.printStackTrace();
} finally {
try {
if (fos != null) {
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return directory.getAbsolutePath();
}
To load image:
public void loadImage(ImageView imageView) {
// get path
ContextWrapper cw = new ContextWrapper(context);
File directory = cw.getDir(IMAGE_TAG, Context.MODE_PRIVATE);
String path = directory.getAbsolutePath();
// load image
try {
File f = new File(path, name + ".jpg");
Bitmap b = BitmapFactory.decodeStream(new FileInputStream(f));
imageView.setImageBitmap(b);
imageView.setVisibility(View.VISIBLE);
} catch (FileNotFoundException e) {
e.printStackTrace();
Log.d("Image", "Image file not found.");
}
}
if your are using marshmallow or latest version of android so you need to provide permission at run time, on your buttom click than you need to call your code for saving file into sd card.
after than do like this,
public void onClick(View v) {
// write on SD card file data in the text box
try {
File myFile = new File("/sdcard/mysdfile.txt");
myFile.createNewFile();
FileOutputStream fOut = new FileOutputStream(myFile);
OutputStreamWriter myOutWriter =
new OutputStreamWriter(fOut);
myOutWriter.append(txtData.getText());
myOutWriter.close();
fOut.close();
Toast.makeText(getBaseContext(),
"Done writing SD 'mysdfile.txt'",
Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Toast.makeText(getBaseContext(), e.getMessage(),
Toast.LENGTH_SHORT).show();
}
}

tess-two won't initialise, even with correct permissions

Here's what I'm currently doing:
tess-two is set up in my Android project
I have permissions specified in the AndroidManifest.xml of my main app (not the tess-two AndroidManifest.xml):
I also check for permissions explicitly in my code:
int readPermission = ActivityCompat.checkSelfPermission(this, READ_EXTERNAL_STORAGE);
int writePermission = ActivityCompat.checkSelfPermission(this, WRITE_EXTERNAL_STORAGE);
// Check we have both read and write permissions
if (readPermission != PackageManager.PERMISSION_GRANTED
|| writePermission != PackageManager.PERMISSION_GRANTED)
{
// We don't have permission so prompt the user
ActivityCompat.requestPermissions(
this,
new String[] {READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE},
REQUEST_EXTERNAL_STORAGE
);
}
else
{
Log.d(TAG, "Read and write external permissions granted");
initTess();
}
Try to initialise the TessBaseAPI:
private void initTess()
{
// Check we have the eng.traineddata file in the correct place
mTessDataPath = getFilesDir() + "/tesseract/";
checkTessFile(new File(mTessDataPath + "tessdata/"));
// Initialise TessBaseAPI
mTess = new TessBaseAPI();
mTess.init(mTessDataPath, "eng");
}
private void checkTessFile(File dir)
{
// Check if directory already exists
if (dir.exists())
{
// Check if file already exists
String dataFilePath = mTessDataPath + "tessdata/eng.traineddata";
File datafile = new File(dataFilePath);
if (!datafile.exists())
{
// If file doesn't exist, copy it over from assets folder
copyTessFiles();
}
}
else
{
if (dir.mkdirs())
{
// If directory doesn't exist, but we can create it, copy file from assets folder
copyTessFiles();
}
}
}
private void copyTessFiles()
{
try
{
// Location we want the file to be at
String filepath = mTessDataPath + "tessdata/eng.traineddata";
// Get access to AssetManager
AssetManager assetManager = getAssets();
// Open byte streams for reading/writing
InputStream instream = assetManager.open("tessdata/eng.traineddata");
OutputStream outstream = new FileOutputStream(filepath);
// Copy the file to the location specified by filepath
byte[] buffer = new byte[1024];
int read;
while ((read = instream.read(buffer)) != -1)
{
outstream.write(buffer, 0, read);
}
outstream.flush();
outstream.close();
instream.close();
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults)
{
switch (requestCode)
{
case REQUEST_EXTERNAL_STORAGE:
{
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED)
{
// Initialise Tesseract API
initTess();
}
return;
}
}
}
When I run the app, I get the following error in my logs:
E/Tesseract(native): Could not initialize Tesseract API with language=eng!
I have no idea where to go from here, so any help or advise would be hugely appreciated, thank you :)
Make sure you're using the right version of the training data files.

Categories

Resources