对于科学测量,我想从服务中访问相机帧。这个想法是在某些条件下实时分析来自摄像机的图像。由于手机可能会重新启动或只是锁定,因此应该可以从服务启动该过程。
目前,我对使用Camera.Callback
和onPreviewFrame
回调感到满意,但它似乎只有在我的应用程序在前台运行时才有效。更确切地说,相机需要有效SurfaceView
才能调用onPreviewFrame
功能。
SurfaceView
被销毁。
我找不到从后台进程获取帧的方法。实际上,它适用于Galaxy Note 10.1
,但Galaxy S4
需要有效的SurfaceView。
有没有办法实现这个目标?
StackOverflow上有很多关于此的主题,但没有一个适合我。
答案 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”一词替换为您的服务类别名称。