How to handle scoped storage backward compatibility? - android

My app's targetSdkVersion is 30, now I am trying to save image in the gallery. it works in android 11 and android 10 but does not work in android 9 and below versions.
Shows error (permission denial) in android 9 and below versions.
CODE
public fun saveImageToStorage(
mContext: DisplayActivity,
bitmap: Bitmap,
filename: String = "screenshot.jpg",
)
{
try {
val values = ContentValues().apply {
put(MediaStore.Images.Media.DISPLAY_NAME, filename)
put(MediaStore.Images.Media.MIME_TYPE, mimeType)
put(MediaStore.Images.Media.RELATIVE_PATH, directory)
}
mContext.contentResolver.run {
val uri =
mContext.contentResolver.insert(mediaContentUri, values)
?: return
imageOutStream = openOutputStream(uri) ?: return
}
imageOutStream.use { bitmap.compress(Bitmap.CompressFormat.JPEG, 100, it) }
} catch (th: Throwable) {
}
}
AndroidManifest
No permission declared in manifest file

keep using the "old ways" of external storage, by asking permission of external storage for android 9 and below
just add this in manifest
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />

MediaStoreCompat from SimpleStorage can handle the backward compatibility:
val fileDesc = FileDescription(fileName, "", "image/jpg")
val mediaFile = MediaStoreCompat.createImage(applicationContext, fileDesc, ImageMediaDirectory.PICTURES)
mediaFile?.openOutputStream()?.use { bitmap.compress(Bitmap.CompressFormat.JPEG, 100, it) }

Related

Copy Files from Internal Storage to SD Card

I am trying to copy a file from internal storage to external storage (SD card) in my Android application. I have the source file in a File object and the destination folder in a String, but I keep getting the error "java.io.FileNotFoundException: open failed: EACCES (Permission denied)".
I am trying to make a gallery, when I select the copy button, it launches an activity where an album is selected and the path is returned as follows as an extra:
var resultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
// There are no request codes
val data: Intent? = result.data
val ruta: String = data?.getStringExtra("RUTA")!!
Toast.makeText(this, ruta, Toast.LENGTH_SHORT).show()
}
}
The album path is in this format: /storage/4329-1A0A/DCIM/Facebook
I have tried many different ways to copy the file, I have tried with MediaStore, Files.copy(), File.copy, shell commands, I have the following permissions in the manifest.xml and these permissions are requested at the start of the app:
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="29" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.MANAGE_MEDIA"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.MANAGE_DOCUMENTS"
tools:ignore="ProtectedPermissions" />
This is the way I am trying to copy with shell:
fun copyFileWithShell(context: Context, src: File, dst: File) {
try {
val command = "cp ${src.absolutePath} ${dst.absolutePath}"
val process = Runtime.getRuntime().exec(command)
process.waitFor()
Toast.makeText(context, "File copied successfully", Toast.LENGTH_SHORT).show()
} catch (e: Exception) {
Toast.makeText(context, "Failed to copy file", Toast.LENGTH_SHORT).show()
}
}
This code gives me the error W/System.err: java.io.FileNotFoundException: open failed: EACCES (Permission denied)
fun copyOrMoveImage(operation: String, source: File, destination: String) {
try {
val fileInputStream = FileInputStream(source)
val fileOutputStream = FileOutputStream(destination + "/" + source.name)
val buf = ByteArray(1024)
var len: Int
while (fileInputStream.read(buf).also { len = it } > 0) {
fileOutputStream.write(buf, 0, len)
}
fileInputStream.close()
fileOutputStream.close()
if (operation == "MOVE") {
source.delete()
}
} catch (e: Exception) {
e.printStackTrace()
}
}
val ruta: String = data?.getStringExtra("RUTA")!!
val file = File(media!![position].path)
when (OPERATION) {
"MOVE" -> copyOrMoveImage("MOVE", file, ruta)
"COPY" -> copyOrMoveImage("COPY", file, ruta)
}
This is the result of using geExternalFilesDirs():
/storage/emulated/0/Android/data/com.example.photo/files
/storage/emulated/0/
Also I declare android:requestLegacyExternalStorage="true" in the manifest
The targetSDK of the project is 33. The device where I am trying has Android Q.
Using Environment.getExternalStorageDirectory() returns the path of the Internal Storage ("/storage/emulated/0") instead of The SD Card path ("/storage/4329-1A0A/"), the same with getExternalFilesDirs()

Kotlin - Create directory in Environment.getExternalStorageDirectory().getAbsolutePath() on Android 10+

This has been asked before but I am unable to find an answer that works well for me.
I have an app in which, at first run, I need to create some directories and files in those directories.
What I have done so far works well on Android 5 to 9.
To my surprise, it does no work on Android 10+ since getExternalStorageDirectory() is deprecated.
This is what I am doing so far:
if(isFirstRun)
{
Log.i("MyApp","ServerWizardActivity > createNecesaryFoldersFiles > isFirstRun")
val absoluteExternalStorageDirectory = Environment.getExternalStorageDirectory().getAbsolutePath()
val appDirectory = File("${absoluteExternalStorageDirectory}/MyApp/")
val picturesDirectory = File("${absoluteExternalStorageDirectory}/Pictures/")
val fullPath: String? = "${absoluteExternalStorageDirectory}/MyApp/${jsonFileName}"
var dataFile = File(fullPath)
if (!appDirectory .exists())
{
Log.i("MyApp","ServerWizardActivity > createNecesaryFoldersFiles > appDirectory")
appDirectory .mkdir()
}
if (!picturesDirectory.exists())
{
Log.i("MyApp","ServerWizardActivity > createNecesaryFoldersFiles > picturesDirectory")
picturesDirectory.mkdir()
}
if(!dataFile.exists())
{
Log.i("MyApp","ServerWizardActivity > createNecesaryFoldersFiles > dataFile")
dataFile.createNewFile()
}
}
else
{
Log.i("MyApp","ServerWizardActivity > createNecesaryFoldersFiles > isNotFirstRun")
}
So far so good.
However, I need to create a directory directly on the Device Storage, on the same level with DCIM, Pictures, Documents and Downloads so that I can make it consistent with Android 5-9 version and the iOS version of the app.
I tried the code below for Android 10+ and it works but I can only create a directory in one of the directories in Environment (in this case, the Pictures directory).
Is there any way to bypass? I don't want to change the entire app structure because of this.
if(isFirstRun)
{
val resolver = contentResolver
val contentValues = ContentValues()
contentValues.put(
MediaStore.MediaColumns.RELATIVE_PATH,
Environment.DIRECTORY_PICTURES + "/MyApp"
)
val path = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues).toString()
val folder = File(path)
val isCreated = folder.exists()
if (!isCreated)
{
folder.mkdirs()
}
}
Oh, and soi far I have these in my Android manifest file:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<application
android:requestLegacyExternalStorage="true"
</application>
Try with the following code it will help you to create a test directory inside document directory.
//Make sure don't forget to ask runtime permission of read/write file
private fun writeFile(fileData: String, fileName: String) {
val dir = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS)
.toString() + "/" + "test"
)
} else {
File(
Environment.getExternalStorageDirectory()
.toString() + "/${Environment.DIRECTORY_DOCUMENTS}/" + "test"
)
}
dir.apply {
if (!this.exists()) this.mkdir()
File(this, "$fileName.txt").apply {
if (!this.exists()) this.createNewFile()
FileOutputStream(this).apply {
write(fileData.toByteArray())
close()
}
}
}
}

Replacement for getExternalStoragePublicDirectory() API 21-30

My app's minSdkVersion is 21 and targetSdkVersion is 30. I need to save image to external storage (to Pictures folder)
So, here's saveImage function:
fun saveImage(context: Context) {
val fileName = "${System.currentTimeMillis()}.png"
val fileType = "image/png"
val folder = "MyApp"
val imageQuality = 100
val write: (OutputStream) -> Boolean = { outputStream ->
this.compress(Bitmap.CompressFormat.PNG, imageQuality, outputStream)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, fileName)
put(MediaStore.MediaColumns.MIME_TYPE, fileType)
put(MediaStore.MediaColumns.RELATIVE_PATH, "${Environment.DIRECTORY_PICTURES}/$folder")
}
context.contentResolver.let {
it.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)?.let { uri ->
it.openOutputStream(uri)?.let(write)
}
}
} else {
val imagesDir = Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
.toString() + File.separator + folder
val file = File(imagesDir)
if (!file.exists()) {
file.mkdir()
}
val image = File(imagesDir, fileName)
write(FileOutputStream(image))
}
}
Also I have this permission in Manifest file:
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
This is working ok, but getExternalStoragePublicDirectory is deprecated in API 29+.
Is there a way to get rid of this deprecated function? Right now I just suppress the warning, but it feels kinda bad.

How to make Gallery app on Andorid 10 + 11 show image saved to external storage

So I have the following code:
fun saveMediaToStorage(bitmap: Bitmap, context: Context) {
val filename = "${System.currentTimeMillis()}.jpg"
var fos: OutputStream? = null
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
context.contentResolver?.also { resolver ->
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, filename)
put(MediaStore.MediaColumns.MIME_TYPE, "image/jpg")
put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES)
}
val imageUri: Uri? =
resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
fos = imageUri?.let { resolver.openOutputStream(it) }
}
} else {
val imagesDir =
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
val image = File(imagesDir, filename)
fos = FileOutputStream(image)
}
fos?.use {
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, it)
}
}
I have the permission in the manifest file:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
As well as the attribute:
android:requestLegacyExternalStorage="true"
I see the image saved in the proper location when using a FileExplorer app, but the Gallary app doesn't recognize it.
Does anyone notice something that I've done wrong or missed?

Environment.getExternalStorageDirectory() deprecated in API level 29 java

Working on android Java, recently updated SDK to API level 29 now there is a warning shown which states that
Environment.getExternalStorageDirectory() is deprecated in API level 29
My code is
private void saveImage() {
if (requestPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
final String folderPath = Environment.getExternalStorageDirectory() + "/PhotoEditors";
File folder = new File(folderPath);
if (!folder.exists()) {
File wallpaperDirectory = new File(folderPath);
wallpaperDirectory.mkdirs();
}
showLoading("Saving...");
final String filepath=folderPath
+ File.separator + ""
+ System.currentTimeMillis() + ".png";
File file = new File(filepath);
try {
file.createNewFile();
SaveSettings saveSettings = new SaveSettings.Builder()
.setClearViewsEnabled(true)
.setTransparencyEnabled(true)
.build();
if(isStoragePermissionGranted() ) {
mPhotoEditor.saveAsFile(file.getAbsolutePath(), saveSettings, new PhotoEditor.OnSaveListener() {
#Override
public void onSuccess(#NonNull String imagePath) {
hideLoading();
showSnackbar("Image Saved Successfully");
mPhotoEditorView.getSource().setImageURI(Uri.fromFile(new File(imagePath)));
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,Uri.fromFile(new File(filepath))));
Intent intent = new Intent(EditImageActivity.this, StartActivity.class);
startActivity(intent);
finish();
}
#Override
public void onFailure(#NonNull Exception exception) {
hideLoading();
showSnackbar("Failed to save Image");
}
});
}
What will be the alternative for this?
Use getExternalFilesDir(), getExternalCacheDir(), or getExternalMediaDirs() (methods on Context) instead of Environment.getExternalStorageDirectory().
Or, modify mPhotoEditor to be able to work with a Uri, then:
Use ACTION_CREATE_DOCUMENT to get a Uri to a location of the user's choosing, or
Use MediaStore, ContentResolver, and insert() to get a Uri for a particular type of media (e.g., an image) — see this sample app that demonstrates doing this for downloading MP4 videos from a Web site
Also, note that your Uri.fromFile with ACTION_MEDIA_SCANNER_SCAN_FILE should be crashing on Android 7.0+ with a FileUriExposedException. On Android Q, only the MediaStore/insert() option will get your content indexed by the MediaStore quickly.
Note that you can opt out of these "scoped storage" changes on Android 10 and 11, if your targetSdkVersion is below 30, using android:requestLegacyExternalStorage="true" in the <application> element of the manifest. This is not a long-term solution, as your targetSdkVersion will need to be 30 or higher sometime in 2021 if you are distributing your app through the Play Store (and perhaps elsewhere).
Get the destPath with the new API call:
String destPath = mContext.getExternalFilesDir(null).getAbsolutePath();
For Android Q, you can add android:requestLegacyExternalStorage="true" to your element in the manifest. This opts you into the legacy storage model, and your existing external storage code will work.
<manifest ... >
<!-- This attribute is "false" by default on apps targeting
Android 10 or higher. -->
<application android:requestLegacyExternalStorage="true" ... >
...
</application>
</manifest>
Technically, you only need this once you update your targetSdkVersion to 29. Apps with lower targetSdkVersion values default to opting into legacy storage and would need android:requestLegacyExternalStorage="false" to opt out.
Please use getExternalFilesDir(), getExternalCacheDir() instead of Environment.getExternalStorageDirectory() when you creating file in Android 10.
See below line:
val file = File(this.externalCacheDir!!.absolutePath, "/your_file_name")
This is a small example how to get URI for a file if you want to take photo using default camera and store it in a DCIM folder (DCIM/app_name/filename.jpg):
Open camera (remember about CAMERA permission):
private var photoURI: Uri? = null
private fun openCamera() {
Intent(MediaStore.ACTION_IMAGE_CAPTURE).also { takePictureIntent ->
photoURI = getPhotoFileUri()
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI)
takePictureIntent.resolveActivity(requireActivity().packageManager)?.also {
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE)
}
}
}
And get URI:
private fun getPhotoFileUri(): Uri {
val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date())
val fileName = "IMG_${timeStamp}.jpg"
var uri: Uri? = null
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val resolver = requireContext().contentResolver
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, fileName)
put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
put(MediaStore.MediaColumns.RELATIVE_PATH, "DCIM/app_name/")
}
uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
}
return uri ?: getUriForPreQ(fileName)
}
private fun getUriForPreQ(fileName: String): Uri {
val dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
val photoFile = File(dir, "/app_name/$fileName")
if (photoFile.parentFile?.exists() == false) photoFile.parentFile?.mkdir()
return FileProvider.getUriForFile(
requireContext(),
"ru.app_name.fileprovider",
photoFile
)
}
Don't forget about WRITE_EXTERNAL_STORAGE permission for pre Q and add a FileProvider to AndroidManifest.xml.
And get a result:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
REQUEST_IMAGE_CAPTURE -> {
photoURI?.let {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val thumbnail: Bitmap =
requireContext().contentResolver.loadThumbnail(
it, Size(640, 480), null
)
} else {
// pre Q actions
}
}
}
}
}
This worked for me
Add this line in application tag of manifest file
android:requestLegacyExternalStorage="true"
Example
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:networkSecurityConfig="#xml/network_security_config"
android:requestLegacyExternalStorage="true"
android:supportsRtl="true"
android:theme="#style/AppTheme">
</application>
Target SDK is 29
defaultConfig {
minSdkVersion 16
targetSdkVersion 29
multiDexEnabled true
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
To get internal storage directory without hard coding,
Permissions (For all Android versions). Don't forget to get permissions from the user.
Request all files access
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="29" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" />
Legacy permission for Android 10 (add this to AndroidManifest.xml > application tag).
android:requestLegacyExternalStorage="true"
Get internal storage directory path:
public static String getInternalStorageDirectoryPath(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
return storageManager.getPrimaryStorageVolume().getDirectory().getAbsolutePath();
} else {
return Environment.getExternalStorageDirectory().getAbsolutePath();
}
}
This worked
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
contentResolver?.also { resolver ->
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, "Image_"+".jpg")
put(MediaStore.MediaColumns.MIME_TYPE, "image/jpg")
put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES + File.separator+ "TestFolder")
}
val imageUri: Uri? = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
fos = imageUri?.let { resolver.openOutputStream(it) }
bitmap.compress(Bitmap.CompressFormat.JPEG,100,fos)
Objects.requireNonNull(fos)
}
}
You could make use of StorageManager & StorageVolume classes
StorageVolume.getPrimaryStorageVolume(): This volume is the same storage device returned by Environment#getExternalStorageDirectory() and Context#getExternalFilesDir(String).
public String myGetExternalStorageDir() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
return getPrimaryStorageVolumeForAndroid11AndAbove();
else
return getPrimaryStorageVolumeBeforeAndroid11();
}
#TargetApi(Build.VERSION_CODES.R)
private String getPrimaryStorageVolumeForAndroid11AndAbove() {
StorageManager myStorageManager = (StorageManager) ctx.getSystemService(Context.STORAGE_SERVICE);
StorageVolume mySV = myStorageManager.getPrimaryStorageVolume();
return mySV.getDirectory().getPath();
}
private String getPrimaryStorageVolumeBeforeAndroid11() {
String volumeRootPath = "";
StorageManager myStorageManager = (StorageManager) ctx.getSystemService(Context.STORAGE_SERVICE);
StorageVolume mySV = myStorageManager.getPrimaryStorageVolume();
Class<?> storageVolumeClazz = null;
try {
storageVolumeClazz = Class.forName("android.os.storage.StorageVolume");
Method getPath = storageVolumeClazz.getMethod("getPath");
volumeRootPath = (String) getPath.invoke(mySV);
} catch (Exception e) {
e.printStackTrace();
}
return volumeRootPath;
}
private fun saveImage(bitmap: Bitmap, name: String) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val resolver = contentResolver
val contentValues = ContentValues()
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, name)
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/png")
contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, "DCIM/" + "YOUR_FOLDER")
val imageUri =
resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
val fos = resolver.openOutputStream(imageUri!!)
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos)
fos!!.flush()
fos.close()
toast("Saved to gallery")
} else {
if (isPermissionGranted(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
val imagesDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DCIM
).toString() + File.separator + "YOUR_FOLDER"
if (!file.exists()) {
file.mkdir()
}
val image = File(imagesDir, "$name.png")
val fos = FileOutputStream(image)
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos)
fos.flush()
fos.close()
} else {
// ask for permission
}
}
}
Recently I also face similar kind of issues, Due to my code was large and i don't want to add new functionality in existing code so i just simply change path..
Environment.getExternalStorageDirectory() Replace with
context.getExternalFilesDir(null).getAbsolutePath()
Code
private void saveImage() {
if (requestPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
final String folderPath = this.getExternalFilesDir(null).getAbsolutePath() + "/PhotoEditors";
File folder = new File(folderPath);
if (!folder.exists()) {
File wallpaperDirectory = new File(folderPath);
wallpaperDirectory.mkdirs();
}
showLoading("Saving...");
final String filepath=folderPath
+ File.separator + ""
+ System.currentTimeMillis() + ".png";
File file = new File(filepath);
try {
file.createNewFile();
SaveSettings saveSettings = new SaveSettings.Builder()
.setClearViewsEnabled(true)
.setTransparencyEnabled(true)
.build();
if(isStoragePermissionGranted() ) {
mPhotoEditor.saveAsFile(file.getAbsolutePath(), saveSettings, new PhotoEditor.OnSaveListener() {
#Override
public void onSuccess(#NonNull String imagePath) {
hideLoading();
showSnackbar("Image Saved Successfully");
mPhotoEditorView.getSource().setImageURI(Uri.fromFile(new File(imagePath)));
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,Uri.fromFile(new File(filepath))));
Intent intent = new Intent(EditImageActivity.this, StartActivity.class);
startActivity(intent);
finish();
}
#Override
public void onFailure(#NonNull Exception exception) {
hideLoading();
showSnackbar("Failed to save Image");
}
});
}
var tempDir: File = inContext.getExternalFilesDir("/")!!
tempDir = File(tempDir.getAbsolutePath().toString() + "/.IncidentImages/")
tempDir.mkdir()
If you work with XAMARIN and are confused by all this different answers (like me) just follow this example:
var picture = new Java.IO.File(Environment.DirectoryPictures, "fileName");
Took me some time to figure this out.

Categories

Resources