Below is my code for MainActivity.java.The error according to toasts is in creating directory.
MainActivity.java
#Override
protected void onActivityResult(int requestcode,int resultcode,Intent data){
super.onActivityResult(requestcode,resultcode,data);
if (requestcode == TAKE_PICTURE)
{
if(resultcode== Activity.RESULT_OK){
ImageView imageHolder = (ImageView)findViewById(R.id.image_camera);
Bitmap bitmap = (Bitmap)data.getExtras().get("data");
String partFilename = currentDateFormat();
storeCameraPhotoInSDCard(bitmap, partFilename);
// display the image from SD Card to ImageView Control
String storeFilename = "photo_" + partFilename + ".jpg";
Bitmap mBitmap = getImageFileFromSDCard(storeFilename);
imageHolder.setImageBitmap(mBitmap);
}
}
}
private String currentDateFormat(){
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HH_mm_ss");
String currentTimeStamp = dateFormat.format(new Date(0));
return currentTimeStamp;
}
/* Checks if external storage is available for read and write */
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
Toast.makeText(MainActivity.this, "WriteMode ON", Toast.LENGTH_SHORT).show();
return true;
}
Toast.makeText(MainActivity.this, "WriteMode OFF", Toast.LENGTH_SHORT).show();
return false;
}
/* Checks if external storage is available to at least read */
public boolean isExternalStorageReadable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state) ||
Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
Toast.makeText(MainActivity.this, "Mounted or ReadMode", Toast.LENGTH_SHORT).show();
return true;
}
Toast.makeText(MainActivity.this, "no-Mounted or no-ReadMode", Toast.LENGTH_SHORT).show();
return false;
}
private void storeCameraPhotoInSDCard(Bitmap bitmap, String currentDate){
boolean isAvailable=isExternalStorageWritable();
if(isAvailable){
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG,90, bytes);
String imgUri = "photo_" + currentDate + ".jpg";
File appDirectory = new File(Environment.getExternalStorageDirectory(),"CountDotsAppImages");
boolean success = appDirectory.mkdirs();
if (success) {
Toast.makeText(MainActivity.this, "Directory Created", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this, "Failed - Error", Toast.LENGTH_SHORT).show();
}
File destination = new File(Environment.getExternalStorageDirectory(),"CountDotsAppImages/"+imgUri);
FileOutputStream fo;
try {
destination.createNewFile();
fo = new FileOutputStream(destination);
fo.write(bytes.toByteArray());
fo.close();
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
private Bitmap getImageFileFromSDCard(String filename){
File storageDir = new File(Environment.getExternalStorageDirectory() + "/", "CountDotsAppImages");
Bitmap bitmap = null;
File imageFile = new File(storageDir.getPath()+File.separator + filename);
try {
FileInputStream fis = new FileInputStream(imageFile);
Toast.makeText(MainActivity.this, imageFile.toString() , Toast.LENGTH_LONG).show();
bitmap = BitmapFactory.decodeStream(fis);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return bitmap;
}
AndroidManifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> permission is added
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.countdots"
android:versionCode="1"
android:versionName="1.0" android:installLocation="auto">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="23" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Toasts Output :
Mounted or ReadMode
WriteMode ON
Directory Does Not Exist, Create It
Failed -Error //Error in creating directory mkdir
I tried using both mkdir() and mkdirs()
Figured it out.
As, I was compiling with Android 6.0. It requires user to grant permission.
So,following code should be inserted and checked if user grants app permission or not.Then if user grants permission to read and write manifest will be updated and volia !!!
if (Build.VERSION.SDK_INT >= 23) {
if (ContextCompat.checkSelfPermission(MainActivity.this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(MainActivity.this, android.Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE, android.Manifest.permission.READ_EXTERNAL_STORAGE},
1);
} else {
//do something
}
} else {
//do something
}
This code works for me
try{
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG,90, bytes);
imgUri = "photo_" + System.currentTimeMillis() + ".jpg";
File appDirectory = new File(Environment.getExternalStorageDirectory(),"CountDotsAppImages");
appDirectory.mkdirs();
File destination = new File(Environment.getExternalStorageDirectory(),"CountDotsAppImages/"+imgUri);
FileOutputStream fo;
try {
destination.createNewFile();
fo = new FileOutputStream(destination);
fo.write(bytes.toByteArray());
fo.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
For adding directory you can use this method.
isAvailable=ExternalStorageChecker.isExternalStorageWritable();
if(isAvailable){
dir = new File(myContext.getExternalFilesDir(null), newAlbumDir.getText().toString().trim());
if(!dir.mkdirs()){
Log.e("++++++","Directoy Already Exist");
Log.e("External Directory Path","++++"+dir.getAbsolutePath());
}
else{
Log.e("++++","Directory Created");
Toast.makeText(myContext,"File Created on External",Toast.LENGTH_SHORT).show();
Log.e("Externa Directory Path","++++"+dir.getAbsolutePath());
}
}
else{
Toast.makeText(myContext,"File Created on Internal",Toast.LENGTH_SHORT).show();
Log.e("Internal Directory Path","++++"+myContext.getFilesDir().getPath());
dir=new File(myContext.getFilesDir(),newAlbumDir.getText().toString());
}
After it created the directory(dir) you can use to create the File.
Related
This code is working till android 10 but now I want to upgrade it to android 11. I can save the jpeg & even can read the directory but I can't save pdf in android 11. I tried everything on internet but can't find anything. Can someone help me.
My Manifest
<uses-permission android:name="com.samsung.android.providers.context.permission.WRITE_USE_APP_FEATURE_SURVEY" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<application
android:name=".MyApplication"
android:allowBackup="true"
android:requestLegacyExternalStorage="true"
android:preserveLegacyExternalStorage="true"
android:usesCleartextTraffic="true"
android:networkSecurityConfig="#xml/network_security_config"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher"
android:supportsRtl="true"
android:theme="#style/AppTheme">
My Bitmap function
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
public void saveBitmap(Bitmap bmp) {
File filename;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R){
try {
String path1 = Environment.getExternalStorageDirectory().toString() + File.separator + "Documents";
Log.i("in save()", "after mkdir");
File file = new File(path1 + "/" + "Premium Scanner/IMAGES");
if (!file.exists())
file.mkdirs();
filename = new File(file.getAbsolutePath() + "/" + "IMG_" + timeStamp + ".jpg");
Log.i("in save()", "after file");
FileOutputStream out = new FileOutputStream(filename);
Log.i("in save()", "after outputstream");
bmp.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
ContentValues image = getImageContent(filename);
getActivity().getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, image);
createPdf(bmp);
Toast.makeText(getActivity().getApplicationContext(), "Image saved successfully", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
}
}
}
My PDF Function
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
private void createPdf(Bitmap bitmap) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R){
WindowManager wm = (WindowManager) getActivity().getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
DisplayMetrics displaymetrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
float hight = displaymetrics.heightPixels;
float width = displaymetrics.widthPixels;
int convertHighet = (int) hight, convertWidth = (int) width;
PdfDocument document = new PdfDocument();
PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(bitmap.getWidth(), bitmap.getHeight(), 1).create();
PdfDocument.Page page = document.startPage(pageInfo);
Canvas canvas = page.getCanvas();
Paint paint = new Paint();
paint.setColor(Color.parseColor("#ffffff"));
canvas.drawPaint(paint);
bitmap = Bitmap.createScaledBitmap(bitmap, bitmap.getWidth(), bitmap.getHeight(), true);
paint.setColor(Color.BLUE);
canvas.drawBitmap(bitmap, 0, 0, null);
document.finishPage(page);
// write the document content
String path1 = Environment.getExternalStorageDirectory().toString() + File.separator + "Documents";
Log.i("in save()", "after mkdir");
File file = new File(path1 + "/" + "Premium Scanner/PDF/");
if (!file.exists())
file.mkdirs();
File filepath = new File(file.getAbsolutePath() + "/" + "FILE_" + timeStamp + ".pdf");
Log.i("in save()", "after file");
try {
document.writeTo(new FileOutputStream(filepath));
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(getActivity(), "Something wrong: " + e.toString(), Toast.LENGTH_LONG).show();
}
document.close();
}
}
Image Content Function
public ContentValues getImageContent(File parent) {
ContentValues image = new ContentValues();
try{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R){
image.put(MediaStore.MediaColumns.TITLE, "IMG_" + timeStamp);
image.put(MediaStore.MediaColumns.DISPLAY_NAME, "IMG_" + timeStamp);
image.put(MediaStore.Images.Media.DESCRIPTION, "App Image");
image.put(MediaStore.MediaColumns.DATE_ADDED, System.currentTimeMillis());
image.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpg");
image.put(MediaStore.MediaColumns.ORIENTATION, 0);
image.put(MediaStore.MediaColumns.BUCKET_ID, parent.toString().toLowerCase().hashCode());
image.put(MediaStore.MediaColumns.BUCKET_DISPLAY_NAME, parent.getName().toLowerCase());
image.put(MediaStore.MediaColumns.SIZE, parent.length());
image.put(MediaStore.Images.Media.RELATIVE_PATH, parent.getAbsolutePath());
dismissDialog();
getActivity().finish();
}
} catch (Exception e){
Toast.makeText(getActivity(), "Image not saved \n" + e.getMessage(), Toast.LENGTH_SHORT).show();`
}
return image;
}
I'm having a problem downloading and installing the app.
On android below 10 this code works.
I am trying to update my application from the server.
Manifest
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
...
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths" />
</provider>
Activity
If there is an update, then a snackbar appears and by clicking update the application should download and install
private void showSnackbar() {
Snackbar snackbar =
Snackbar.make(
findViewById(android.R.id.content),
"update available",
Snackbar.LENGTH_INDEFINITE);
snackbar.setAction("update", new View.OnClickListener() {
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
#Override
public void onClick(View v) {
try {
if (checkPermission()) {
UpdateApp atualizaApp = new UpdateApp();
atualizaApp.setContext(CommonListObjects.this);
atualizaApp.execute("http://195.200.000.000:0000/app.apk");
} else {
requestPermission();
}
} catch (android.content.ActivityNotFoundException anfe) {
}
}
});
snackbar.show();
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if (requestCode == PERMISSION_REQUEST_CODE) {
if (grantResults.length > 0) {
boolean locationAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
boolean cameraAccepted = grantResults[1] == PackageManager.PERMISSION_GRANTED;
if (locationAccepted && cameraAccepted) {
UpdateApp updateApp = new UpdateApp();
updateApp.setContext(CommonListObjects.this);
updateApp.execute("http://195.200.000.000:0000/app.apk");
}
}
}
}
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
private boolean checkPermission() {
int result = ContextCompat.checkSelfPermission(getApplicationContext(), WRITE_EXTERNAL_STORAGE);
int result1 = ContextCompat.checkSelfPermission(getApplicationContext(), READ_EXTERNAL_STORAGE);
return result == PackageManager.PERMISSION_GRANTED && result1 == PackageManager.PERMISSION_GRANTED;
}
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
private void requestPermission() {
ActivityCompat.requestPermissions(this, new String[]{WRITE_EXTERNAL_STORAGE, READ_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE);
}
this is how it loads
#Override
protected String doInBackground(String... arg0) {
try {
URL url = new URL(arg0[0]);
HttpURLConnection c = (HttpURLConnection) url.openConnection();
c.setRequestMethod("GET");
c.setDoOutput(true);
c.connect();
int lenghtOfFile = c.getContentLength();
String PATH = Environment.getExternalStorageDirectory() + "/" + "app.apk";
File file = new File(PATH);
boolean isCreate = file.mkdirs();
File outputFile = new File(file, "app.apk");
if (outputFile.exists()) {
boolean isDelete = outputFile.delete();
}
FileOutputStream fos = new FileOutputStream(outputFile);
InputStream is = c.getInputStream();
byte[] buffer = new byte[1024];
int len1;
long total = 0;
while ((len1 = is.read(buffer)) != -1) {
total += len1;
fos.write(buffer, 0, len1);
publishProgress((int) ((total * 100) / lenghtOfFile));
}
fos.close();
is.close();
if (mPDialog != null)
mPDialog.dismiss();
installApk();
} catch (Exception e) {
Log.e("UpdateAPP", "Update error! " + e.getMessage());
}
return null;
}
this is how the installation works
void installApk(){
String PATH = Environment.getExternalStorageDirectory() + "/" + "app.apk"+ "/" + "app.apk";
File file = new File(PATH);
if(file.exists()) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(uriFromFile(getApplicationContext(), new File(PATH)), "application/vnd.android.package-archive");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
try {
getApplicationContext().startActivity(intent);
} catch (ActivityNotFoundException e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(),"Error in opening the file!",Toast.LENGTH_LONG).show();
}
}else{
Toast.makeText(getApplicationContext(),"installing",Toast.LENGTH_LONG).show();
}
}
Uri uriFromFile(Context context, File file) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider", file);
} else {
return Uri.fromFile(file);
}
}
on android below 10 works, but in 10 and 11 does not work. even the file does not load.
Java code:
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_camera:
if (i==21) {
Toast.makeText(FileUploadActivity.this,R.string.max_file_upload,Toast.LENGTH_SHORT).show();
}
else {
++i;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ActivityCompat.checkSelfPermission(FileUploadActivity.this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, MY_PERMISSIONS);
} else if (ActivityCompat.checkSelfPermission(FileUploadActivity.this, android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{android.Manifest.permission.CAMERA}, MY_PERMISSIONS);
} else {
openCamera();
}
} else {
openCamera();
}
}
break;
public void openCamera() {
File photoFile = null;
try {
photoFile = createTempFile("Images", "IMG_", ".jpg"); //error
Log.i(TAG, "openCamera: Camera access"+photoFile);
} catch (IOException e) {
e.printStackTrace();
}
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
takePictureIntent.putExtra("PhotoPath", mCameraPhotoPath);
if (photoFile != null) {
mCameraPhotoPath = photoFile.getAbsolutePath();
}else {
Toast.makeText(FileUploadActivity.this,"Unable to open",Toast.LENGTH_LONG).show();
}
// takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
// startActivityForResult(takePictureIntent, SELECT_PICTURE);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(photoFile));
} else {
File file = new File(Uri.fromFile(photoFile).getPath());
Uri photoUri = FileProvider.getUriForFile(getApplicationContext(), getApplicationContext().getPackageName() + ".provider", file);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
}
takePictureIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
if (takePictureIntent.resolveActivity(getApplicationContext().getPackageManager()) != null) {
startActivityForResult(takePictureIntent, SELECT_PICTURE);
}
}
private File createTempFile(String storage,String fileName,String fileType) throws IOException {
File imageFile = null;
File folder = new File(Environment.getExternalStorageDirectory() +
File.separator + "CTrack" + File.separator + storage);
boolean success = true;
if (!folder.exists()) {
success = folder.mkdirs();
}
if (success) {
String timeStamp = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").format(new Date());
String imageFileName = fileName + timeStamp + "_";
imageFile = File.createTempFile(imageFileName, fileType, folder);
}
return imageFile;
}
private String encodeImage(String path) {
File imagefile = new File(path);
FileInputStream fis = null;
String encodeResponse="";
try {
fis = new FileInputStream(imagefile);
Bitmap bm = BitmapFactory.decodeStream(fis);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] b = baos.toByteArray();
encodeResponse=Base64.encodeToString(b, Base64.DEFAULT);
} catch (FileNotFoundException e) {
e.printStackTrace();
encodeResponse="nofile";
}
catch (OutOfMemoryError e) {
e.printStackTrace();
encodeResponse="memory";
}
return encodeResponse;
}
Permissions:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<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" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
error:
2021-05-03 12:52:30.921 9669-9669/com.transasia.ctrack E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.transasia.ctrack, PID: 9669
android.os.FileUriExposedException: file:///storage/emulated/0/CTrack/Images/IMG_2021-05-03T12%3A52%3A30_6074100336714487332.jpg exposed beyond app through ClipData.Item.getUri()
at android.os.StrictMode.onFileUriExposed(StrictMode.java:2083)
at android.net.Uri.checkFileUriExposed(Uri.java:2388)
at android.content.ClipData.prepareToLeaveProcess(ClipData.java:977)
at android.content.Intent.prepareToLeaveProcess(Intent.java:10759)
at android.content.Intent.prepareToLeaveProcess(Intent.java:10744)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1703)
at android.app.Activity.startActivityForResult(Activity.java:5192)
at androidx.fragment.app.FragmentActivity.startActivityForResult(FragmentActivity.java:675)
at android.app.Activity.startActivityForResult(Activity.java:5150)
App is working in android 9 and below 9 but when it comes to android 10 and 11, app is crashing and getting file error. I thought problem with creating temp file because there it gives me an error.
Thank you,........................................................................Thanks...........................................................................................................
Try this
In Manifest file - add provider inside
<application android:requestLegacyExternalStorage="true">
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths" />
</provider>
create provider_path.xml (res -> xml -> provider_path.xml)
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path
name="external_files"
path="." />
</paths>
Add Camera permission
<uses-permission android:name="android.permission.CAMERA"/>
<uses-feature android:name="android.hardware.camera" />
This question already has answers here:
Accessing external storage in Android API 29
(2 answers)
Closed 2 years ago.
I have a pdf file in the Download Storage and I try show it using intent, I already have three PDF viewer apps, but none of them sucessfully show the file, but if I open the pdf directly via file explorer its show just fine.
here is my code :
File kuda = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
File file1 = new File(kuda,"KK.pdf");
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri= FileProvider.getUriForFile(getContext(), BuildConfig.APPLICATION_ID+".provider",file1);
intent.setDataAndType(uri, "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);
my manifest :
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths"/>
</provider>
provider paths :
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="Download/"/>
<files-path name="files" path="files/" />
</paths>
I'm using android 10
please help. thanks
Yea, things changed after OS 10, you have to write logic in new way. Sample where we get some response using retrofit and using those byte[], working in my apps. Put this code in your android component(activity for example). Invoking viewModel.getPdfBytes() is response from backend!
private static final int CREATE_FILE = 23;
private void saveFileToStorageIntent() {
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType(MimeTypeMap.getSingleton().getMimeTypeFromExtension("pdf"));
intent.putExtra(Intent.EXTRA_TITLE, getString(R.string.text_export_pdf_file_first) + getDateString() + getString(R.string.text_export_pdf_file));
startActivityForResult(intent, CREATE_FILE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CREATE_FILE) {
if (resultCode == Activity.RESULT_OK && data != null) {
writePDFToFile(data.getData(), viewModel.getPdfBytes());
}
}
}
private void writePDFToFile(Uri uri, ResponseBody body){
InputStream inputStream = null;
OutputStream outputStream = null;
try {
byte[] fileReader = new byte[4096];
long fileSize = body.contentLength();
long fileSizeDownloaded = 0;
inputStream = body.byteStream();
outputStream = getContentResolver().openOutputStream(uri);
while (true) {
int read = inputStream.read(fileReader);
if (read == -1) {
break;
}
outputStream.write(fileReader, 0, read);
fileSizeDownloaded += read;
Logger.print(TAG, "file download: " + fileSizeDownloaded + " of " + fileSize);
}
outputStream.flush();
openFileWithIntent(uri,"pdf", getString(R.string.open_file));
} catch (Exception e) {
Logger.print(TAG, e.getMessage());
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private void openFileWithIntent(Uri fileUri, String typeString, String openTitle) {
Intent target = new Intent(Intent.ACTION_VIEW);
target.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
target.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
target.setDataAndType(
fileUri,
MimeTypeMap.getSingleton().getMimeTypeFromExtension(typeString)
); // For now there is only type 1 (PDF).
Intent intent = Intent.createChooser(target, openTitle);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
try {
startActivity(intent);
} catch (ActivityNotFoundException e) {
if (BuildConfig.DEBUG) e.printStackTrace();
Toast.makeText(context, getString(R.string.error_no_pdf_app), Toast.LENGTH_SHORT).show();
FirebaseCrashlytics.getInstance().log(getString(R.string.error_no_pdf_app));
FirebaseCrashlytics.getInstance().recordException(e);
}
}
I am trying to get the file from picking image from photos and get intent data, save the file in internal memory and use the file to load on Image views.
But I am getting the error as follows:
java.io.FileNotFoundException: /storage/emulated/0/Android/data/com.dailyfaithapp.dailyfaith/Files/MI_10052020_1711.png: open failed: ENOENT (No such file or directory)
I checked on the lower version of api i.e. on 24 it worked once or twice but again it failed.
And on api 29 its not working at all. For that I followed this url :
https://medium.com/#sriramaripirala/android-10-open-failed-eacces-permission-denied-da8b630a89df
I checked the code in java and tried the same but still its giving the error.
I am also checking for runtime permissions and have specified permissions in manifest file.
Following is my code:
<uses-permission android:name = "android.permission.INTERNET" />
<uses-permission android:name = "android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name = "android.permission.WAKE_LOCK" />
<uses-permission android:name = "android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name = "android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name = "android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name = "com.google.android.apps.photos.permission.GOOGLE_PHOTOS" />
Checking runtime permissions :
private boolean checkPermission() {
return ContextCompat.checkSelfPermission(this, WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(this, READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
;
}
private void requestPermissionAndContinue() {
if (ContextCompat.checkSelfPermission(this, WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(this, READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, WRITE_EXTERNAL_STORAGE)
&& ActivityCompat.shouldShowRequestPermissionRationale(this, READ_EXTERNAL_STORAGE)) {
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(this);
alertBuilder.setCancelable(true);
alertBuilder.setTitle("Allow Daily Faith to access photos," +
"media, and files on your device?");
alertBuilder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions(ThemesActivity.this,
new String[]{WRITE_EXTERNAL_STORAGE
, READ_EXTERNAL_STORAGE}, 200);
}
});
AlertDialog alert = alertBuilder.create();
alert.show();
Log.e("", "permission denied, show dialog");
} else {
ActivityCompat.requestPermissions(ThemesActivity.this,
new String[]{WRITE_EXTERNAL_STORAGE,
READ_EXTERNAL_STORAGE}, 200);
}
} else {
selectImageFromGallery();
}
}
Checking if permission is given:
if (!checkPermission()) {
selectImageFromGallery();
} else {
if (checkPermission()) {
requestPermissionAndContinue();
} else {
selectImageFromGallery();
}
}
Opening intent :
public void selectImageFromGallery()
{
Intent pickPhoto = new Intent(Intent.ACTION_PICK,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(pickPhoto , 2);
}
Get intent data on result :
#RequiresApi(api = Build.VERSION_CODES.KITKAT) #Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// Check which request we're responding to
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 2) {
// Make sure the request was successful
if (resultCode == RESULT_OK) {
// The user picked a image.
// The Intent's data Uri identifies which item was selected.
if (data != null) {
customTheme = true;
// This is the key line item, URI specifies the name of the data
mImageUri = data.getData();
// Saves image URI as string to Default Shared Preferences
SharedPreferencesData sharedPreferencesData =
new SharedPreferencesData(this);
sharedPreferencesData.setStr("customThemeSet","true");
try {
Bitmap bitmap =
MediaStore.Images.Media.getBitmap(getContentResolver(), mImageUri);
/* Utils.storeImage(bitmap,
ThemesActivity.this);
File file = Utils.getOutputMediaFile(ThemesActivity.this);
*/
try {
final ParcelFileDescriptor parcelFileDescriptor = getContentResolver().openFileDescriptor(
mImageUri, "r");
final FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor);
parcelFileDescriptor.close();
Utils.storeImage(bitmap,
ThemesActivity.this);
File file = Utils.getOutputMediaFile(ThemesActivity.this);
int color = Utils.getDominantColor(bitmap);
Log.d("Bitmap", bitmap.toString());
Boolean isDark = Utils.isColorDark(color);
if(customTheme) {
for (Themes themes : themesArrayList) {
themes.setCustomTheme(file.getPath());
themes.setDark(isDark);
}
if(isDark)
sharedPreferencesData.setStr("ThemeColor","dark");
else
sharedPreferencesData.setStr("ThemeColor","light");
themesAdapter = new ThemesAdapter(themesArrayList, this,customTheme);
recyclerView.setAdapter(themesAdapter);
}
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
Log.e("Failed", "Failed to Parse Image Uri", e);
try {
throw new Exception("failed to parse image uri");
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}
}
}
Saving and getting file
public static File getOutputMediaFile(Context context){
// To be safe, you should check that the SDCard is mounted
// using Environment.getExternalStorageState() before doing this.
File mediaStorageDir = new File(Environment.getExternalStorageDirectory()
+ "/Android/data/"
+ context.getApplicationContext().getPackageName()
+ "/Files");
// 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()){
mediaStorageDir.mkdirs();
}
else {
return null;
}
// Create a media file name
String timeStamp = new SimpleDateFormat("ddMMyyyy_HHmm").format(new Date());
File mediaFile;
String mImageName="MI_"+ timeStamp +".png";
mediaFile = new File(mediaStorageDir.getPath() + File.separator + mImageName);
return mediaFile;
}
public static void storeImage(Bitmap image,Context context) {
File pictureFile = getOutputMediaFile(context);
if (pictureFile == null) {
Log.d(TAG,
"Error creating media file, check storage permissions: ");// e.getMessage());
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
image.compress(Bitmap.CompressFormat.PNG, 90, fos);
fos.close();
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d(TAG, "Error accessing file: " + e.getMessage());
}
}
Before I was getting EACCESS error when I only used above two funtions to save the file.
Later I tried Parcel file descriptor but not working
Why am I getting this error? Is it only on api level 29 or below too?
What can be the solution for this to run on all devices?
Here is what worked for me Using the downloads folder which all phones old and new have public access to..
try{
File csvfile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/brcOrdersaved.csv");
final String filename = csvfile.toString();
if (!csvfile.exists()) {
// displayMsg(context, "No Saved Order: ");
return (false);
}
FileReader fr = new FileReader(filename);
BufferedReader reader = new BufferedReader(fr);
String csvLine = "";
final char Separator = ',';
final char Delimiter = '"';
final char LF = '\n';
final char CR = '\r';
boolean quote_open = false;
if (reader.equals(null)) {
displayMsg(context, "NULL");
return (false);//rww 11/13/2021
}
int i = 0;
while (!myendofcsvfile) {
csvLine = reader.readLine();
if (csvLine == null) {
myendofcsvfile = true;
}
// do stuff here
}
fr.close();
fileexists = true;
} catch (Exception e) {
String msg = "Can not Load Saved Order ";
fileexists = false;
return (fileexists);
}
I add this permissions, and it works.
<uses-permission
enter code hereandroid:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
tools:ignore="ProtectedPermissions" />