Xamarin android display image from external Storage - android

I'm currently trying to displa an image from the storage, but I have no success.
What I'm dooing.
public Stream ReadImage(string path)
{
//var uri = Android.Net.Uri.Parse(path);
//var stream = MainActivity._activity.ContentResolver.OpenInputStream(uri);
//return stream;
var memoryStream = new MemoryStream();
using (var source = System.IO.File.OpenRead(path))
{
source.CopyTo(memoryStream);
}
return memoryStream;
}
string path = "/storage/emulated/0/DCIM/Camera/IMG_20190521_094202.jpg"
var imageSource = ImageSource.FromStream(
delegate {
return DependencyService.Get<IMediaHelper>().ReadImage(path);
});
But in the using line the programm doese not proceed, it does not reach the following lines and it does not load the file from the storage, the way with the contetn resolver does end teh same way, in the contentresolver line.
I have the Read/write external storage permission.
I am using android x, with Xamarin 5.0.0.2012. Under android 10 & and 11, on multiple different xiaomi devices.
This might be a bug, because I think, I had it running in an earlier project.
Some insight woult be appreciated, I'm biting my teath out on this nut.

To give users more control over their files and to limit file clutter, apps that target Android 10 (API level 29) and higher are given scoped access into external storage, or scoped storage, by default. Such apps have access only to the app-specific directory on external storage, as well as specific types of media that the app has created.You could read it here.
For android 10,you could request the requestLegacyExternalStorage attribute in your Application tag in the AndroidManifest.
<application android:label="NewForms.Android" android:resizeableActivity="true" android:requestLegacyExternalStorage="true" android:theme="#style/MainTheme">
For android 11,you need add <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> in your AndroidManifest.And determine in the Activity whether the permission is enabled.
And you can't forget to dynamically request WRITE_EXTERNAL_STORAGE permissions (this was added after Android 6.0,named Runtime Permissions).
The final code is as follows:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.companyname.newforms" android:installLocation="preferExternal">
<uses-sdk android:minSdkVersion="18" android:targetSdkVersion="30" />
<application android:label="NewForms.Android" android:requestLegacyExternalStorage="true" android:theme="#style/MainTheme"></application>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
</manifest>
and you could request the runtime permission like this in your MainActivity:
RequestPermissions(new string[] { Manifest.Permission.WriteExternalStorage}, 0);
if (Build.VERSION.SdkInt > BuildVersionCodes.Q)
{
if (!Environment.IsExternalStorageManager)
{
StartActivityForResult(new Intent( Android.Provider.Settings.ActionManageAllFilesAccessPermission), 101);
}
}

Related

All Files Access Permission Policy: Not a core feature App Rejected by Playstore

The story starts when my app get rejected from Play Store. I have a feature that user needs to take picture and upload to Server. So I have to take picture and save it somewhere in the storage area.
So I have these permissions in android manifest file
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature
android:name="android.hardware.camera"
android:required="true" />
<uses-feature
android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.test.fileupload.provider"
android:exported="false"
android:grantUriPermissions="true">
<!-- ressource file to create -->
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths"></meta-data>
</provider>
For Android APi 30 + , there is a need to request MANAGE_EXTERNAL_STORAGE otherwise, it crashes .
<uses-permission
android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
android:minSdkVersion="30" /
I save images to externalStorage.
val storageDir: File? = File( Environment.getExternalStorageDirectory().toString() +"/myimages")
Even I save photos in app's internal storage , MANAGE_EXTERNAL_STORAGE is required for API 30+. Otherwise it crashes.
Update -> I change it to
with
val storageDir: File? = File( context?.filesDir.toString() +"/my_images")
And some says we are supposed to use MediaStore . And I have tried
val mimeType = "image/*"
val values = ContentValues().apply {
put(MediaStore.Images.Media.DISPLAY_NAME, getNewFileName())
put(MediaStore.Images.Media.MIME_TYPE, mimeType)
put(
MediaStore.Images.Media.RELATIVE_PATH,
relativeLocation
)
}
val imageUri =
context.contentResolver.insert(MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL), values)
if (imageUri != null) {
currentPhotoPath = imageUri.toString()
shareUri = imageUri
}
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri)
The problem only happens when I try to convert imageUri to File .
imageUri from mediastore doesn't provide full path . I need actual file path so that I can upload to server.
Which library should I use to save image so that my app got approved by Google Playstore? It has been long week .Any comment/ solution is really appreciated .

Xamarin.Android desperately need to update but can't due to external storage

So my company's app desperately needs to be updated. However, I've always avoided targeting SDK 30 for not having to deal with the whole 'getting rejected due to MANAGE_EXTERNAL_STORAGE'.
FYI: I'm very poor at programming and lave little knowledge especially in this subject with things not coding related..
The only thing, literally the only thing this app does is retreive a base64 pdf, convert it, save it to the device, and open it.
I cannot find a simple way/explanation anywhere to work around this. My app needs to be updated, but I'm forced to use SDK30 which google will reject due to this whole storage policy thing..
This is how we work with PDF's in our code:
private async void PDFDrawer(int pos)
{
UI ui = new UI(this);
ui.ShowProgressDialog("", "Laden");
Console.WriteLine(invoices[pos].Obj["InvoiceID"].ToString());
//get PDF based on list selection
JsonValue json = await getPDFTask(invoices[pos].Obj["InvoiceID"].ToString());
var PDFResults = json["InvoicePDFResponse_InvoicePDF"];
var pdf = (string)PDFResults[0]["PDFString"];
byte[] pdfAsBytes = Convert.FromBase64String(pdf);
var externalStorageState = Android.OS.Environment.ExternalStorageState;
String path = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath + "/AppName";
Console.WriteLine("pad: " + path);
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
String file_path = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath + "/AppName";
Java.IO.File dir = new Java.IO.File(file_path);
if (!dir.Exists())
{
var b = dir.Mkdir();
}
try
{
String noMediaPath = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath + "/AppName/.nomedia";
if (!File.Exists(noMediaPath))
{
File.CreateText(noMediaPath);
}
}
catch (Exception ex)
{
Xamarin.Insights.Report(ex);
Console.WriteLine(ex);
}
var externalPath = Android.App.Application.Context.GetExternalFilesDir("AppName").AbsolutePath + "/" + "invoice.pdf";
File.WriteAllBytes(externalPath, pdfAsBytes);
//open pdf file on device
OpenFile(externalPath);
ui.HideProgressDialog();
}
In my AndroidManifest I have:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
<protected-broadcast android:name="android.intent.action.MEDIA_MOUNTED" />
<application android:allowBackup="true" android:label="AppName" android:icon="#mipmap/logoIconWhite" android:requestLegacyExternalStorage="true">
<provider android:name="androidx.core.content.FileProvider"
Please if anyone can help me out.. Xamarin native is old, it sucks, but I need to get an update trough without this headdace inducing problem and miles-long documentation on the subject from Google for just simply downloading and opening a pdf...
EDIT:
After #Cheesebaron 's suggestion to remove MANAGE_EXTERNAL_STORAGE, it still gets refused.. see image:
Email from Google
EDIT:
Now the app was finally accepted, however, the app now crashed on Android 11 devices..

How to delete files from media content providers on android N

This code worked on previous versions of android, but no longer seems to work on N.
I want to delete a media file, given the content URI of the file. I query the content provider for the path of the file. On android N, this seems to return a filename of the following form:
/storage/1143-1403/DCIM/Camera/20171019_185604.mp4
On previous versions of Android, the path would been a direct path to the SD Card. (And the real file can actually be found in the /sdcard/DCIM/Camera directory).
The problem: when I call new File(path).delete(), the delete fails. It succeeds in previous versions of Android.
Manifest permissions are:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
I have requested the following permissions, and they have been granted:
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
...
Manifest.permission.MODIFY_AUDIO_SETTINGS,
There is no Manifest.permission flag for WRITE_INTERNAL_STORAGE.
I'm guessing "/storage/1143-1403/DCIM/Camera" is some kind of fused file system.
Calling file = file.getAbsoluteFile().getCanonicalFile(); does not change the path or otherwise improve the situtation.

android APN How to read and write it?

i work on a app (> 4.4) and my boss would like to save the configuration of the APN into the SQLite (our database).
As this, if the APN is lost for a reason we can retrieve easily these information and configure it ..
well, i've try some code but actually NOTHING work ...
I have this error message
Java.Lang.SecurityException: No permission to write APN settings: Neither user 10081 nor current process has android.permission.WRITE_APN_SETTINGS.
Of course, i have added to the manifest the correct RIGTH as this
<uses-permission android:name="android.permission.READ_APN_SETTINGS"></uses-permission>
<uses-permission android:name="android.permission.WRITE_APN_SETTINGS"></uses-permission>
<uses-feature android:name="android.hardware.telephony" android:required="false" />
And here is it my code, it's with xamarin android but if you have some code with android , no matter i can find the translatation ..
Android.Net.Uri APN_TABLE_URI = Android.Net.Uri.Parse("content://telephony/carriers");
//path to preffered APNs
Android.Net.Uri PREFERRED_APN_URI = Android.Net.Uri.Parse("content://telephony/carriers/preferapn");
//
Android.Database.ICursor cursor = ctx.ContentResolver.Query(PREFERRED_APN_URI, null, null, null, null);
Thanks guys for all your time you spend here for to share your knowledge
try to add these two permissions:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Can't Read Files in Sdcard in emulator

I have some problems in my App.
I just wanna read file in sdcard, so I put the file in /storage/sdcard/abcd (the folder I made by adb) in emulator.
File name is "1.14P", and I verify it is in that path. Its permission is 770.
But my problem is, I can't access sdcard by Application.
sampleFile = new File (Environment.getExternalStorageDirectory(), "abcd/1.14P");
sampleFile.exists() //return false
sampleFile2 = new File (Environment.getExternalStorageDirectory(), "tttt");
sampleFile2.mkdir() //return false
Sdcard is mounted well, I thought.
String state = Environment.getExternalStorageState(); //return "mounted"
I give the permission but I can't access to sdcard. Here is my manifest.xml. (part)
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.hu.test004" >
<uses-permission android:name="ANDROID.PERMISSION.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="ANDROID.PERMISSION.READ_EXTERNAL_STORAGE"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
...(Activities)
I can't understand why it happens. Please give me some favor. Thanks.
SOLVED::I've got it!
The problem is, I declared permissions in capital letter, so App doesn't grant permissions.
I change
<uses-permission android:name="ANDROID.PERMISSION.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="ANDROID.PERMISSION.READ_EXTERNAL_STORAGE"/>
to
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
and permission granted.
Thank you for your favor all.
I think the "," is part of the problem. The other is the "exists()" is for directories, not files.
See here:
new File(path) always actually creates a file on android?
contrary to the docs:
http://developer.android.com/reference/java/io/File.html
you may want to use isFile() instead.
Could you try adding "/" in front of your names??
e.g. "/abcd/1.14P"

Categories

Resources