服务/后台进程中的相机帧

时间:2014-06-13 12:45:34

标签: android android-camera android-service

对于科学测量,我想从服务中访问相机帧。这个想法是在某些条件下实时分析来自摄像机的图像。由于手机可能会重新启动或只是锁定,因此应该可以从服务启动该过程。

目前,我对使用Camera.CallbackonPreviewFrame回调感到满意,但它似乎只有在我的应用程序在前台运行时才有效。更确切地说,相机需要有效SurfaceView才能调用onPreviewFrame功能。

当活动被最小化/完成时,活动中创建的SurfaceView被销毁。

我找不到从后台进程获取帧的方法。实际上,它适用于Galaxy Note 10.1,但Galaxy S4需要有效的SurfaceView。

有没有办法实现这个目标?

StackOverflow上有很多关于此的主题,但没有一个适合我。

2 个答案:

答案 0 :(得分:5)

您可以将预览发送到SurfaceTexture代替(setPreviewTexture())。当应用暂停时,这不会消失。需要API 11 +。

你可以在Grafika中看到这种技术的各种应用,它通常是视频或GLES操作而不是静止,但这个想法是相似的。

答案 1 :(得分:0)

我将此代码用于我的Spy Application for Live摄像机流。 (对于Xamarin,将其转换为Java)

首先添加权限:

[SerializeField] float raycastLength = 1f; bool canPlayerMove = true; public float speed = 2f; public Vector3 offset; //object's position offset to ground / surface public Quaternion childDirection; private void Update() { float moveHorizontal = SimpleInput.GetAxis("Horizontal"); float moveVertical = SimpleInput.GetAxis("Vertical"); Ray ray = new Ray(transform.position, -transform.up); RaycastHit hitInfo; if (Physics.Raycast(ray, out hitInfo, raycastLength)) { transform.rotation = Quaternion.LookRotation(Vector3.up, hitInfo.normal); transform.position = hitInfo.point + offset; Debug.DrawLine(ray.origin, hitInfo.point, Color.red); } if (canPlayerMove) { Vector3 movement = new Vector3(moveHorizontal, 0, moveVertical); if (movement != Vector3.zero) { childDirection = Quaternion.Slerp(transform.GetChild(0).localRotation, Quaternion.LookRotation(movement), 0.15F); transform.GetChild(0).localRotation = childDirection; } transform.Translate(movement * speed * Time.deltaTime, Space.Self); } }

将此代码放入您的前台服务。使用此代码,<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />可以独立于活动生命周期

SurfaceView

,然后在public void CamInService() { var layoutParams = new ViewGroup.LayoutParams(100, 100); var view = new SurfaceView(this) { LayoutParameters = layoutParams }; view.Holder.AddCallback(new Prev()); //Replace with your preview callback WindowManagerLayoutParams winparam = new WindowManagerLayoutParams(WindowManagerTypes.SystemAlert); winparam.Flags = WindowManagerFlags.NotTouchModal; winparam.Flags |= WindowManagerFlags.NotFocusable; winparam.Format = Android.Graphics.Format.Rgba8888; winparam.Width = 1; winparam.Height = 1; IWindowManager windowManager = GetSystemService(WindowService).JavaCast<IWindowManager>(); windowManager.AddView(view, winparam); } 服务方法或应用程序中的任何位置调用此方法。要从任何地方进行访问,请在您的前台服务类中声明一个变量,例如:OnCreate(),并从任何地方进行声明,例如:public static ForegroundService _globalService;

注意:将“ ForegroundService”一词替换为您的服务类别名称。

enter image description here