重复使用 Xamarin.Essentials.MediaPicker.CapturePhotoAsync 会在 Android 11 上重新启动我的应用程序

问题描述 投票:0回答:5

我需要拍摄更多照片,但应用程序会在 Android 11 设备上重新启动。 Android 10 或更低版本即可。 它表现得神秘莫测。有时它发生在第三次捕获之后,有时可能发生在第七次捕获之后。

问题模拟(第二次捕获后重启):

  1. 点击按钮拍照
  2. 拍照
  3. 点击确定
  4. 应用程序返回到带有按钮的屏幕
  5. 步骤1-3
  6. 应用程序重新启动并显示主屏幕

如果我在

var photo = await MediaPicker.CapturePhotoAsync();
上放置断点 并进入下一步,什么也没有完成并且应用程序崩溃了。

这也发生在App-Essentials示例应用程序中。

编辑: 我的代码:

var file = await MediaPicker.CapturePhotoAsync();

while (LS.IsIntermediateActivity())

{ await Task.Delay(10); }

正常行为:拍摄照片,单击“确定”,下一步 - while (LS.IsIntermediateActivity()),然后在 MainActivity OnRestart 和 OnResume 中。 (LS是DependencyService)

不正确的行为:拍摄照片,单击“确定”,没有下一步 - 应用程序崩溃或重新启动并显示主页。没有例外,没有警告。

android xamarin xamarin.essentials
5个回答
2
投票

我记得我的一位同事遇到了一个非常相似的问题,媒体选择器上的这篇说明实际上解决了他们的问题

所有方法都必须在 UI 线程上调用,因为权限检查和请求由 Xamarin.Essentials 自动处理。

这很奇怪,因为他们自己的示例没有这样做:/

无论如何,请尝试一下,看看这是否可以解决您的问题:

var fileResult= await Device.InvokeOnMainThreadAsync(async () => await MediaPicker.CapturePhotoAsync());

祝你好运

如有疑问,请随时回复。


2
投票

我调查了这个问题。 基本上,当从您的应用程序内使用媒体选择器打开相机时,您的应用程序会被 Android 置于后台,因为相机应用程序现在正在使用。进行一些 RAM 优化,操作系统可能会重新启动您的应用程序。在测试中,我们在 3Gb RAM 的设备上没有出现任何问题,但在 2Gb RAM 的设备上遇到了这个问题。很可能是因为内存不足。

解决方案是在离开应用程序时保存应用程序状态,并在拍照回来后重新使用该状态,以防应用程序重新启动。我们还没有找到简单的解决方案,非常欢迎提出想法......


0
投票

我尝试了另一种解决方案:

public async Task<string> TakePhotoAsync()
    {
        waitForResult = new AsyncAutoResetEvent();
        var context = Android.App.Application.Context;
        var activity = Xamarin.Essentials.Platform.CurrentActivity as MainActivity;
        using (var intent = new Intent(MediaStore.ActionImageCapture))
        {
            string timestamp = System.DateTime.Now.ToString("yyyyMMdd_HHmmss");
            var file = new File(GetPictureDirPath(), "EMAphoto_" + timestamp + ".jpg");
            var uri = FileProvider.GetUriForFile(context, context.ApplicationContext.PackageName + ".fileprovider", file);
            intent.PutExtra(MediaStore.ExtraOutput, uri);
            activity.StartActivityForResult(intent, CAMERA_REQUEST_CODE);
            await waitForResult.WaitAsync().ConfigureAwait(true);
            return file.Path;
        }

    }

而且它也崩溃了...... 愚蠢的Android 11还是我?


0
投票

更新至Android 12,问题已解决...


0
投票

我最近遇到了这个问题,在网上找不到解决方案,所以我在这里提供我的解决方案,希望它能帮助别人。

当前的问题是,当调用 CapturePhotoAsync 时,相机应用程序将打开,并且您的应用程序将置于后台。这使得它容易受到垃圾收集的影响,有时会导致应用程序在下次启动时重新启动。

我的解决方案: 为了在拍照时保持我们的应用程序处于活动状态,我们将在调用 CapturePhotoAsync 之前首先启动前台进程。

1.) 在 Android 项目中创建一个服务,如下所示:

[Service]
public class AndroidPhotoService : Service

2.) 在服务中,重写 OnStartCommand 并创建通知

// Create a notification and set it as a foreground service
var notification = new Notification.Builder(this)
    .SetChannelId("yourChannelName")
    .SetContentTitle("Whatever")
    .SetContentText("Whatever")
    .SetSmallIcon(Resource.Drawable.SymDefAppIcon)
    .Build();

StartForeground(1, notification);

return StartCommandResult.Sticky;

3.) 确保覆盖 OnDestroy

public override void OnDestroy()
{
    StopForeground(true);
    base.OnDestroy();
}

4.) 在您的 MainActivity 中,设置消息订阅来捕获照片并将结果发送回您的 ViewModel

MessagingCenter.Subscribe<AddAttachmentViewModel>(this, "StartPhotoService", async (sender) =>
{
    var intent = new Intent(this, typeof(AndroidPhotoService));
    StartService(intent);
    var photo = await MediaPicker.CapturePhotoAsync();
    MessagingCenter.Send("YourMessageID", "PhotoCaptured", photo);
}

5.) 在 ViewModel 中订阅此消息并根据需要处理照片。

© www.soinside.com 2019 - 2024. All rights reserved.