Android - Camera App passed null surface
You should use SurfaceTexture
and setPreviewTexture()
instead of SurfaceHolder
:
SurfaceTexture surfaceTexture = new SurfaceTexture(0);
cam.setPreviewTexture(surfaceTexture);
The error Camera : app passed NULL surface
has been thrown in setPreviewDisplay()
is because there was no surface created.
If you still want to use SurfaceHolder
, you should implement SurfaceHolder.Callback
first and setPreviewDisplay()
in surfaceCreated()
method to make sure a surface was created before you setPreviewDisplay()
.
Note that the surface will not be created until you add it to the View hierarchy.
EDIT
Come back to your error when you setPreviewTexture()
, because you used cam.unlock();
, your camera is temporarily released for another process to use (read more about unlock()
method here). That's why you got error java.io.IOException: setPreviewTexture failed
when you call setPreviewTexture()
.
The solution is just remove line cam.unlock();
in your code.
Biratus
Updated on June 04, 2022Comments
-
Biratus almost 2 years
I have tried every possible solutions given on stackoverflow and still haven't reach what I want. I want to take a picture with the Camera API with a service. The picture should be taken when user light the screen, but the screen is still lock. I saw different post about dummy surface etc... but none of them worked, of course I must have made misatke in my code as I am new with the camera API. My application proceed as so : I schedule an AlarmManager to start a service :
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(); } }
And in
takePicture()
I simply save the image, this method works as I tested it in an activity. Logs show the errorCamera : app passed NULL surface
,error : setPreviewTextureFailed
. I put a log to see ifmHolder
is null but it's not.
Why doessetPreviewDisplay()
throw an error ?