I’m updating a working app that targeted API 9 (Pie) to API 33 (Tiramisu) and the camera always returns Result.Cancelled
to the OnActivityResult
code. I’m using Visual Studio 2022 Version 17.3.6 on a Windows 11 pro machine. This is my camera code:
camerabutton.Click += (sender, evt) =>
{
var cameraispresent = checkCameraHardware(this);
if (cameraispresent)
{
try
{
CreateDirectoryForPictures();
MySubjectInfo.Name = MySubjectInfo.Name.Replace(",", "");
MySubjectInfo.Name = MySubjectInfo.Name.Replace(" ", "");
MySubjectInfo.Name = MySubjectInfo.Name.Replace(".", "");
var filename = MySubjectInfo.Name + ".jpg";
Intent intent = new Intent(MediaStore.ActionImageCapture);
App._file = new File(App._dir, String.Format(filename, Guid.NewGuid()));
intent.PutExtra(MediaStore.ExtraOutput, Uri.FromFile(App._file));
StartActivityForResult(intent, TakePictureRequestCode);
}
catch (Exception e)
{
var result = e.Message;
};
}
};
The create directory code, this code was also updated to reflect changes in API 33, however I can’t find the folder on my test device via file explorer where the photos should be stored yet App._dir.Exists()
returns true saying it’s there:
private void CreateDirectoryForPictures()
{
int version = (int)Android.OS.Build.VERSION.SdkInt;
var root = "";
if (Android.OS.Environment.IsExternalStorageEmulated)
{
root = Android.OS.Environment.ExternalStorageDirectory.ToString();
}
else
{
root = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyPictures);
}
if (version >= Convert.ToInt32(BuildVersionCodes.Q))
{
App._dir = new File(root + "/PhotoManager");
}
else
{
App._dir = new File(
Environment.GetExternalStoragePublicDirectory(
Environment.DirectoryPictures), "PhotoManager");
}
if (!App._dir.Exists())
{
App._dir.Mkdirs();
}
}
This is the app class where I store the data:
public static class App
{
public static File _file;
public static File _dir;
public static Bitmap bitmap;
}
This is the OnActivityResult1
code, I left my API 9 code in there commented out so you can see where I was and where I’m going. With API 9 I needed to resize the picture to scale it down to 160 X 100 as these photos are used for ID cards, I commented that code out until I can figure out why the camera intent is returning null:
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
if (requestCode == TakePictureRequestCode && resultCode == Result.Ok)
{
//Intent mediaScanIntent = new Intent(Intent.ActionMediaScannerScanFile);
//Uri contentUri = Uri.FromFile(App._file);
//mediaScanIntent.SetData(contentUri);
//SendBroadcast(mediaScanIntent);
Bitmap photo = (Bitmap)data.GetByteArrayExtra("data");
App.bitmap = photo;
//int height = 160; //Resources.DisplayMetrics.HeightPixels;
//int width = 100; //MyImageView.Height;
//App.bitmap = App._file.Path.LoadAndResizeBitmap(width, height);
if (App.bitmap != null)
{
MyImageView.SetImageBitmap(App.bitmap);
Bitmap bitmap = App.bitmap;
var filePath = App._file.AbsolutePath;
var stream = new System.IO.FileStream(filePath, System.IO.FileMode.Create);
bitmap.Compress(Bitmap.CompressFormat.Jpeg, 100, stream);
stream.Close();
bitmap = null;
App.bitmap = null;
PictureTaken = true;
}
// Dispose of the Java side bitmap.
GC.Collect();
}
}
So what am I doing wrong?
2
Answers
You cannot use Uri.FromFile anymore since Android 7.
Use FileProvider to serve a writable uri for the camera app.
Example: EnsureBluetoothEnabled called from a permission request
Setup
Handler:
ActivityResultCallback class