Nougat getUriForFile issue with camera Return - java

I've been trying to update my app to the way Nougat handles URI in intents and can't for the life of me figure out how to get the camera to work again. I've tried following the documentation but I must be missing something. Can anyone help?
this is my dispatch event
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
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
return;
}
// Continue only if the File was successfully created
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(this,
"com.everywhere_ww.provider",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
this is my provider in manifest:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.everywhere_ww.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths"/>
</provider>
This is my file paths
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="imgFolder" path="pictures" />
<external-path name="tempFolder" path="temp" />
Attempting to take a picture always fails with a
java.lang.IllegalArgumentException: Failed to find configured root that contains /data/data/com.everywhere_ww/files/temp/JPEG_20170223_101548_1550424251.jpg

/data/data/com.everywhere_ww/files/temp/JPEG_20170223_101548_1550424251.jpg would appear to be a path pointing to internal storage. You created this via getFilesDir(), presumably.
Replace:
<external-path name="tempFolder" path="temp" />
with:
<files-path name="tempFolder" path="temp" />

Hi not sure can make the difference but try to add to your xml file paths the following param
<external-path name="external_files" path="."/>

Related

Trying to add attacment " csv file " to gmail without success , Its Android App , im debugging with my phone as emulator

the app opens gmail and put all the data in but don't bring the attachment and I don't see issues.
Here is the code :
String filelocation = root.getAbsolutePath() + filename;
Intent intent = new Intent(Intent.ACTION_SENDTO);
intent.setType("text/plain");
String message = "File to be shared is " + filename + ".";
intent.putExtra(Intent.EXTRA_SUBJECT, "Subject");
intent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + filelocation));
intent.putExtra(Intent.EXTRA_TEXT, message);
intent.setData(Uri.parse("mailto:xyz#gmail.com"));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
} catch (Exception e) {
System.out.println("is exception raises during sending mail" + e);
}
I also uploaded image .
Thanks in advance .
Try to access the file using Provider :
Add a provider in your manifest under </application>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="#string/authority" //<string name="authority">'<packagename>'.provider</string>
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths" />
</provider>
and create a Path xml under res/xml/file_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>
then try to access the file using provider
Uri uri=FileProvider.getUriForFile(
this,
this.getPackageName().toString() + ".provider",
image_FilePath
);
Intent i = Intent(Intent.ACTION_SEND);
i.putExtra(Intent.EXTRA_STREAM, uri);
i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
this.startActivity(Intent.createChooser(i, "Share:"));
Hope its works ...

Android Image FIle variable is becoming null after image capture

The app I am currently developing has the feature of being able to capture an image, record a video, browse and upload a media file from gallery. Problem is, the app works well enough in emulator. Without any errors (checked with android 9+ emulators). But the app behaves unexpectedly while testing on physical device (Android 10). Unexpected, because, video recording and playing works fine, as well as browsing and uploading media from gallery. What fails is image capture. The thing is the image file is actually getting created, But I am getting the image file variable photoFile value as null in onActivityResult() method.
Here is the implementation:
manifest.xml
<provider android:name=".utils.MyFileProvider"
android:authorities="com.app.mtccrm.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths"/>
</provider>
provider_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="external"
path="." />
<external-files-path
name="external_files"
path="." />
<cache-path
name="cache"
path="." />
<external-cache-path
name="external_cache"
path="." />
<files-path
name="files"
path="." />
</paths>
method to create image_file
public static File createImageFile(Context mContext, String name) throws IOException {
String imageFileName = name.replaceAll(" ", "_");
File storageDir = mContext.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = new File(storageDir + File.separator + imageFileName + ".png");
return image;
}
method responsible for opening the camera
private void openCamera() {
if (ActivityCompat.checkSelfPermission(AddNewFileActivity.this, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, REQUEST_PERMISSION_CODE_IMAGE);
} else {
Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
try {
photoFile = CommonMethod.createImageFile(this, fileName);
} catch (IOException ioe) {
ioe.printStackTrace();
}
//Toast.makeText(this, ""+photoFile.getAbsolutePath(), Toast.LENGTH_SHORT).show();
if(photoFile != null ) {
Uri photoURI = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".fileprovider", photoFile);
captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
captureIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivityForResult(captureIntent, TAKE_PICTURE_CODE);
}else {
Toast.makeText(this, "Something went wrong while trying to create a file. Please try again", Toast.LENGTH_SHORT).show();
}
}
}
onActivityResult()
Toast.makeText(this, ""+photoFile, Toast.LENGTH_SHORT).show();
if (requestCode == TAKE_PICTURE_CODE && resultCode == RESULT_OK) {
if(photoFile == null) {
if(data != null) {
parseGalleryFile(data);
}
}else {
setImage(Uri.parse(photoFile.getAbsolutePath()));
}
}
The first Toast in onActivityResult() gives me null value. So somehow the photoFile variable is becoming null, however I am at a loss about the cause. Since, from the same activity using the same methods, recording of videos and browsing gallery works just fine. I thought it might have something to do with the activity getting paused when the camera is called. So, I added this
#Override
public void onSaveInstanceState(#NonNull Bundle outState, #NonNull PersistableBundle outPersistentState) {
super.onSaveInstanceState(outState, outPersistentState);
Toast.makeText(this, ""+photoFile, Toast.LENGTH_SHORT).show();
if(photoFile != null) {
outState.putString("FileId", photoFile.getAbsolutePath());
}
}
#Override
protected void onRestoreInstanceState(#NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Toast.makeText(this, ""+savedInstanceState.getString("FileId"), Toast.LENGTH_SHORT).show();
if(savedInstanceState.getString("FileId") != null) {
if (photoFile == null) {
photoFile = new File(savedInstanceState.getString("FileId"));
}
}
}
Unfortunately, save and restore state methods are not getting called, so that means the activity is not being paused. So what could be the cause for photofile becoming null? what exactly am I doing wrong?
Thanks for the help.

Android: Failure delivering result, Couldn't find meta-data for provider with authority

I am trying to use uCrop for cropping images and uploading to firebase. I want to allow the option of either using the camera or files for input.
val pickIntent = Intent()
pickIntent.type = "image/*"
pickIntent.action = Intent.ACTION_GET_CONTENT
val takePhotoIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
val pickTitle = "Select or take a new Picture"
val chooserIntent = Intent.createChooser(pickIntent, pickTitle)
chooserIntent.putExtra(
Intent.EXTRA_INITIAL_INTENTS, arrayOf(takePhotoIntent)
)
startActivityForResult(chooserIntent, REQUEST_IMAGE_CAPTURE)
my onActivityResult function looks like this :
override fun onActivityResult(
requestCode: Int,
resultCode: Int,
data: Intent?
): Unit {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode === Activity.RESULT_OK) {
if (requestCode === REQUEST_IMAGE_CAPTURE) {
var photoFile: File? = null
try {
photoFile = createImageFile()
if(photoFile != null) Log.v("AFTER CREATE IMAGE FILE", "photoFILE " + photoFile.toString())
if (photoFile != null) {
var photoUri: Uri =
FileProvider.getUriForFile(this, this.packageName, photoFile)
Log.v("AFTER FILE URI", "photoUri " + photoUri.toString())
startCrop(photoUri)
}
} catch (ex: IOException) {
}
}
}
}
The null check for photoFile in the above code fails and I don't receive any log for that if statement.
However, I run into the following error for the lack of authority:
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1888, result=-1, data=Intent { dat=content://com.android.providers.media.documents/document/image:25 flg=0x1 }} to activity {com.gigforce.app/com.gigforce.app.modules.photoCrop.ui.main.PhotoCrop}: java.lang.IllegalArgumentException: Couldn't find meta-data for provider with authority com.gigforce.app
But I have following in 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/file_paths">
</meta-data>
</provider>
and file_paths.xml look like this:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="my_images"
path="." />
</paths>
Also, for some reason, the files are being saved in
/storage/emulated/0/Android/data/com.gigforce.app/files/Pictures/IMG_20200318_192722_2465645043825713296.jpg
instead of the . defined in file_paths.xml
FileProvider.getUriForFile(this, this.packageName, photoFile)
You are using this.packageName as your authority string.
Your actual authority string is:
android:authorities="{applicationId}.provider"
These do not match. So, instead, use:
FileProvider.getUriForFile(this, "${this.packageName}.provider", photoFile)
or:
FileProvider.getUriForFile(this, "${BuildConfig.APPLICATION_ID}.provider", photoFile)
(the latter should be a bit faster)

I can not share video to whatsapp from my app

I have an Android Studio project with the option to share videos by whatsapp.
This is my code:
private void shareFile(File file){
String titulo = file.getName();
String path = file.getAbsolutePath();
Uri uri = Uri.parse(path);
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
shareIntent.setType("video/*");
shareIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, title);
shareIntent.putExtra(android.content.Intent.EXTRA_TITLE, title);
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
shareIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
shareIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(shareIntent);
}
But when I share it I receive the message from Whatsapp: this file format is not compatible.
I do not understand what happens, before it worked.
ANDROIDMANIFEST.XML
<provider
android:name="android.support.v4.content.FileProvider"
android:grantUriPermissions="true"
android:exported="false"
android:authorities="${applicationId}">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_provider_paths"/>
</provider>
FILE_PROVIDER_PATHS.XML in res/xml
<paths>
<cache-path name="cache" path="/" />
<files-path name=”files” path=”/” />
</paths>
USE YOUR FILEPROVIDER
// create new Intent
Intent intent = new Intent(Intent.ACTION_VIEW);
// set flag to give temporary permission to external app to use your FileProvider
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
// generate URI, I defined authority as the application ID in the Manifest, the last param is file I want to open
String uri = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID, file);
// I am opening a PDF file so I give it a valid MIME type
intent.setDataAndType(uri, "video/*");
// validate that the device can open your File!
PackageManager pm = getActivity().getPackageManager();
if (intent.resolveActivity(pm) != null) {
startActivity(intent);
}

FileProvider not working

What I am trying to do is to get a file that is in the private area to be opened by another program. In this example, a image viewer app.
AndroidManifest.xml
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.mydomain.myapp"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/path" />
</provider>
/res/xml/path.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="cache" path="cache/"/>
</paths>
Java code (file location)
File file = new File(context.getApplicationInfo().dataDir + File.separator + "cache" + File.separator + filename);
Java code (open file)
if(file != null && file.isFile() && file.canRead() && file.length() > 0){
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
List<ResolveInfo> resInfoList = this.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
Uri uri = Uri.parse(file.toURI().toString());
for (int i = 0; i < resInfoList.size(); i++) {
try{
ResolveInfo resolveInfo = resInfoList.get(i);
String packageName = resolveInfo.activityInfo.packageName;
grantUriPermission(packageName, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
}catch(Exception e){
}catch(Error e){
}
}
MimeTypeMap myMime = MimeTypeMap.getSingleton();
Intent newIntent = new Intent(Intent.ACTION_VIEW);
String mimeType = myMime.getMimeTypeFromExtension(".jpg");
newIntent.setDataAndType(Uri.fromFile(file), mimeType);
newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
context.startActivity(newIntent);
return true;
} catch (Exception e) {
}
}
This always results in a toast message "Unable to find item". What am I doing wrong and how to resolve this?
What am I doing wrong
File file = new File(context.getApplicationInfo().dataDir + File.separator + "cache" + File.separator + filename);
Use getCacheDir() to get the cache directory, as your approach is not going to be reliable for secondary accounts on Android 4.2+ tablets and Android 5.0+ phones. So, this should be:
File file = new File(context.getCacheDir(), filename);
Then, you need to replace Uri.fromFile(file) with a call to getUriForFile() on FileProvider, as is covered in the documentation. What you presently have is a Uri pointing to a file, not pointing to a ContentProvider, let alone your FileProvider implementation.
Finally, you will need to call addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) on the Intent before you use it with startActivity(), as otherwise the app that responds to the startActivity() request will not have access to the content.
This sample app demonstrates a working implementation of a FileProvider.

Categories