I am trying to create a surface view for a camera so it renders on the surface whenever is in the view of the camera. At the moment all I can see on my camera view is a black screen view. I have tried to look on Google and here but so far I haven't found what I am looking for. Anyone can suggest me some idea.
I have written a class that can help you.
public class Preview_can_work extends Activity {
private SurfaceView surface_view;
private Camera mCamera;
SurfaceHolder.Callback sh_ob = null;
SurfaceHolder surface_holder = null;
SurfaceHolder.Callback sh_callback = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFormat(PixelFormat.TRANSLUCENT);
surface_view = new SurfaceView(getApplicationContext());
addContentView(surface_view, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
if (surface_holder == null) {
surface_holder = surface_view.getHolder();
}
sh_callback = my_callback();
surface_holder.addCallback(sh_callback);
}
SurfaceHolder.Callback my_callback() {
SurfaceHolder.Callback ob1 = new SurfaceHolder.Callback() {
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
mCamera = Camera.open();
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException exception) {
mCamera.release();
mCamera = null;
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
mCamera.startPreview();
}
};
return ob1;
}
}
in your manifest file copy this code for camera permission
<uses-permission android:name="android.permission.CAMERA"/>
Explanation:
SurfaceView is a type of View which contains a SurfaceHolder. SurfaceHolder holds the surface on which we can display our media (generally frames).
mCamera is a Camera object which will contains the camera instance.
When you want to hold default Camera instance then you can simply call Camera.open();
Camera mCamera = Camera.open();
Now you have an open camera or you are having default camera instance. Now you need to capture frames from the camera and display it on a surface. But you cannot display it without any
surface. Here the surfaceView provides surfaceHolder and surfaceHolder provides surface to display camera frames. Now when surface will be created three callback functions will be
called.
1. public void surfaceCreated(SurfaceHolder holder)
2. public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
3. public void surfaceDestroyed(SurfaceHolder holder)
Note:- Surface will be destroyed when your application will go on pause.
surfaceCreated:
surfaceCreated is a callback function which will be called when your surface will be created. In this, you can open your camera and set other attributes.
surfaceChanged:
This will be called atleast one time when your surface will be created. After that it will be called whenever your surface will change(In device rotation). Here you can
start your preview because your surface have already created.
surfaceDestroyed:
This will be called every time when your surface will destroy. Now if you dont have surface then where you can display you camera frames so I have released camera by using
mCamera.release(). This is very important because if your activity will be on pause and any other activity tries to open camera then it will not able to open it as you have
already open camera. Camera is a shared resource so one time only one application can use it. So remember one thing whenever you open a camera then always release it.
stopPreview:
When you start preview then your camera starts capturing your frames and display it on a surface. Now if your surface have destroyed then you need to stop capturing frames
from camera so you have to call mCamera.stopPreview.
Make shure you added the permission :
<uses-permission android:name="android.permission.CAMERA"/>
Also these window properties:
getWindow().setFormat(PixelFormat.TRANSLUCENT);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
WindowManager.LayoutParams.FLAG_FULLSCREEN | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
Post some code if that doesn't work in order to help you
Related
I have a camera app that had a Camera Preview which worked. The app was developed some years ago (2012) and i decided to reuse parts of its code, but, upon testing again (on same hardware i9100, different OS 4.4 vs 3.0), my camera preview image has a problem
when i move the phone, i see the image change and it responds to light and dark patterns (therefore app is communicating with camera).
this is my code (it uses deprecated method setType):
class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private static final String TAG = "TGCamera";
SurfaceHolder mHolder;
public Camera camera;
public final String fileName = "/download/CameraGPS/zdelTempPhotoPreview.jpg";
CameraPreview(Context context) {
super(context);
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, acquire the camera and tell it where
// to draw.
camera = Camera.open();
Parameters parameter02 = camera.getParameters();
parameter02.setJpegThumbnailSize(80, 60);
parameter02.setPictureSize(640, 480);
camera.setParameters(parameter02);
try {
camera.setPreviewDisplay(holder);
camera.setDisplayOrientation(90);
Parameters parameters00 = camera.getParameters();
//parameters00.setRotation(90);
//parameters00.setFlashMode("on");
//parameters00.setJpegQuality(20);
camera.setParameters(parameters00);
camera.setPreviewCallback(new PreviewCallback() {
public void onPreviewFrame(byte[] data, Camera arg1) {
CameraPreview.this.invalidate();
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// Surface will be destroyed when we return, so stop the preview.
// Because the CameraDevice object is not a shared resource, it's very
// important to release it when the activity is paused.
camera.stopPreview();
camera = null;
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// Now that the size is known, set up the camera parameters and begin
// the preview.
//camera.getParameters().setRotation();
//camera.getParameters().setJpegQuality(20);
//camera.getParameters().setPictureSize(width, height)
Parameters parameters = camera.getParameters();
parameters.setPreviewSize(w, h);
camera.setParameters(parameters);
camera.startPreview();
}
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
Log.w(TAG,"clicked in preview");
Paint p = new Paint(Color.RED);
Log.d(TAG, "draw");
canvas.drawText("PREVIEW", canvas.getWidth() / 2,
canvas.getHeight() / 2, p);
}
Any suggestions?
You cannot set the picture size and preview size to arbitrary values. Make sure you check the lists returned by getSupportedPictureSizes() and getSupportedPreviewSizes(), respectively.
Often (I don't remember if this applies to Samsung Galaxy S2), the camera does not work correctly when the aspect ratio for picture is different from the one for preview.
Furthermore, you are not supposed to draw on the preview surface, and definitely not from onPreviewFrame() callback.
The first thing would be to add camera.setPreviewDisplay(holder) in your surfaceChanged() method too
Update:
Please debug in surfaceCreated and surfaceChanged that holder.getSurface() != null
Also you should add camera.release() in surfaceDestroyed and then clean install app (uninstall first and then fresh install the app). The camera service could be hanging since a previous run of the app.
Update 2:
I just noticed that you missed registering to callbacks from the SurfaceHolder passed by the surfaceCreated() and surfaceChanged() methods. In this case it would make sense that surfaceChanged() is never reached and that means startPreview() is never actually called..
In surfaceCreated and surfaceChanged methods, please update the code to include:
mHolder.removeCallback(this); // unregister from old SurfaceHolder
holder.addCallback(this); // register to new holder
try {
camera.setPreviewDisplay(holder);
} catch (IOException e) {
e.printStackTrace();
}
mHolder = holder;
I've used the camera native app through my app for taking picture. I've used the below code for display the camera app in portrait mode only.
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
takePictureIntent.putExtra(MediaStore.EXTRA_SCREEN_ORIENTATION,
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
startActivityForResult(takePictureIntent, actionCode);
But, it's not working with the above code.
Any suggestions will be appreciated :-)
You can't control the orientation of an external application that you launch, so there is no way to do this.
But you could create your own camera activity.
considering your mCamera as your Camera, you can create your camera activity, set à cameraPReview and set the preview in protrait mode by adding mCamera.setDisplayOrientation(90); before starting preview
here is an example for camera preview in a FrameLayout in potrait mode:
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
if(mCamera!=null){
mCamera.setPreviewDisplay(holder);
mCamera.setDisplayOrientation(90);
mCamera.startPreview();}
} catch (IOException e) {
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null) {
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
}
}
and you set the preview from your MainActivity like below :
mPreview = new CameraPreview(getApplicationContext(), camera);
preview.addView(mPreview);
I am developing a custom camera application.Given below is my Activity class.
public class MyCustomCam extends Activity {
private Camera mCamera;
private CameraPreview mPreview;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mCamera = getCameraInstance();
mPreview = new CameraPreview(this, mCamera);
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(mPreview);
}
public static Camera getCameraInstance(){
Camera c = null;
try {
c = Camera.open(); // attempt to get a Camera instance
}
catch (Exception e){
// Camera is not available (in use or does not exist)
}
return c; // returns null if camera is unavailable}
}
}
Given below is my main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<FrameLayout
android:id="#+id/camera_preview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1" />
<Button android:id="#+id/button_capture"
android:text="Capture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
/></LinearLayout>
And this is my CameraPreview class
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera; // Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.d("", "Error setting camera preview: " + e.getMessage());
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null){ // preview surface does not exist
return; } // stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
} // set preview size and make any resize, rotate or
// reformatting changes here // start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
Log.d("", "Error starting camera preview: " + e.getMessage());
}
}
}
Here
mCamera.setPreviewDisplay(holder);
code is throwing null pointer exception...i cant fix that.please tell me why it is throwing exception and how can i fix that?
Release the camera in your surfaceDestroyed function
public void surfaceDestroyed(SurfaceHolder holder) {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
and make sure you add camera permission in your manifest file.
<uses-permission android:name="android.permission.CAMERA" />
I was having the same bug.
I used this Q&A to help solve my issue. Specifically, reference the adding of the function getBestPreviewSize(...) invoked prior to params.setPreviewSize(...) being set in surfaceChanged.
Android - cam.setPreviewDisplay(holder) running into IOError
As a side note (because this was my next bug), if you start doing any more customization of the Layout (e.g. removing the title bar), any "requests" to the UI to make changes should be made prior to setContentView(...), noted in the link below.
requestFeature() must be called before adding content
Most probably your problem would be that your emulator's camera settings. Go to AVD manager, edit your emulator and set your camera , may be to emulated. restart the emulator and launch your app.
I am trying to display the camera preview with an image overlay and have a button at the bottom to take the picture. I pretty much copied the API from CameraPreview and added an addcontentview which seems to work pretty well for adding an xml file which acts as my overlay. (Except that it has to be in landscape mode so I need to figure out how to either rotate all my stuff through code or, easier for me, just make sideways images :-P)
My problem is that I just can't figure out how to get my button to work correctly.
All I want to do is use the image as the background for my next activity. Anyway, this is what I've got.
public class CameraPreview extends Activity {
private Preview mPreview;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
mPreview = new Preview(this);
setContentView(mPreview);
LayoutInflater inflater = getLayoutInflater();
getWindow().addContentView(inflater.inflate(R.layout.overlay, null), new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.FILL_PARENT));
}
}
// ----------------------------------------------------------------------
class Preview extends SurfaceView implements SurfaceHolder.Callback {
SurfaceHolder mHolder;
Camera mCamera;
Preview(Context context) {
super(context);
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
mCamera = Camera.open();
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException exception) {
mCamera.release();
mCamera = null;
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(w, h);
mCamera.setParameters(parameters);
mCamera.startPreview();
}
}
I just can't figure out where to put in my button, what to type or anything. I'm assuming its something like camera.takepicture but I can't get it to work.
Oh yea, I've spent about half the day on this one area so if you could super simplify it for me, my fried mind would appreciate it. :)
Alright, I poked around a little today with a fresh mind and decided it would be much easier to just have the user use their camera app. So I did that with a startActivityForResult and from there it was a cinch to modify my imageview with the data and I just am going to put my overlay onto the returned preview using RelativeLayout.
Thanks if you were working on this. I pulled from the question below to make mine.
How do I save data from Camera to disk using MediaStore on Android?
I am writing an Android 1.5 application which starts just after boot-up. This is a Service and should take a picture without preview. This app will log the light density in some areas whatever. I was able to take a picture but the picture was black.
After researching for a long time, I came across a bug thread about it. If you don't generate a preview, the image will be black since Android camera needs preview to setup exposure and focus. I've created a SurfaceView and the listener, but the onSurfaceCreated() event never gets fired.
I guess the reason is, the surface is not being created visually. I've also seen some examples of calling the camera statically with MediaStore.CAPTURE_OR_SOMETHING which takes a picture and saves in the desired folder with two lines of code, but it doesn't take a picture too.
Do I need to use IPC and bindService() to call this function? Or is there an alternative method to achieve this?
it is really weird that camera on android platform can't stream video until it given valid preview surface. it seems that the architects of the platform was not thinking about 3rd party video streaming applications at all. even for augmented reality case the picture can be presented as some kind of visual substitution, not real time camera stream.
anyway, you can simply resize preview surface to 1x1 pixels and put it somewhere in the corner of the widget (visual element). please pay attention - resize preview surface, not camera frame size.
of course such trick does not eliminate unwanted data streaming (for preview) which consumes some system resources and battery.
I found the answer to this in the Android Camera Docs.
Note: It is possible to use MediaRecorder without creating a camera
preview first and skip the first few steps of this process. However,
since users typically prefer to see a preview before starting a
recording, that process is not discussed here.
You can find the step by step instructions at the link above. After the instructions, it will state the quote that I have provided above.
Actually it is possible, but you have to fake the preview with a dummy SurfaceView
SurfaceView view = new SurfaceView(this);
c.setPreviewDisplay(view.getHolder());
c.startPreview();
c.takePicture(shutterCallback, rawPictureCallback, jpegPictureCallback);
Update 9/21/11: Apparently this does not work for every Android device.
Taking the Photo
Get this working first before trying to hide the preview.
Correctly set up the preview
Use a SurfaceView (pre-Android-4.0 compatibility) or SurfaceTexture (Android 4+, can be made transparent)
Set and initialise it before taking the photo
Wait for the SurfaceView's SurfaceHolder (via getHolder()) to report surfaceCreated() or the TextureView to report onSurfaceTextureAvailable to its SurfaceTextureListener before setting and initialising the preview.
Ensure the preview is visible:
Add it to the WindowManager
Ensure its layout size is at least 1x1 pixels (you might want to start by making it MATCH_PARENT x MATCH_PARENT for testing)
Ensure its visibility is View.VISIBLE (which seems to be the default if you don't specify it)
Ensure you use the FLAG_HARDWARE_ACCELERATED in the LayoutParams if it's a TextureView.
Use takePicture's JPEG callback since the documentation says the other callbacks aren't supported on all devices
Troubleshooting
If surfaceCreated/onSurfaceTextureAvailable doesn't get called, the SurfaceView/TextureView probably isn't being displayed.
If takePicture fails, first ensure the preview is working correctly. You can remove your takePicture call and let the preview run to see if it displays on the screen.
If the picture is darker than it should be, you might need to delay for about a second before calling takePicture so that the camera has time to adjust its exposure once the preview has started.
Hiding the Preview
Make the preview View 1x1 size to minimise its visibility (or try 8x16 for possibly more reliability)
new WindowManager.LayoutParams(1, 1, /*...*/)
Move the preview out of the centre to reduce its noticeability:
new WindowManager.LayoutParams(width, height,
Integer.MIN_VALUE, Integer.MIN_VALUE, /*...*/)
Make the preview transparent (only works for TextureView)
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
width, height, /*...*/
PixelFormat.TRANSPARENT);
params.alpha = 0;
Working Example (tested on Sony Xperia M, Android 4.3)
/** Takes a single photo on service start. */
public class PhotoTakingService extends Service {
#Override
public void onCreate() {
super.onCreate();
takePhoto(this);
}
#SuppressWarnings("deprecation")
private static void takePhoto(final Context context) {
final SurfaceView preview = new SurfaceView(context);
SurfaceHolder holder = preview.getHolder();
// deprecated setting, but required on Android versions prior to 3.0
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
holder.addCallback(new Callback() {
#Override
//The preview must happen at or after this point or takePicture fails
public void surfaceCreated(SurfaceHolder holder) {
showMessage("Surface created");
Camera camera = null;
try {
camera = Camera.open();
showMessage("Opened camera");
try {
camera.setPreviewDisplay(holder);
} catch (IOException e) {
throw new RuntimeException(e);
}
camera.startPreview();
showMessage("Started preview");
camera.takePicture(null, null, new PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
showMessage("Took picture");
camera.release();
}
});
} catch (Exception e) {
if (camera != null)
camera.release();
throw new RuntimeException(e);
}
}
#Override public void surfaceDestroyed(SurfaceHolder holder) {}
#Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}
});
WindowManager wm = (WindowManager)context
.getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
1, 1, //Must be at least 1x1
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
0,
//Don't know if this is a safe default
PixelFormat.UNKNOWN);
//Don't set the preview visibility to GONE or INVISIBLE
wm.addView(preview, params);
}
private static void showMessage(String message) {
Log.i("Camera", message);
}
#Override public IBinder onBind(Intent intent) { return null; }
}
On Android 4.0 and above (API level >= 14), you can use TextureView to preview the camera stream and make it invisible so as to not show it to the user. Here's how:
First create a class to implement a SurfaceTextureListener that will get the create/update callbacks for the preview surface. This class also takes a camera object as input, so that it can call the camera's startPreview function as soon as the surface is created:
public class CamPreview extends TextureView implements SurfaceTextureListener {
private Camera mCamera;
public CamPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
}
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
Camera.Size previewSize = mCamera.getParameters().getPreviewSize();
setLayoutParams(new FrameLayout.LayoutParams(
previewSize.width, previewSize.height, Gravity.CENTER));
try{
mCamera.setPreviewTexture(surface);
} catch (IOException t) {}
mCamera.startPreview();
this.setVisibility(INVISIBLE); // Make the surface invisible as soon as it is created
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
// Put code here to handle texture size change if you want to
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return true;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
// Update your view here!
}
}
You'll also need to implement a callback class to process the preview data:
public class CamCallback implements Camera.PreviewCallback{
public void onPreviewFrame(byte[] data, Camera camera){
// Process the camera data here
}
}
Use the above CamPreview and CamCallback classes to setup the camera in your activity's onCreate() or similar startup function:
// Setup the camera and the preview object
Camera mCamera = Camera.open(0);
CamPreview camPreview = new CamPreview(Context,mCamera);
camPreview.setSurfaceTextureListener(camPreview);
// Connect the preview object to a FrameLayout in your UI
// You'll have to create a FrameLayout object in your UI to place this preview in
FrameLayout preview = (FrameLayout) findViewById(R.id.cameraView);
preview.addView(camPreview);
// Attach a callback for preview
CamCallback camCallback = new CamCallback();
mCamera.setPreviewCallback(camCallback);
There is a way of doing this but it's somewhat tricky.
what should be done, is attach a surfaceholder to the window manager from the service
WindowManager wm = (WindowManager) mCtx.getSystemService(Context.WINDOW_SERVICE);
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);
wm.addView(surfaceview, params);
and then set
surfaceview.setZOrderOnTop(true);
mHolder.setFormat(PixelFormat.TRANSPARENT);
where mHolder is the holder you get from the surface view.
this way, you can play with the surfaceview's alpha, make it completly transparent, but the camera will still get frames.
that's how i do it. hope it helps :)
We solved this problem by using a dummy SurfaceView (not added to actual GUI) in versions below 3.0 (or let's say 4.0 as a camera service on a tablet does not really make sense).
In versions >= 4.0 this worked in the emulator only ;(
The use of SurfaceTexture (and setSurfaceTexture()) instead of SurfaceView (and setSurfaceView()) worked here. At least this works on Nexus S.
I think this really is a shortcoming of the Android framework.
In the "Working Example by Sam" (Thank you Sam... )
if at istruction "wm.addView(preview, params);"
obtain exception "Unable to add window android.view.ViewRoot -- permission denied for this window type"
resolve by using this permission in AndroidManifest:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
You can try this working code, This service click front picture, if you want to capture back camera picture then uncomment back camera in code and comment front camera.
Note :- Allow Camera and Storage permission to App And startService from Activity or anywhere.
public class MyService extends Service {
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
CapturePhoto();
}
private void CapturePhoto() {
Log.d("kkkk","Preparing to take photo");
Camera camera = null;
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
int frontCamera = 1;
//int backCamera=0;
Camera.getCameraInfo(frontCamera, cameraInfo);
try {
camera = Camera.open(frontCamera);
} catch (RuntimeException e) {
Log.d("kkkk","Camera not available: " + 1);
camera = null;
//e.printStackTrace();
}
try {
if (null == camera) {
Log.d("kkkk","Could not get camera instance");
} else {
Log.d("kkkk","Got the camera, creating the dummy surface texture");
try {
camera.setPreviewTexture(new SurfaceTexture(0));
camera.startPreview();
} catch (Exception e) {
Log.d("kkkk","Could not set the surface preview texture");
e.printStackTrace();
}
camera.takePicture(null, null, new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFileDir=new File("/sdcard/CaptureByService");
if (!pictureFileDir.exists() && !pictureFileDir.mkdirs()) {
pictureFileDir.mkdirs();
}
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyymmddhhmmss");
String date = dateFormat.format(new Date());
String photoFile = "ServiceClickedPic_" + "_" + date + ".jpg";
String filename = pictureFileDir.getPath() + File.separator + photoFile;
File mainPicture = new File(filename);
try {
FileOutputStream fos = new FileOutputStream(mainPicture);
fos.write(data);
fos.close();
Log.d("kkkk","image saved");
} catch (Exception error) {
Log.d("kkkk","Image could not be saved");
}
camera.release();
}
});
}
} catch (Exception e) {
camera.release();
}
}
}