直接在应用程序中实现相机

Posted

技术标签:

【中文标题】直接在应用程序中实现相机【英文标题】:Implementing a camera directly in the application 【发布时间】:2019-02-23 11:01:38 【问题描述】:

我功能,因为我不想使用 Intent 打开默认相机应用程序。我已经按照here提供的代码:

拍摄照片后应用立即崩溃,并显示以下错误消息:

Java.Lang.RuntimeException: 连接相机服务失败

这是我的设置方式。我已经省略了不必要的代码。

namespace camera_test
    
        [Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true, Icon = "@drawable/icon")]
        public class MainActivity : android.Support.V7.App.AppCompatActivity, Android.Hardware.Camera.IPictureCallback, Android.Hardware.Camera.IPreviewCallback,
            Android.Hardware.Camera.IShutterCallback, ISurfaceHolderCallback
        
    static Android.Hardware.Camera camera = null;
    Button btnStart;
    Button btnEnd;

    protected override void OnCreate(Bundle savedInstanceState)
     
        base.OnCreate(savedInstanceState);

        // Set our view from the "main" layout resource

        SetContentView(Resource.Layout.activity_main);

        SurfaceView surface = (SurfaceView)FindViewById(Resource.Id.surface);
        var holder = surface.Holder;
        holder.AddCallback(this);
        holder.SetType(Android.Views.SurfaceType.PushBuffers);

        btnStart = FindViewById<Button>(Resource.Id.buttonStart);
        btnEnd = FindViewById<Button>(Resource.Id.buttonEnd);

        btnStart.Click += BtnStart_Click;
        btnEnd.Click += BtnEnd_Click;

        StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder(); StrictMode.SetVmPolicy(builder.Build());

    


    private void BtnStart_Click(object sender, EventArgs e)
    
        camera.StartPreview();



    private void BtnEnd_Click(object sender, EventArgs e)
    

        Android.Hardware.Camera.Parameters p = camera.GetParameters();
        p.PictureFormat = Android.Graphics.ImageFormatType.Jpeg;
        camera.SetParameters(p);
        camera.TakePicture(this, this, this);
        StartActivity(typeof(MainActivity));

    
    void Android.Hardware.Camera.IPictureCallback.OnPictureTaken(byte[] data, Android.Hardware.Camera camera)
    
        Java.IO.FileOutputStream outStream = null;
        Java.IO.File dataDir = Android.OS.Environment.ExternalStorageDirectory;
        DateTime DT = DateTime.Now;
        String DateTimeStamp = DT.Year.ToString("D4") + "-" + DT.Month.ToString("D2") + "-" + DT.Day.ToString("D2") + "-" + DT.Hour.ToString("D2") + DT.Minute.ToString("D2") + DT.Second.ToString("D2");
        String PictureFilename = "Photo-" + DateTimeStamp + ".jpg";

        if (data != null)
        
            try
            
                outStream = new Java.IO.FileOutputStream(dataDir + "/" + PictureFilename);
                outStream.Write(data);
                outStream.Close();
            
            catch (FileNotFoundException e)
            
                System.Console.Out.WriteLine(e.Message);
            
            catch (IOException ie)
            
                System.Console.Out.WriteLine(ie.Message);
            
        
    

    void Android.Hardware.Camera.IPreviewCallback.OnPreviewFrame(byte[] b, Android.Hardware.Camera c)
    

    

    void Android.Hardware.Camera.IShutterCallback.OnShutter()
    

    


    public void SurfaceCreated(ISurfaceHolder holder)
    


        try
        
            camera = Android.Hardware.Camera.Open();
            Android.Hardware.Camera.Parameters p = camera.GetParameters();
            p.PictureFormat = Android.Graphics.ImageFormatType.Jpeg;
            camera.SetParameters(p);
            camera.SetPreviewCallback(this);
            camera.Lock();
            camera.SetPreviewDisplay(holder);
            // camera.StartPreview();
        
        catch (IOException e)
        
        
    

    public void SurfaceDestroyed(ISurfaceHolder holder)
    

        camera.Unlock();
        camera.StopPreview();
        camera.SetPreviewCallback(null);
        camera.Release();
        camera = null;
    

    public void SurfaceChanged(ISurfaceHolder holder, Android.Graphics.Format f, int i, int j)
    
    

我猜这与相机打开和关闭的方式有关,但我不知道如何解决这个问题。请注意,开始按钮正确启动相机查看器。只有当点击结束按钮时应用程序才会崩溃。任何帮助或建议将不胜感激。另外,我知道 相机 已经贬值了。谢谢。

更新:

错误发生在:

设备改变方向

或者当我拨打此电话时:StartActivity(typeof(MainActivity));

即,当活动重新启动时会发生错误(我认为如果方向发生变化,那么它也会重新启动活动)。我不知道如何重新开始我的活动,因为我需要这样做。有趣的是,如果我切换到其他活动然后切换回具有相机功能的主要活动,则不会发生错误。我很不解。

【问题讨论】:

您是否在清单中声明了权限?此外,如果您的操作系统版本是 6.0 或更高版本,那么您可能必须实现运行时权限模型。 是的,我已经声明了权限。如果是权限错误,我将无法查看相机(它在我的表面视图中显示正确)。我已验证我可以访问外部存储(读取和写入)和相机。 我说的是读写权限忘了提了。检查这些权限是否在设置页面的应用权限列表中打开或关闭。 是的,我绝对有读写权限。 请查看this SO post - 这是重复的吗? 【参考方案1】:

您使用已弃用的相机 api 是否有原因?

你应该使用camera2: https://developer.android.com/reference/android/hardware/camera2/package-summary

Xamarin 还为此提供了一个基本示例: https://developer.xamarin.com/samples/monodroid/android5.0/Camera2Basic/

【讨论】:

以上是关于直接在应用程序中实现相机的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 XCode 在 iOS 应用中实现相机功能

如何在本机摄像机中实现HDR设置?

如何在自定义相机中实现“捏放大”

Unity中实现垂直角度的相机在不同分辨率下的适配

Unity中实现高级相机操作——Cinemachine插件

Unity中实现高级相机操作——Cinemachine插件