Android - 相机应用程序通过了空表面
Android - Camera App passed null surface
我已经尝试了 Whosebug 上给出的所有可能的解决方案,但仍然没有达到我想要的效果。我想用带有服务的相机 API 拍照。当用户点亮屏幕时应该拍照,但屏幕仍处于锁定状态。我看到了关于虚拟表面等的不同 post...但是其中 none 有效,当然我一定是在我的代码中犯了错误,因为我是相机的新手 API。我的应用程序是这样进行的:我安排了一个 AlarmManager 来启动服务:
public int onStartCommand(Intent intent,int flags,int startId) {
Log.i("service","start");
Calendar finServ=Calendar.getInstance();
String all=intent.getStringExtra("all");
nomevt=all.split(Pattern.quote("**"))[3];
Scanner sc;
String str="";
try {
sc = new Scanner(new File(getFilesDir(),"Event.evt"));
while(sc.hasNext()) {
str=sc.next();
if(all.equals(str)) break;
}
sc.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
if(!all.equals(str)) stopSelf();
else {
finServ.setTimeInMillis(toMillis(str.split(Pattern.quote("**"))[1]));
Calendar now=Calendar.getInstance();
now.setTime(new Date());
while(finServ.after(now)) {
PowerManager pm=(PowerManager)getSystemService(Context.POWER_SERVICE);
if(pm.isScreenOn()) {
//AsyncCapture ac=new AsyncCapture(this);
//ac.execute("nomevt");
photo();
Log.i("screen","on");
while(pm.isScreenOn()) {
pm=(PowerManager)getSystemService(Context.POWER_SERVICE);
}
}
now.setTime(new Date());
}
stopSelf();
}
return super.onStartCommand(intent, flags, startId);
}`
<br>The service will call `photo()` when the screen is light on. <br>
`public void photo() {
cam=Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
try {
cam.unlock();
/*WindowManager wm=(WindowManager)this.getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams params=new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
PixelFormat.TRANSLUCENT);*/
SurfaceView sv=new SurfaceView(this);
//wm.addView(sv, params);
ViewGroup.LayoutParams param=new ViewGroup.LayoutParams(1,1);
sv.setLayoutParams(param);
sv.setZOrderOnTop(true);
SurfaceHolder mHolder=sv.getHolder();
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
Log.i("holder",(mHolder==null)+"");
cam.setPreviewDisplay(mHolder);
cam.startPreview();
cam.takePicture(null,null,this);
//wm.removeView(sv);
Log.i("take","picture");
} catch (IOException e) {
Log.e("error",e.getMessage());
e.printStackTrace();
}catch(RuntimeException re) {
Log.e("error",re.getMessage()+"");
re.printStackTrace();
}finally{
cam.stopPreview();
cam.release();
}
}
而在 takePicture()
中,我只是简单地保存了图像,此方法在我在 activity 中测试时有效。
日志显示错误 Camera : app passed NULL surface
、error : setPreviewTextureFailed
。我放了一个日志来查看 mHolder
是否为 null 但它不是。
为什么 setPreviewDisplay()
会抛出错误?
您应该使用 SurfaceTexture
和 setPreviewTexture()
而不是 SurfaceHolder
:
SurfaceTexture surfaceTexture = new SurfaceTexture(0);
cam.setPreviewTexture(surfaceTexture);
在 setPreviewDisplay()
中抛出错误 Camera : app passed NULL surface
是因为没有创建表面。
如果您仍然想使用 SurfaceHolder
,您应该先实现 SurfaceHolder.Callback
,然后在 surfaceCreated()
方法中实现 setPreviewDisplay()
,以确保在您 setPreviewDisplay()
.
请注意,在将表面添加到视图层次结构之前,不会创建该表面。
编辑
回到你 setPreviewTexture()
时的错误,因为你使用了 cam.unlock();
,你的相机 暂时释放给另一个进程使用 (阅读更多关于 unlock()
方法 here)。这就是为什么当您调用 setPreviewTexture()
.
时出现错误 java.io.IOException: setPreviewTexture failed
解决方法是删除代码中的 cam.unlock();
行。
我已经尝试了 Whosebug 上给出的所有可能的解决方案,但仍然没有达到我想要的效果。我想用带有服务的相机 API 拍照。当用户点亮屏幕时应该拍照,但屏幕仍处于锁定状态。我看到了关于虚拟表面等的不同 post...但是其中 none 有效,当然我一定是在我的代码中犯了错误,因为我是相机的新手 API。我的应用程序是这样进行的:我安排了一个 AlarmManager 来启动服务:
public int onStartCommand(Intent intent,int flags,int startId) {
Log.i("service","start");
Calendar finServ=Calendar.getInstance();
String all=intent.getStringExtra("all");
nomevt=all.split(Pattern.quote("**"))[3];
Scanner sc;
String str="";
try {
sc = new Scanner(new File(getFilesDir(),"Event.evt"));
while(sc.hasNext()) {
str=sc.next();
if(all.equals(str)) break;
}
sc.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
if(!all.equals(str)) stopSelf();
else {
finServ.setTimeInMillis(toMillis(str.split(Pattern.quote("**"))[1]));
Calendar now=Calendar.getInstance();
now.setTime(new Date());
while(finServ.after(now)) {
PowerManager pm=(PowerManager)getSystemService(Context.POWER_SERVICE);
if(pm.isScreenOn()) {
//AsyncCapture ac=new AsyncCapture(this);
//ac.execute("nomevt");
photo();
Log.i("screen","on");
while(pm.isScreenOn()) {
pm=(PowerManager)getSystemService(Context.POWER_SERVICE);
}
}
now.setTime(new Date());
}
stopSelf();
}
return super.onStartCommand(intent, flags, startId);
}`
<br>The service will call `photo()` when the screen is light on. <br>
`public void photo() {
cam=Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
try {
cam.unlock();
/*WindowManager wm=(WindowManager)this.getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams params=new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
PixelFormat.TRANSLUCENT);*/
SurfaceView sv=new SurfaceView(this);
//wm.addView(sv, params);
ViewGroup.LayoutParams param=new ViewGroup.LayoutParams(1,1);
sv.setLayoutParams(param);
sv.setZOrderOnTop(true);
SurfaceHolder mHolder=sv.getHolder();
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
Log.i("holder",(mHolder==null)+"");
cam.setPreviewDisplay(mHolder);
cam.startPreview();
cam.takePicture(null,null,this);
//wm.removeView(sv);
Log.i("take","picture");
} catch (IOException e) {
Log.e("error",e.getMessage());
e.printStackTrace();
}catch(RuntimeException re) {
Log.e("error",re.getMessage()+"");
re.printStackTrace();
}finally{
cam.stopPreview();
cam.release();
}
}
而在 takePicture()
中,我只是简单地保存了图像,此方法在我在 activity 中测试时有效。
日志显示错误 Camera : app passed NULL surface
、error : setPreviewTextureFailed
。我放了一个日志来查看 mHolder
是否为 null 但它不是。
为什么 setPreviewDisplay()
会抛出错误?
您应该使用 SurfaceTexture
和 setPreviewTexture()
而不是 SurfaceHolder
:
SurfaceTexture surfaceTexture = new SurfaceTexture(0);
cam.setPreviewTexture(surfaceTexture);
在 setPreviewDisplay()
中抛出错误 Camera : app passed NULL surface
是因为没有创建表面。
如果您仍然想使用 SurfaceHolder
,您应该先实现 SurfaceHolder.Callback
,然后在 surfaceCreated()
方法中实现 setPreviewDisplay()
,以确保在您 setPreviewDisplay()
.
请注意,在将表面添加到视图层次结构之前,不会创建该表面。
编辑
回到你 setPreviewTexture()
时的错误,因为你使用了 cam.unlock();
,你的相机 暂时释放给另一个进程使用 (阅读更多关于 unlock()
方法 here)。这就是为什么当您调用 setPreviewTexture()
.
java.io.IOException: setPreviewTexture failed
解决方法是删除代码中的 cam.unlock();
行。