xamarin 类活动结果回调:Java语言对象,IActivityResultCallback结果始终为空

fhg3lkii  于 2022-12-16  发布在  Java
关注(0)|答案(1)|浏览(134)

我已经将旧的StartActivityForResult代码转换为新的RegisterForActivityResult,因为StartActivityForResult在android API 29和更高版本中贬值了。我的新代码工作得很完美,除了class ActivityResultCallback中的result总是空。我需要能够知道用户何时取消拍照,当他们点击后退按钮时,否则,应用程序会崩溃(如果之前的图片不存在),或者之前拍摄的图片会被再次处理。我的代码(仅显示相关代码):

public class Photo : AppCompatActivity
{
    public ImageView MyImageView;
    public ImageButton camerabutton;
    public bool PictureTaken = false;
    private CurrentSubjectInfo MySubjectInfo;
    private ActivityResultCallback _activityResultCallback;
    private ActivityResultLauncher _activityResultLauncher;
    private Uri uri;

    protected override void OnCreate(Bundle bundle)
    {
        try 
        {
            _activityResultCallback = new ActivityResultCallback();
            _activityResultCallback.OnActivityResultCalled += ActivityResultCallback_ActivityResultCalled;
            _activityResultLauncher = RegisterForActivityResult(new ActivityResultContracts.TakePicture(), _activityResultCallback);
            RequestedOrientation = Android.Content.PM.ScreenOrientation.Portrait;
            base.OnCreate(bundle);
            SetContentView(Resource.Layout.Photo);
            PictureTaken = false;
            MySubjectInfo = new CurrentSubjectInfo("", "", "", "", "");
            // retrieve subject information from previous activity
            MySubjectInfo = Mybundle.GetParcelable("MySubjectInfo", Java.Lang.Class.FromType(typeof(CurrentSubjectInfo))) as CurrentSubjectInfo;
            ImageButton camerabutton = FindViewById<ImageButton>(Resource.Id.button1);
            MyImageView = FindViewById<ImageView>(Resource.Id.imageView1);

            camerabutton.Click += (sender, evt) =>
            {

                var cameraispresent = CheckCameraHardware();
                if (cameraispresent)
                {
                    try
                    {
                        // get directory where pictures are stored
                        App._dir = Environment.GetExternalStoragePublicDirectory(Environment.DirectoryPictures);
                        // build file name
                        MySubjectInfo.Name = MySubjectInfo.Name.Replace(",", "");
                        MySubjectInfo.Name = MySubjectInfo.Name.Replace(" ", "");
                        MySubjectInfo.Name = MySubjectInfo.Name.Replace(".", "");
                        var filename = MySubjectInfo.Name + ".jpg";
                        App._file = new File(App._dir, String.Format(filename, Guid.NewGuid()));
                        uri = FileProvider.GetUriForFile(this, this.ApplicationContext.PackageName + ".provider",App._file);
                        // launch camera activity
                        _activityResultLauncher.Launch(uri);

                    }
                    catch (Exception e)
                    {
                        // trap error and log it
                    };

                }
            };
        }
    }
    Boolean CheckCameraHardware()
    {
        Android.Content.PM.PackageManager pm = PackageManager;
        if (pm.HasSystemFeature(Android.Content.PM.PackageManager.FeatureCamera))
        {
            // this device has a camera
            return true;
        }
        else
        {
            // no camera on this device
            return false;
        }
    }

    private void ActivityResultCallback_ActivityResultCalled(object sender, ActivityResult result)
    {
        // result is always null, so I don't check it
        try
        {
            // Because the resulting bitmap is rotated and too large, I set original orientation and resize
            // suffice it to say it works perfectly so I won't post the code here
            int height = 260;
            int width = 200;
            App.bitmap = App._file.Path.LoadAndResizeBitmap(width, height);

            Bitmap bitmap = App.bitmap;
            var filePath = App._file.AbsolutePath;
            // save the resized bitmap, overwriting original file
            var stream = new System.IO.FileStream(filePath, System.IO.FileMode.Create);
            bitmap.Compress(Bitmap.CompressFormat.Jpeg, 100, stream);
            stream.Close();
            // set the imageview to the resulting bitmap
            MyImageView.SetImageBitmap (App.bitmap);
            // cleanup
            bitmap = null;
            App.bitmap = null;
            PictureTaken = true;
        }
        catch (Exception ex)
        {
            PictureTaken = false;
            // trap and log error
        }
    }
}

这是ActivityResultCallback类:

public class ActivityResultCallback : Java.Lang.Object, IActivityResultCallback
{
    public EventHandler<ActivityResult> OnActivityResultCalled;

    public void OnActivityResult(Java.Lang.Object result)
    {
        ActivityResult activityResult = result as ActivityResult;
        OnActivityResultCalled?.Invoke(this, activityResult);
    }
}

如上所述,除了Java.Lang.Object result始终为空之外,所有这些代码都完美地执行,没有任何错误。我需要知道用户何时取消摄像头活动,我会假设Java.Lang.Object result将指示cancelled,但我什么也得不到。我错过了什么?

uplii1fm

uplii1fm1#

好了,经过一番尝试之后,我注意到ActivityResultCallback类中的参数Java.Lang.Object result可能是true,也可能是false,这取决于用户使用相机的方式,因此我将该类更改为:

public class ActivityResultCallback : Java.Lang.Object, IActivityResultCallback
{
    public EventHandler<ActivityResult> OnActivityResultCalled;
    
    public void OnActivityResult(Java.Lang.Object result)
    {

        ActivityResult activityResult;
        if ((bool)result)
        {
            activityResult = new ActivityResult((int)Result.Ok, null);
        } else
        {
            activityResult = new ActivityResult((int)Result.Canceled, null);
        }
        OnActivityResultCalled?.Invoke(this, activityResult);
    }
}

ActivityResultCallback_ActivityResultCalled函数中,我将其修改为:

private void ActivityResultCallback_ActivityResultCalled(object sender, ActivityResult result)
    {

        try
        {
            if (result.ResultCode == (int)Result.Ok)
            {
                int height = 260;
                int width = 200;
                App.bitmap = App._file.Path.LoadAndResizeBitmap(width, height);

                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();

                MyImageView.SetImageBitmap(App.bitmap);

                bitmap = null;
                App.bitmap = null;
                PictureTaken = true;
            }
        }
        catch (Exception ex)
        {
            // trap and log error
        }
    }

activityResult显然至少有两个参数,result和data。我已经有了data所需的参数,所以我将其设置为null,并根据result为true还是false将Result.OkResult.Cancelled转换为int。我仍然不完全理解如何使用新的ActivityForResult API,但这对我很有效,我正在使用它。

相关问题