I realize there have been a lot of posts with the fileProvider but I can't seem to find an answer to my problem in there.
I take images, using the following intent:
private fun openCamera() {
currentFocus?.clearFocus()
val intent = Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA)
if (intent.resolveActivity(packageManager) != null) {
startActivity(intent)
}
}
To make this work, I also have an Observer:
fun observe(): Flowable<Picture> =
pictureSubject.onBackpressureLatest()
.map { uri ->
appContext.get()?.let {
val cursor = it.contentResolver.query(uri, null, null, null, "date_added DESC, _id DESC")
if (cursor != null) {
if (cursor.moveToNext()) {
val dataColumn = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA)
val filePath = cursor.getString(dataColumn)
val name = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DISPLAY_NAME)
return#map Picture()
.apply {
this.name = cursor.getString(name)
this.path = filePath
}
}
cursor.close()
}
return#map Picture()
}
return#map Picture()
}
These pictures are then added to an Object, called file.
fun listenForGeneralPictures(observe: Flowable<Picture>?) {
observe?.apply {
generalPictureDisposable = concatMap {
if (it.name?.isNotEmpty() == true
&& it.path?.isNotEmpty() == true
&& file != null) {
it.categoryNr = Picture.CAT_GENERAL_PICTURES
file?.generalPictures?.add(it)
Log.d(it.name.toString(), "pictureAfter")
return#concatMap fileRepository.update(file!!)
} else {
return#concatMap Flowable.just(file)
}
}.subscribe({
cachedFile?.generalPictures = it!!.generalPictures
}, errorUtils::onError)
}
}
I'm using this, to get to the path and set the image to an Imageview:
override fun showPicture(path: String?) {
val pictureFile = File(path)
ivDraw?.setImageUri(FileProvider.getUriForFile(this, this.applicationContext.packageName + ".provider", pictureFile))
}
But when I do I get an error:
System.err: java.io.FileNotFoundException:
/external_path/DCIM/Camera/20180801_115654(1).jpg (No such file or
directory)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.(FileInputStream.java:146)
at java.io.FileInputStream.(FileInputStream.java:99)
at android.content.ContentResolver.openInputStream(ContentResolver.java:708)
at com.insypro.inspector3.ui.custom.picturedraw.DrawImageView.rotateImageToTakenDirection(DrawImageView.kt:108)
at com.insypro.inspector3.ui.custom.picturedraw.DrawImageView.setImageUri(DrawImageView.kt:54)
at com.insypro.inspector3.ui.picture.PictureViewActivity.showPicture(PictureViewActivity.kt:124)
at com.insypro.inspector3.ui.picture.PicturePresenter.processPicture(PicturePresenter.kt:69)
at com.insypro.inspector3.ui.picture.PicturePresenter.access$processPicture(PicturePresenter.kt:24)
at com.insypro.inspector3.ui.picture.PicturePresenter$loadDataPicture$1.accept(PicturePresenter.kt:51)
I also have a fileprovider file and everything needed in the manifest:
<provider
android:name="android.support.v4.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"
tools:replace="android:resource"/>
</provider>
and the paths:
<paths>
<files-path name="files" path="." />
<cache-path name="cache" path="/"/>
<external-path name="external_path" path="." />
<external-files-path name="external_files" path="." />
Well, first of all you need to understand where a FileProvider
is for. It is for sharing local files to other apps in a safe way: https://developer.android.com/reference/android/support/v4/content/FileProvider
You are only using the image file only in your own application. Therefore there is no need to use the FileProvider at all.
To show the image, use a BitmapFactory, note that your_path is the full path to the image, not changed by a FileProvider:
val bitmap = BitmapFactory.decodeFile(your_path);
ivDraw.setImageBitmap(bitmap);
I take images, using the following intent:
That Intent action simply opens a camera app, one of hundreds of possible apps. Whether the user takes pictures with that camera app is up to the user.
To make this work, I also have an Observer
There is no requirement for a camera app to have its images available via any ContentProvider, such as MediaStore.
There is no requirement for dataColumn to return a filesystem path.
There is no requirement for dataColumn to return a filesystem path that you have read access to.
IOW, this code will not be reliable across the ~24,000 Android device models and ~2 billion Android users.
I'm using this, to get to the path and set the image to an Imageview
Do not use setImageUri(). The documentation specifically advises against it.
Do not use FileProvider here. That is for sharing content with other apps, not for internal use within your own app. Moreover, because you have no idea where dataColumn will point, you cannot configure FileProvider to serve arbitrary files.
Instead, pass your "path" to your favorite image-loading library (e.g., Glide, Picasso), which can attempt to load your photo on a background thread and then populate your ImageView with the result.
Related
I am having trouble trying to show an image in a remote view with a contentUri. I have outlined the steps I took below. I believe I have followed the procedure correctly but still get a "Can't load widget" message. What am I doing wrong? Is the image saved to the correct storage area? Is the contentUri constructed correctly? Please help.
Blockquote
Save the image into my file directory. I can see the image successfully saved in data/data/com.mydomain/files/myImage.jpg when I check using Android Studio's Device File Explorer.
val file = File(applicationContext.filesDir, "myImage.jpg")
try {
FileOutputStream(file).use { out ->
myBitmap?.compress(Bitmap.CompressFormat.JPEG, 90, out)
}
} catch (e: IOException) {
e.printStackTrace()
}
Create a FileProvider in manifest and provider_paths.xml in res.xml
<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>
<paths>
<files-path name="name" path="." />
</paths>
Create a content Uri using getUriForFile. This returns a content uri of: content://com.mydomain.provider/name/myImage.jpg
val file = File(getAppInstance().filesDir, "myImage.jpg")
val contentUri = FileProvider.getUriForFile(
getAppInstance(),
BuildConfig.APPLICATION_ID + ".provider",
file
)
I pass the content Uri into Image() composable.
Image(
modifier = GlanceModifier.size(28.dp),
provider = ImageProvider(contentUri),
contentDescription = "Image"
)
Result on run:
I'm trying to save a file as PNG of a canvas where the user can draw something and then call an Intent.ACTION_SEND so that the user can share it's drawing with other apps.
The code is able to save the file without any problems, but when I try to use the MediaScannerConnection.scanFile(), the Uri returned by the function is null. I'm using the absolute path of the file created, so I can't understand why this is happening.
My class, called BitmapAsyncTask inherits from AsyncTask (yes, I know it's deprecated). Here's the important code:
Writing the file to memory:
override fun doInBackground(vararg p0: Any?): String {
var result = ""
try {
val bytes = ByteArrayOutputStream()
mBitmap.compress(Bitmap.CompressFormat.PNG, 95, bytes)
val file = File(externalCacheDir!!.absoluteFile.toString()
+ File.separator + "KidsDrawingApp_"
+ System.currentTimeMillis() / 1000 + ".png")
val fileOutput = FileOutputStream(file)
fileOutput.write(bytes.toByteArray())
fileOutput.close()
result = file.absolutePath
} catch (e: Exception) {
e.printStackTrace()
}
Log.d("File", result)
return result
}
** The mBitmap variable is just the Bitmap generated from the canvas.
Here, the Log.d returns, for instance:
D/File: /storage/emulated/0/Android/data/com.example.kidsdrawingapp/cache/KidsDrawingApp_1599992654.png
I can access the file just fine if I open the Files app and search for it.
But when I run the MediaScannerConnection on onPostExecute(), the function doesn't return an uri based on the absolute path at all. Here's the code:
MediaScannerConnection.scanFile(this#MainActivity, arrayOf(result), null) {
path, uri -> val shareIntent = Intent()
Log.d("Path", path)
Log.d("Uri", uri.toString())
shareIntent.action = Intent.ACTION_SEND
shareIntent.putExtra(Intent.EXTRA_STREAM, uri)
shareIntent.type = "image/png"
startActivity(
Intent.createChooser(
shareIntent, "Share image"
)
)
}
Once again, the Log.d("Path", path) returns the same file as the previous Log.d(), but when I try to convert the Uri to string, it crashes because it's null.
I tried adding "file://" + file.absolutePath" like I saw in some other answers but it still didn't work, the uri returned by the scanFile() was still null.
I'm using API 21.
File Provider Code
AndroidManifest.xml
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.example.kidsdrawingapp.fileprovider"
android:exported="false"
android:grantUriPermissions="true" >
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/path" />
</provider>
#xml/path.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="captured" path="Android/data/com.example.kidsdrawingapp/files" />
</paths>
I can't seem to figure out why it can't return a valid uri if the file is being saved in the phone and the path is a valid one
It is valid. However, it is not indexable by MediaStore on Android 10 and higher. MediaStore will no longer index files in app-specific external storage, such as getExternalFilesDir(), which is what you are using.
If your objective is to have the image be usable by every app on the device, then getting indexed by MediaStore is fine. On Android 10+, you can insert() into the MediaStore and use the resulting Uri for writing out your content. See this sample app for a demonstration, though in my case I am writing out a video, not a PNG.
If, instead, all you want to do is share this content, then do not use MediaScannerConnection. Instead, use FileProvider. See the documentation and this sample app (though in my case I am sharing a PDF, not a PNG).
... in case the above solution was not fully clear to everyone - here's how I applied the suggested fix to the reported file sharing issue within the tutorial exercise "Kids Drawing App" (from "The Complete Android 10 & Kotlin Development Masterclass" at Udemy):
// offer to share content
MediaScannerConnection.scanFile(
this#MainActivity,
arrayOf(result),
null
) { path, _ ->
// Use the FileProvider to get a content URI
val requestFile = File(path)
val fileUri: Uri? = try {
FileProvider.getUriForFile(
this#MainActivity,
AUTHORITY,
requestFile)
} catch (e: IllegalArgumentException) {
Log.e("File Selector",
"The selected file can't be shared: $requestFile")
null
}
val shareIntent = Intent()
shareIntent.action = Intent.ACTION_SEND
shareIntent.type = "image/png"
shareIntent.putExtra(Intent.EXTRA_STREAM, fileUri)
startActivity(
Intent.createChooser(
shareIntent, "Share"
)
)
}
... where I added the following AUTHORITY definition:
// static variables
companion object {
private const val STORAGE_PERMISSION_CODE = 1
private const val GALLERY = 2
private const val AUTHORITY = "${BuildConfig.APPLICATION_ID}.fileprovider"
}
I am kind of stuck on this one and have been working on it for a little while with no luck. I have an android application which allows the user to take photos/videos. The files are stored on external storage using a FileProvider. I have been trying (without luck) to get the videos to show up in the Photos app and have not been able to. The Intent.ACTION_MEDIA_SCANNER_SCAN_FILE and sendBroadcast works perfect for images but does not work on video. I know the videos are being captured, they are being saved in the correct location, and are not corrupted (i can play them in VideoView using FileProvider content Uri) I have not attempted to update this to Android 10 yet as my minimum target is 24 and i cannot seem to get it to work for that.
Creating the Intent.ACTION_MEDIA_SCANNER_SCAN_FILE and sendBroadcast the video does not show up. If i use MediaScannerConnection it does not show up. If i manually insert with the content resolver using the content URI it shows up in Photos but video is not playable and there is no preview. If i manually insert into the content resolver with the absolute path it does not show up at all in Photos
Below is the code i use to take the video and add to the MediaStore
File Provider
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.FileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths" />
</provider>
File Provider Paths
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-files-path name="Image" path="Image" />
<external-files-path name="Recording" path="Recording"/>
<external-files-path name="Video" path="Video"/>
</paths>
Methods to create the file and call Intent to capture video
private fun takeVideo() {
Intent(MediaStore.ACTION_VIDEO_CAPTURE).also{ videoIntent ->
val videoFile: File? = try{
createVideoFile()
}catch(ex: IOException){
Toast.makeText(mMainActivityHelper.contextProvider(), R.string.error_taking_photo, Toast.LENGTH_SHORT).show()
Log.w("OPENING_VIDEO_FILE", "Error opening video file with message = " + ex.message)
return
}
mFilePath = Uri.parse(videoFile?.absolutePath)
videoFile?.also{
videoIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
mFileUri = FileProvider.getUriForFile(mMainActivityHelper.contextProvider(), "FileProvider", it)
videoIntent.putExtra(MediaStore.EXTRA_OUTPUT, mFileUri)
mMainActivityHelper.startActivityForResult(videoIntent, MainActivity.TAKE_VIDEO)
}
}
}
#Throws(IOException::class)
private fun createVideoFile(): File? {
val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date())
val externalDir = mMainActivityHelper.externalFilesDirProvider(null)
val imagePath = File(externalDir, "NuNoteVideo")
if(!imagePath.exists())
imagePath.mkdir()
return File(imagePath.path, "MPEG_${timeStamp}" + ".mp4")
}
OnActivityResult code i have tried and none of it has worked. I have tried with both the content URI and the absolute path with no luck
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when{
requestCode == TAKE_VIDEO && resultCode == Activity.RESULT_OK->{
val cv = ContentValues(3).apply {
val absolutePath = myObjectWithThePath.mFilePath.toString()
val name = absolutePath.substring(absolutePath.lastIndexOf("/") + 1)
put(MediaStore.Video.Media.TITLE, name)
put(MediaStore.Video.Media.DISPLAY_NAME, name)
put(MediaStore.Video.Media.MIME_TYPE, "video/mp4")
put(MediaStore.Video.Media.DATE_ADDED, Date().time)
put(MediaStore.MediaColumns.DATA, absolutePath)
contentResolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, this)
}
Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE).also { mediaScanIntent ->
val fileUri = myObjectWithThePath.mFileUri
if(fileUri != null) {
val f = File(fileUri)
mediaScanIntent.data = Uri.fromFile(f)
//mediaScanIntent.type = "video/mp4"
sendBroadcast(mediaScanIntent)
}
}
val f = File(myObjectWithThePath.mFilePath.toString())
MediaScannerConnection.scanFile(applicationContext, listOf(f.absolutePath).toTypedArray(), listOf("video/mp4").toTypedArray()){
path, uri ->
print(path)
print(uri) //This shows a URI if i use the absolute path but nothing shows up in the photos app. If i use content uri with FileProvider is null
}
I have looked at many many many anwsers on Stack already and nothing has worked. Any help is greatly appreciated
Video not shown on Gallery
MediaScanner and ScopedStorage on SDK-29
MediaStore.ACTION_VIDEO_CAPTURE not saving the video in Nougat 7.0
ACTION_MEDIA_SCANNER_SCAN_FILE from external sdcard Lollipop+
Saving photos and videos using Android FileProvider to the gallery
android - save image into gallery
MediaScannerConnection doesn't work
Android How to use MediaScannerConnection scanFile
Android MediaStore insertVideo
Capturing and Saving Videos in Android (API > 24) using File object?
Posting an update. I solved this by creating a video without providing a file path. This creates the video in the DCIM folder. When the video is created I save the uri, and query the uri to make sure it still exists on the load of the application. Not exactly what i wanted but it will works
The contract has been changed to return Boolean instead of Bitmap starting in androidx.activity version 1.2.0-alpha05. How can I use the Boolean returned by the built in AndroidResultContracts.TakePicture() contract to access and display the photo just taken by the user?
I am using
implementation 'androidx.activity:activity-ktx:1.2.0-alpha07'
implementation 'androidx.fragment:fragment-ktx:1.3.0-alpha07'
Here's my full sample code showing how to use the built-in Android Result Contract to take a photo from your application and display it in an ImageView.
Note: My solution uses View Binding
MainActivity's layout XML included (1) a button defining onTakePhotoClick as the onClick event and (2) and ImageView to display the photo taken.
<Button
android:id="#+id/take_photo_button"
style="#style/Button"
android:drawableStart="#drawable/ic_camera_on"
android:onClick="onTakePhotoClick"
android:text="#string/button_take_photo"
app:layout_constraintTop_toBottomOf="#id/request_all_button" />
...
<ImageView
android:id="#+id/photo_preview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
app:layout_constraintTop_toBottomOf="#id/take_video_button" />
In my MainActivity I have done the following:
Defined imageUri: Uri? which will be set to the uri of the image taken by the TakePicture() contract.
Implemented onTakePhotoClick() to check for the necessary camera permissions before launching the TakePicture() contract.
Defined takePictureRegistration: ActivityResultLauncher which will actually launch the request to take a photo on the device. When isSuccess is returned as true then I know the imageUri I previously defined now references the photo I just took.
Defined a takePicture: Runnable simply for code reuse. Note that the 2nd String parameter passed to the FileProvider.getUriForFile(context, authority, file) method will need to match the authorities attribute provided to the <provider> in your app's AndroidManifest.xml.
For full transparency, I have also added the code showing how I use the ActivityResultContracts.RequestPermission() to request the user for runtime permissions to access the camera.
private var imageUri: Uri? = null
/**
* Function for onClick from XML
*
* Check if camera permission is granted, and if not, request it
* Once permission granted, launches camera to take photo
*/
fun onTakePhotoClick(view: View) {
if (!checkPermission(Manifest.permission.CAMERA)) {
// request camera permission first
onRequestCameraClick(callback = takePicture)
} else {
takePicture.run()
}
}
private val takePicture: Runnable = Runnable {
ImageUtils.createImageFile(applicationContext)?.also {
imageUri = FileProvider.getUriForFile(
applicationContext,
BuildConfig.APPLICATION_ID + ".fileprovider",
it
)
takePictureRegistration.launch(imageUri)
}
}
private val takePictureRegistration =
registerForActivityResult(ActivityResultContracts.TakePicture()) { isSuccess ->
if (isSuccess) {
mBinding.photoPreview.setImageURI(imageUri)
}
}
/**
* Function for onClick from XML
*
* Launches permission request for camera
*/
fun onRequestCameraClick(view: View? = null, callback: Runnable? = null) {
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean ->
// update image
mBinding.iconCameraPermission.isEnabled = isGranted
val message = if (isGranted) {
"Camera permission has been granted!"
} else {
"Camera permission denied! :("
}
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
if (isGranted) {
callback?.run()
}
}.launch(Manifest.permission.CAMERA)
}
For full transparency the ImageUtils utility class has the createImageFile() method defined as follows and returns a File? when given context. Note that I am using the external files directory as the storage directory for my FileProvider.
object ImageUtils {
lateinit var currentPhotoPath: String
#Throws(IOException::class)
fun createImageFile(context: Context): File? {
// Create an image file name
val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(Date())
val storageDir: File? = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)
return File.createTempFile(
"JPEG_${timeStamp}_", /* prefix */
".jpg", /* suffix */
storageDir /* directory */
).apply {
// Save a file: path for use with ACTION_VIEW intents
currentPhotoPath = absolutePath
}
}
}
Don't forget to add the uses-permission, uses-feature and provider tags to the AndroidManifest.
Also make sure the authorities attribute provided to the <provider> matches the 2nd String parameter passed to FileProvider.getUriForFile(context, authority, file) method. In my example, I have made my authority the package name + ".fileprovider". Read more about FileProvider from Google's documentation.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.captech.android_activity_results">
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.camera" />
<application
...
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.captech.android_activity_results.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths" />
</provider>
</application>
</manifest>
My res/xml/file_paths is shown below. Because I am using getExternalFilesDir(), I am using the <external-files-path> tags in the XML.
Note: If you are NOT using the external files directory, you may want to look up which FileProvider storage directory you want to specify in your XML tags here.
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-files-path
name="my_images"
path="/" />
</paths>
The result would display the imageUri in the ImageView:
I've been struggling with this same issue and only just came up with a (somewhat) tenable solution involving ContentResolver.
The documentation leaves a lot to the imagination. A major concern with this approach is that the captured image URI has to be managed external to the ActivityResultContract, which seems counterintuitive as the original question already points out.
I do not know of another way to insert media into the gallery that would solve that part of the problem, but I would absolutely love to see that solution.
// Placeholder Uri
var uri: Uri? = null
// ActivityResultContract for capturing an image
val takePicture =
registerForActivityResult(contract =
ActivityResultContracts.TakePicture()) { imageCaptured ->
if (imageCaptured) {
// Do stuff with your Uri here
}
}
...
fun myClickHandler() {
// Create a name for your image file
val filename = "${getTimeStamp("yyyyMMdd_HHmmss")}-$label.jpg"
// Get the correct media Uri for your Android build version
val imageUri =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
MediaStore.Images.Media.getContentUri(
MediaStore.VOLUME_EXTERNAL_PRIMARY)
} else {
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
}
val imageDetails = ContentValues().apply {
put(MediaStore.Audio.Media.DISPLAY_NAME, filename)
}
// Try to create a Uri for your image file
activity.contentResolver.insert(imageUri, imageDetails).let {
// Save the generated Uri using our placeholder from before
uri = it
// Capture your image
takePicture.launch(uri)
} ?: run {
// Something went wrong
}
}
How to send(share) *csv file?
I have android app, wich create a csv file. And i want to share it: send to email, open at excel and so on.
I read tutorials:set up file sharing and sharing a file, but can not understand: is it for my option or not?
I declare a manifest:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.nam1.name2.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/filepaths" />
</provider>
But what i should do next?
Can you tell me some simple code example (maybe git-repo) how to share file to another apps?
Thank you!
EDIT: I write some new code to share files (look at FileProvider example)
public class ExportActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_export);
Intent intentShareFile = new Intent(Intent.ACTION_SEND);
intentShareFile.setAction(Intent.ACTION_SEND);
File imagePath = new File(getApplicationContext().getFilesDir(), "statistics");
File newFile = new File(imagePath, "stat.csv");
CSVHelper csvHelper = new CSVHelper(SharedData.AllPlayersColl);
try {
String path=imagePath.getAbsolutePath();
csvHelper.SaveToCSV(path);
} catch (IOException e) {
e.printStackTrace();
}
Context context=getApplicationContext();
Uri contentUri = getUriForFile(context, "com.name1.name2.fileprovider", newFile);
List<ResolveInfo> resInfoList = getApplicationContext().getPackageManager()
.queryIntentActivities(intentShareFile, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
String packageName = resolveInfo.activityInfo.packageName;
getApplicationContext()
.grantUriPermission(packageName, contentUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
intentShareFile.setData(contentUri);
intentShareFile.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
setResult(100, intentShareFile);
startActivityForResult(intentShareFile,100);
}
}
Where CSVHelper is:
fun SaveToCSV(fileName: String?) {
if (fileName == null)
throw NullPointerException("fileName is null!")
val writer = CSVWriter(FileWriter(fileName), '\t')
// make csv file
writer.writeNext(firstLine);
}
And filepaths is:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<paths>
<files-path name="stat" path="statistics/" />
</paths>
But, i get a error:
Caused by: android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.SEND dat=content://com.name1.name2.fileprovider/stat/stat.csv flg=0x2 }
I want, that when i start an Intent a list of variants shows (at android device) : email_app,excel_app and so on. So, i want to send noname intent.
FileProvider is a helper class designed to share files as content:// URIs instead of file:// URIs which have been deprecated for some time and forbidden since API level 24.
You have declared the content provider, you need now to configure it, i.e. choose what file it can serve. This is done in the xml/filepath file that you have declared in the meta-data. You will then be able to generate shareable content URIs using FileProvider.getUriForFile().
There is a complete wrap up
Unfortunately not all application understand content:// URIs. If you need to share a file with a (very old or badly written) application which only handle file:// URIs you may still use them if you set the target level of your application to 23 or lower.