java.io.FileNotFoundException: (Permission denied) Only in Oreo - java

I am downloading photos to smartphone. For versions lower than Oreo, there's no problem. But for Oreo, my code isn't not working. I tried this code in Emulator:
I implemented a function to save an image to external storage.
private void saveImageToExternalStorage(Bitmap finalBitmap,String name) {
String root = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString();
File myDir = new File(root + "/xx");
myDir.mkdirs();
String fname = name + ".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();
}
// Tell the media scanner about the new file so that it is
// immediately available to the user.
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);
}
});
}
I am requesting permissions with dexter library.
Dexter.withActivity(MainActivity.this)
.withPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
.withListener(new PermissionListener() {
#Override
public void onPermissionGranted(PermissionGrantedResponse response) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(MainActivity.this);
if (!prefs.getBoolean("firstTime", false)) {
task.execute();
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean("firstTime", true);
editor.commit();
}
}
#Override
public void onPermissionDenied(PermissionDeniedResponse response) {
Toast.makeText(MainActivity.this, "You need to allow permission if you want to use camera", Toast.LENGTH_LONG).show();
}
#Override
public void onPermissionRationaleShouldBeShown(PermissionRequest permission, PermissionToken token) {
token.continuePermissionRequest();
Toast.makeText(MainActivity.this, "You need to allow permission if you want to use camera", Toast.LENGTH_LONG).show();
}
}).check();
I save images with asynctask
final AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
private ProgressDialog dialog;
#Override
protected void onPreExecute()
{
this.dialog = new ProgressDialog(MainActivity.this);
this.dialog.setMessage(getString(R.string.newfeature));
this.dialog.setCancelable(false);
this.dialog.setOnCancelListener(new DialogInterface.OnCancelListener()
{
#Override
public void onCancel(DialogInterface dialog)
{
// cancel AsyncTask
cancel(false);
}
});
this.dialog.show();
}
#Override
protected Void doInBackground(Void... params)
{
// do your stuff
Bitmap myBitmap2 = BitmapFactory.decodeResource(getApplicationContext().getResources(), R.drawable.im2);
saveImageToExternalStorage(myBitmap2,"imag2");
myBitmap2.recycle();
return null;
}
#Override
protected void onPostExecute(Void result)
{
//called on ui thread
if (this.dialog != null) {
this.dialog.dismiss();
}
}
#Override
protected void onCancelled()
{
//called on ui thread
if (this.dialog != null) {
this.dialog.dismiss();
}
}
};
I can see Storage permission is granted when I look Settings --> Apps for my app. But images are not saved correctly. In fact images are saved but all of them is green square like this.
As a result, it gives permission denied error although permission is granted.
09-21 13:11:08.023 17636-17765/xx.xx W/System.err: java.io.FileNotFoundException: /storage/emulated/0/Pictures/xx/imag2.jpg (Permission denied)
09-21 13:11:08.024 17636-17765/xx.xx W/System.err: at java.io.FileOutputStream.open0(Native Method)
09-21 13:11:08.024 17636-17765/xx.xx W/System.err: at java.io.FileOutputStream.open(FileOutputStream.java:308)
09-21 13:11:08.033 17636-17765/xx.xx W/System.err: at java.io.FileOutputStream.<init>(FileOutputStream.java:238)
09-21 13:11:08.033 17636-17765/xx.xx W/System.err: at java.io.FileOutputStream.<init>(FileOutputStream.java:180)
09-21 13:11:08.033 17636-17765/xx.xx W/System.err: at xx.xx.MainActivity.saveImageToExternalStorage(MainActivity.java:804)
09-21 13:11:08.033 17636-17765/xx.xx W/System.err: at xx.xx.MainActivity.access$000(MainActivity.java:62)
09-21 13:11:08.033 17636-17765/xx.xx W/System.err: at xx.xx.MainActivity$1.doInBackground(MainActivity.java:119)
09-21 13:11:08.033 17636-17765/xx.xx W/System.err: at xx.xx.MainActivity$1.doInBackground(MainActivity.java:89)
09-21 13:11:08.033 17636-17765/xx.xx W/System.err: at android.os.AsyncTask$2.call(AsyncTask.java:333)
09-21 13:11:08.033 17636-17765/xx.xx W/System.err: at java.util.concurrent.FutureTask.run(FutureTask.java:266)
09-21 13:11:08.033 17636-17765/xx.xx W/System.err: at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
09-21 13:11:08.033 17636-17765/xx.xx W/System.err: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
09-21 13:11:08.033 17636-17765/xx.xx W/System.err: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
09-21 13:11:08.033 17636-17765/xx.xx W/System.err: at java.lang.Thread.run(Thread.java:764)

Access Sd-Card's files
Use DOCUMENT_TREE dialog to get sd-card's Uri.
Inform user about how to choose sd-card on the dialog. (with pictures or gif animations)
// call for document tree dialog
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, REQUEST_CODE_OPEN_DOCUMENT_TREE);
On onActivityResult you'll have the selected directory Uri. (sdCardUri)
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQUEST_CODE_OPEN_DOCUMENT_TREE:
if (resultCode == Activity.RESULT_OK) {
sdCardUri = data.getData();
}
break;
}
}
Now must check if the user,
a. selected the sd-card
b. selected the sd-card that our file is on (some devices could have multiple sd-cards).
We check both a and b by finding the file through the hierarchy, from sd root to our file. If file found, both of a and b conditions are acquired.
//First we get `DocumentFile` from the `TreeUri` which in our case is `sdCardUri`.
DocumentFile documentFile = DocumentFile.fromTreeUri(this, sdCardUri);
//Then we split file path into array of strings.
//ex: parts:{"", "storage", "extSdCard", "MyFolder", "MyFolder", "myImage.jpg"}
// There is a reason for having two similar names "MyFolder" in
//my exmple file path to show you similarity in names in a path will not
//distract our hiarchy search that is provided below.
String[] parts = (file.getPath()).split("\\/");
// findFile method will search documentFile for the first file
// with the expected `DisplayName`
// We skip first three items because we are already on it.(sdCardUri = /storage/extSdCard)
for (int i = 3; i < parts.length; i++) {
if (documentFile != null) {
documentFile = documentFile.findFile(parts[i]);
}
}
if (documentFile == null) {
// File not found on tree search
// User selected a wrong directory as the sd-card
// Here must inform user about how to get the correct sd-card
// and invoke file chooser dialog again.
} else {
// File found on sd-card and it is a correct sd-card directory
// save this path as a root for sd-card on your database(SQLite, XML, txt,...)
// Now do whatever you like to do with documentFile.
// Here I do deletion to provide an example.
if (documentFile.delete()) {// if delete file succeed
// Remove information related to your media from ContentResolver,
// which documentFile.delete() didn't do the trick for me.
// Must do it otherwise you will end up with showing an empty
// ImageView if you are getting your URLs from MediaStore.
//
Uri mediaContentUri = ContentUris.withAppendedId(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
longMediaId);
getContentResolver().delete(mediaContentUri , null, null);
}
}
Note:
You must provide access permission to the external storage inside your manifest and for os>=Marshmallow inside the app.
https://stackoverflow.com/a/32175771/2123400
Edit Sd-Card's Files
For editing an existing image on your sd-card you don't need any of above steps if you want to invoke another app to do it for you.
Here we invoke all the activities (from all the installed apps) with the capability of editing the images. (Programmers mark their apps in the manifest for its capabilities to provide accessibility from other apps (activities)).
on your editButton click event:
String mimeType = getMimeTypeFromMediaContentUri(mediaContentUri);
startActivityForResult(Intent.createChooser(new Intent(Intent.ACTION_EDIT).setDataAndType(mediaContentUri, mimeType).putExtra(Intent.EXTRA_STREAM, mediaContentUri).addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION), "Edit"), REQUEST_CODE_SHARE_EDIT_SET_AS_INTENT);
and this is how to get mimeType:
public String getMimeTypeFromMediaContentUri(Uri uri) {
String mimeType;
if (uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
ContentResolver cr = getContentResolver();
mimeType = cr.getType(uri);
} else {
String fileExtension = MimeTypeMap.getFileExtensionFromUrl(uri
.toString());
mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
fileExtension.toLowerCase());
}
return mimeType;
}
Note:
On Android KitKat(4.4) don't ask the user to select the sd-card because on this version of Android DocumentProvideris not applicable, hence we have no chance to have access to the sd-card with this approach.
Look at the API level for the DocumentProvider
https://developer.android.com/reference/android/provider/DocumentsProvider.html
I couldn't find anything that works on Android KitKat(4.4). If you found anything useful with KitKat please share with us.
On versions below the KitKat access to sd-card is already provided by the OS.

Related

Camera2 API Exception on android.media.Image.getPlanes() on certain device

I use Camera2 API for capturing OCR image in my App (Tablet only). Everything is work but there are one device (let say A Device) did'nt work. Here the log :
2021-05-28 13:46:23.402 28882-28937/com. D/OpenGLRenderer: textureCacheSize 75497472
2021-05-28 13:46:23.416 28882-28882/com. I/CameraManagerGlobal: Connecting to camera service
2021-05-28 13:46:33.303 28882-28975/com. W/System.err: java.lang.NullPointerException: Attempt to invoke virtual method 'android.media.Image$Plane[] android.media.Image.getPlanes()' on a null object reference
2021-05-28 13:46:33.305 28882-28975/com. W/System.err: at com.Camera2Fragment$6$1.run(Camera2Fragment.java:927)
2021-05-28 13:46:33.307 28882-28975/com. W/System.err: at android.os.Handler.handleCallback(Handler.java:873)
2021-05-28 13:46:33.308 28882-28975/com. W/System.err: at android.os.Handler.dispatchMessage(Handler.java:99)
2021-05-28 13:46:33.310 28882-28975/com. W/System.err: at android.os.Looper.loop(Looper.java:193)
2021-05-28 13:46:33.311 28882-28975/com. W/System.err: at android.os.HandlerThread.run(HandlerThread.java:65)
Here my CaptureSession.CaptureCallback :
CameraCaptureSession.CaptureCallback CaptureCallback = new CameraCaptureSession.CaptureCallback() {
#Override
public void onCaptureCompleted(#NonNull CameraCaptureSession session, #NonNull CaptureRequest request, #NonNull TotalCaptureResult result) {
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
Bitmap bitmap = null;
String nik;
try {
System.out.println("Array plane : " + mImageReader.acquireLatestImage().getPlanes().toString());
ByteBuffer buffer = mImageReader.acquireLatestImage().getPlanes()[0].getBuffer(); // Error start from here, in other device, acquireLatestImage is not null, but in A device is become null
byte[] data = new byte[buffer.remaining()];
buffer.get(data);
bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
} catch (NullPointerException e) {
// **In one device, its fall to here**
e.printStackTrace();
}
if (bitmap == null) {
Toast.makeText(getActivity(), "Failed to get image, please try again", Toast.LENGTH_SHORT).show();
} else {
// other my code (proccessing image, ocr and other)
}
}
}
}
}
Extra :
The A device have screen specification 10 inch and 800x1280 and 8MP. I dont know its take a effect for the surface but its only happen in this device.
I have read some issues about getting an image from Camera2 API, but actually my code work on many many devices.

Can you save files in the external storage on Galaxy S21?

I am trying to build a music recording app and the recording and stopping part is working, but it looks like the app cannot play the recorded file because it throws this error:
java.io.FileNotFoundException: /storage/emulated/0/CKENCAudioRecording.3gp: open failed: ENOENT (No such file or directory)
W/System.err: at libcore.io.IoBridge.open(IoBridge.java:492)
W/System.err: at java.io.FileInputStream.<init>(FileInputStream.java:160)
W/System.err: at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1259)
W/System.err: at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1230)
W/System.err: at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1195)
W/System.err: at com.example.karaokebuddies.record$3.onClick(record.java:99)
W/System.err: at android.view.View.performClick(View.java:8160)
W/System.err: at android.widget.TextView.performClick(TextView.java:16193)
W/System.err: at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1119)
W/System.err: at android.view.View.performClickInternal(View.java:8137)
W/System.err: at android.view.View.access$3700(View.java:888)
W/System.err: at android.view.View$PerformClick.run(View.java:30236)
W/System.err: at android.os.Handler.handleCallback(Handler.java:938)
W/System.err: at android.os.Handler.dispatchMessage(Handler.java:99)
W/System.err: at android.os.Looper.loop(Looper.java:246)
W/System.err: at android.app.ActivityThread.main(ActivityThread.java:8462)
W/System.err: at java.lang.reflect.Method.invoke(Native Method)
W/System.err: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:596)
W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)
W/System.err: Caused by: android.system.ErrnoException: open failed: ENOENT (No such file or directory)
W/System.err: at libcore.io.Linux.open(Native Method)
W/System.err: at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
W/System.err: at libcore.io.BlockGuardOs.open(BlockGuardOs.java:254)
W/System.err: at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
W/System.err: at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:8323)
W/System.err: at libcore.io.IoBridge.open(IoBridge.java:478)
The error is referring to this line inside the play.setOnClicklistener.
mediaPlayer.setDataSource(AudioSavePathInDevice);
//AudioSavePathInDevice = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + CreateRandomAudioFileName(5) + "AudioRecording.3gp";
I've searched through a lot of similar cases in stack overflow, but none really helped.
I included necessary permissions and set requestLegacyExternalStorage to true:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
android:requestLegacyExternalStorage="true"
Here's my record.java:
package com.example.karaokebuddies;
import android.content.pm.PackageManager;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import java.io.IOException;
import java.util.Random;
import static android.Manifest.permission.RECORD_AUDIO;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
public class record extends AppCompatActivity {
private Button play, stop, record, stopPlaying;
private MediaRecorder myAudioRecorder;
private String outputFile;
private String AudioSavePathInDevice = null;
Random random;
String RandomAudioFileName = "ABCDEFGHIJKLMNOP";
public static final int RequestPermissionCode = 1;
private MediaPlayer mediaPlayer;
boolean isRecording = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.record);
play = (Button) findViewById(R.id.play);
stop = (Button) findViewById(R.id.stop);
record = (Button) findViewById(R.id.record);
stopPlaying = (Button) findViewById(R.id.button_stopPlaying);
stop.setEnabled(false);
play.setEnabled(false);
stopPlaying.setEnabled(false);
random = new Random();
record.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (checkPermission()) {
AudioSavePathInDevice = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + CreateRandomAudioFileName(5) + "AudioRecording.3gp";
MediaRecorderReady();
try {
myAudioRecorder.prepare();
myAudioRecorder.start();
isRecording = true;
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
record.setEnabled(false);
stop.setEnabled(true);
Toast.makeText(getApplicationContext(), "Recording started", Toast.LENGTH_LONG).show();
} else {
requestPermission();
}
}
});
stop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (isRecording) {
myAudioRecorder.stop();
}
myAudioRecorder.release();
isRecording = false;
stop.setEnabled(false);
play.setEnabled(true);
record.setEnabled(true);
stopPlaying.setEnabled(false);
Toast.makeText(getApplicationContext(), "Audio Recorded successfully", Toast.LENGTH_LONG).show();
}
});
play.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) throws IllegalArgumentException, SecurityException, IllegalStateException {
// MediaPlayer mediaPlayer = new MediaPlayer();
stop.setEnabled(false);
record.setEnabled(false);
stopPlaying.setEnabled(true);
mediaPlayer = new MediaPlayer();
try {
// mediaPlayer.setDataSource(outputFile);
mediaPlayer.setDataSource(AudioSavePathInDevice);
mediaPlayer.prepare();
} catch (IOException e) {
e.printStackTrace();
}
mediaPlayer.start();
Toast.makeText(getApplicationContext(), "Playing Audio", Toast.LENGTH_LONG).show();
}
});
stopPlaying.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
stop.setEnabled(false);
record.setEnabled(true);
stopPlaying.setEnabled(false);
play.setEnabled(true);
if (mediaPlayer != null) {
mediaPlayer.stop();
mediaPlayer.release();
MediaRecorderReady();
}
}
});
}
public void MediaRecorderReady() {
myAudioRecorder = new MediaRecorder();
myAudioRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
myAudioRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
myAudioRecorder.setAudioEncoder(MediaRecorder.OutputFormat.AMR_NB);
myAudioRecorder.setOutputFile(AudioSavePathInDevice);
}
public String CreateRandomAudioFileName(int string) {
StringBuilder stringBuilder = new StringBuilder(string);
int i = 0;
while (i < string) {
stringBuilder.append(RandomAudioFileName.charAt(random.nextInt(RandomAudioFileName.length())));
i ++;
}
return stringBuilder.toString();
}
private void requestPermission() {
ActivityCompat.requestPermissions(record.this, new String[]{WRITE_EXTERNAL_STORAGE, RECORD_AUDIO}, RequestPermissionCode);
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode) {
case RequestPermissionCode:
if (grantResults.length > 0) {
boolean StoragePermission = grantResults[0] == PackageManager.PERMISSION_GRANTED;
boolean RecordPermission = grantResults[1] == PackageManager.PERMISSION_GRANTED;
if (StoragePermission && RecordPermission) {
Toast.makeText(record.this, "Permission Granted", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(record.this, "Permission Denied", Toast.LENGTH_LONG).show();
}
}
break;
}
}
public boolean checkPermission() {
int result = ContextCompat.checkSelfPermission(getApplicationContext(), WRITE_EXTERNAL_STORAGE);
int result1 = ContextCompat.checkSelfPermission(getApplicationContext(), RECORD_AUDIO);
return result == PackageManager.PERMISSION_GRANTED && result1 == PackageManager.PERMISSION_GRANTED;
}
}
As I was searching for a solution, I was wondering if the cause of this error is because I own a Galaxy s21+, which does not have an external storage, and I'm trying to save the recorded file into external storage directory. If so, would there be a solution to my situation? (i.e. saving to an internal storage?). Or, is there something else that I'm doing wrong?
Thank you in advance for your support!
First of all, when Android references "External Storage", it doesn't refer to an SD card. From this link:
"Categories of storage locations
Android provides two types of physical storage locations: internal storage and external storage. On most devices, internal storage is smaller than external storage. However, internal storage is always available on all devices, making it a more reliable place to put data on which your app depends."
The File Not Found could be related to two issues:
You do not have the correct permissions
The folder or file doesn't exist
If you review the error in your Logcat, you can usually determine the specific details. Also, using a File app on your device, you should be able to see if file with that name actually does in that folder.
Double-check to ensure that the permissions have been granted/accepted.
What level SDK are you targeting? If you have targetSdkVersion 30 in your app's build.gradle file, you need to update your code to adhere to a recent policy change that Google made.
If you aren't sure if the directory exists, you can use code such as this to create it:
final File root = new File(String.valueOf(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)));
// Create the directory if it doesn't exist
if (!root.exists()) {
boolean wasSuccessful = root.mkdirs();
// Display Toast message if the directory creation wasn't successful
if (!wasSuccessful) {
mToast = Toast.makeText(this, R.string.photo_directory_not_created_error, Toast.LENGTH_SHORT);
mToast.show();
}
}

Get GPS data from file metadata in Android 10

So, I have to get GPS data from file MetaData. "No problem", I said, "This will only take an hour or two". Six hour later, here I am searching through all Android Documentation and Stack exchange questions I can yet I still cant get it to work.
My Code is straight forward:
I am using a ACTION_PICK to select a video (ACTION_OPEN_DOCUMENT Doesn't work either).
I Have already requested the following permissions and added to the Manifest:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
Below is code from the button listener
#Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_PICK , MediaStore.Video.Media.EXTERNAL_CONTENT_URI);
//intent.setType("video/*");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
startActivityForResult(Intent.createChooser(intent,"Select A Video"),REQUEST_VIDEO_CONTENT);
}
});
And From the OnActivityResult:
protected void onActivityResult(int requestCode, int resultCode, Intent vIntent) {
super.onActivityResult(requestCode, resultCode, vIntent);
if ((requestCode == REQUEST_VIDEO_CAPTURE || requestCode == REQUEST_VIDEO_CONTENT) && resultCode == RESULT_OK) {
//Attempt to get Content Data
vIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
vIntent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
Uri vUri = vIntent.getData();
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
vUri = MediaStore.setRequireOriginal(vUri);
}
try {
InputStream vIS = getContentResolver().openInputStream(vUri);
ExifInterface vExif = new ExifInterface(vIS);
} catch (SecurityException | IOException e) {
e.printStackTrace();
}
And finally, the lovely SecurityException:
W/System.err: java.lang.SecurityException: Permission Denial: reading com.google.android.apps.photos.contentprovider.impl.MediaContentProvider uri content://com.google.android.apps.photos.contentprovider/0/2/content%3A%2F%2Fmedia%2Fexternal%2Fvideo%2Fmedia%2F198668/ORIGINAL/NONE/video%2Fmp4/328149382?requireOriginal=1 from pid=6190, uid=10146 requires the provider be exported, or grantUriPermission()
W/System.err: at android.os.Parcel.createException(Parcel.java:2071)
at android.os.Parcel.readException(Parcel.java:2039)
W/System.err: at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:188)
at android.database.DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(DatabaseUtils.java:151)
W/System.err: at android.content.ContentProviderProxy.openTypedAssetFile(ContentProviderNative.java:705)
at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1710)
W/System.err: at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:1526)
W/System.err: at android.content.ContentResolver.openFileDescriptor(ContentResolver.java:1345)
at android.content.ContentResolver.openFileDescriptor(ContentResolver.java:1293)
W/System.err: at com.equinox.openeyes.VideoSubmission.onActivityResult(VideoSubmission.java:117)
at android.app.Activity.dispatchActivityResult(Activity.java:8147)
at android.app.ActivityThread.deliverResults(ActivityThread.java:4883)
W/System.err: at android.app.ActivityThread.handleSendResult(ActivityThread.java:4931)
at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:51)
W/System.err: at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2022)
W/System.err: at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:235)
W/System.err: at android.app.ActivityThread.main(ActivityThread.java:7441)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
I get that the Error is saying the provider needs to be exported, or grantUriPermission which sounds like an easy fix, except I cannot find a way to implement what they ask. All the places I have looked have suggested adding flags.. as you can see it didnt work.
Please Help :-(

Android: java.io.FileNotFoundException: Not a whole file

I make an chat app for practice and
tried to use my add1.png image in my drawable folder as a default profile image whether user put the image or not
here's my code snipet
if (imageUri == null) { //when user has no image
//use default image as a profile image that in drawable folder
imageUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE +
"://" + getResources().getResourcePackageName(R.drawable.add1)
+ '/' + getResources().getResourceTypeName(R.drawable.add1)
+ '/' + getResources().getResourceEntryName(R.drawable.add1));
}
//insert into firebase storage
FirebaseStorage.getInstance().getReference().child("userImages").child(uid).putFile(imageUri).addOnCompleteListener(new OnCompleteListener<UploadTask.TaskSnapshot>() {...}
In the event that run the app exception has occurred but the default image(add1.png) be inserted into firebase storage properly.
here's the exception.
W/UploadTask: could not retrieve file size for upload android.resource://com.example.harag.myapplication/drawable/add1
java.io.FileNotFoundException: Not a whole file
at android.content.ContentResolver.openFileDescriptor(ContentResolver.java:812)
at android.content.ContentResolver.openFileDescriptor(ContentResolver.java:749)
at com.google.firebase.storage.UploadTask.<init>(Unknown Source)
at com.google.firebase.storage.StorageReference.putFile(Unknown Source)
at com.example.harag.myapplication.SignUpActivity$2$1.onComplete(SignUpActivity.java:92)
at com.google.android.gms.tasks.zzf.run(Unknown Source)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
thank you!
You need to use UploadTask.UploadTask which you can use to manage and monitor the status of the upload.
Uri file = Uri.fromFile(new File("path/to/images/rivers.jpg"));
StorageReference riversRef = storageRef.child("images/"+file.getLastPathSegment());
uploadTask = riversRef.putFile(file);
// Register observers to listen for when the download is done or if it fails
uploadTask.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
// Handle unsuccessful uploads
}
}).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
// taskSnapshot.getMetadata() contains file metadata such as size, content-type, and download URL.
Uri downloadUrl = taskSnapshot.getDownloadUrl();
}
});
Firebase Upload Files
You can try below code.
Uri uri = Uri.parse("android.resource://org.xyz.abc/drawable/myimage");
or
Uri uri=Uri.parse("android.resource://"+context.getPackageName()+"/drawable/myimage");

Capture Image, Upload To Firebase And Retrieve Java Android Studio

I am very sorry if this may be a question with a simple solution.
What Am I Trying To Do?
Capture an image from a Button
Upload that image to Firebase storage
Retrieve that image in an ImageView
What Is My Trouble So Far?
Takes picture, but crashes when I click the tick.
Hence nothing is being uploaded or being achieved.
My Code
P.N I have looked at lots of other forums and video tutorials but nothing seems to be working. Hopefully someone can help.
public class LeaderboardActivity extends AppCompatActivity {
private static final int CAMERA_REQUEST_CODE = 1;
private static final int REQUEST_TAKE_PHOTO = 1;
private StorageReference mStorage;
private ProgressDialog mProgress;
String mCurrentPhotoPath;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_leaderboard);
mStorage = FirebaseStorage.getInstance().getReference();
final Button bImage = (Button) findViewById(R.id.bCamera);
final ImageView ivPic = (ImageView) findViewById(R.id.ivPic);
mProgress = new ProgressDialog(this);
bImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, CAMERA_REQUEST_CODE);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CAMERA_REQUEST_CODE && resultCode == RESULT_OK) {
mProgress.setMessage("Uploading Image");
mProgress.show();
Uri uri = data.getData();
StorageReference filepath = mStorage.child("Photo").child(uri.getLastPathSegment());
filepath.putFile(uri).addOnSuccessListener(new OnSuccessListener < UploadTask.TaskSnapshot > () {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
mProgress.dismiss();
Toast.makeText(LeaderboardActivity.this, "Uploading Complete...", Toast.LENGTH_LONG);
}
});
}
}
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = image.getAbsolutePath();
return image;
}
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
}
// Continue only if the File was successfully created
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(this,
"com.example.android.fileprovider",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}
}
Error In Android Monitor
Not sure if this will help
02-13 02:30:32.693 2133-2133/com.example.rikhi.chores E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.rikhi.chores, PID: 2133
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1, result=-1, data=Intent { act=inline-data (has extras) }} to activity {com.example.rikhi.chores/com.example.rikhi.chores.LoginRegister.InsideMainActivity.LeaderboardActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.net.Uri.getLastPathSegment()' on a null object reference
at android.app.ActivityThread.deliverResults(ActivityThread.java:4089)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4132)
at android.app.ActivityThread.-wrap20(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1533)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.net.Uri.getLastPathSegment()' on a null object reference
at com.example.rikhi.chores.LoginRegister.InsideMainActivity.LeaderboardActivity.onActivityResult(LeaderboardActivity.java:74)
at android.app.Activity.dispatchActivityResult(Activity.java:6932)
at android.app.ActivityThread.deliverResults(ActivityThread.java:4085)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4132) 
at android.app.ActivityThread.-wrap20(ActivityThread.java) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1533) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:154) 
at android.app.ActivityThread.main(ActivityThread.java:6119) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776) 
I have looked at other people who had the same problem, followed what they said nothing happend, followed the Google Android instructions for this and again same problem.
On button, click remove that intent and just call your
dispatchTakePictureIntetnt() method on Onclick button Listener
Also, check go to your emulator settings, and check your camera
permission is on for your this app and also go to firebase console
and check the rules if, rules are not equal to null made them equal
to null then run your app because !=null rules only work when there
is an authentication method in your app

Categories

Resources