I\'m using Camera API and invoking the camera.
I want to display a header (for branding) on the top of the camera preview. The header is a jpeg image.
Is
look your XML would be like this:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<android.view.SurfaceView
android:id="@+id/surface"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<ImageView
android:id = "@+id/header"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content" />
</FrameLayout>
and for the java code you should extend SurfaceHolder.Callback in your activity and then attach the camera to the surface view like this,its my full code please be careful with bitmaps and canvas that is the tricky part :
public class MainActivity extends Activity implements SurfaceHolder.Callback
{
private Camera camera = null;
private SurfaceView cameraSurfaceView = null;
private SurfaceHolder cameraSurfaceHolder = null;
private boolean previewing = false;
RelativeLayout relativeLayout;
private Button btnCapture = null;
private Button btnsave = null;
private Button btnshare = null;
private boolean isSaved=false;
private boolean isCaptured=false;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
getWindow().setFormat(PixelFormat.TRANSLUCENT);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_main);
relativeLayout=(RelativeLayout) findViewById(R.id.containerImg);
relativeLayout.setDrawingCacheEnabled(true);
cameraSurfaceView = (SurfaceView)
findViewById(R.id.surfaceView1);
// cameraSurfaceView.setLayoutParams(new FrameLayout.LayoutParams(640, 480));
cameraSurfaceHolder = cameraSurfaceView.getHolder();
cameraSurfaceHolder.addCallback(this);
// cameraSurfaceHolder.setType(SurfaceHolder.
// SURFACE_TYPE_PUSH_BUFFERS);
btnCapture = (Button)findViewById(R.id.capturebtn);
btnCapture.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
camera.takePicture(cameraShutterCallback,
cameraPictureCallbackRaw,
cameraPictureCallbackJpeg);
isCaptured=true;
}
});
btnsave = (Button)findViewById(R.id.savebtn);
btnsave.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
FrameLayout frm = (FrameLayout)findViewById(R.id.frameLayout1);
frm.setDrawingCacheEnabled(true);
frm.buildDrawingCache();
Bitmap bitmap = frm.getDrawingCache();
try {
File rootFile=new File(Environment.getExternalStorageDirectory().toString()+"/MYCAMERAOVERLAY");
rootFile.mkdirs();
Random generator = new Random();
int n = 10000;
n = generator.nextInt(n);
String fname = "Image-"+ n +".png";
File resultingfile = new File(rootFile, fname);
if (resultingfile.exists ()) resultingfile.delete ();
try {
FileOutputStream Fout = new FileOutputStream(resultingfile);
bitmap.compress(CompressFormat.PNG, 100, Fout);
Fout.flush();
Fout.close();
} catch (FileNotFoundException e) {
Log.d("In Saving File", e + "");
}
} catch(IOException e){
Log.d("In Saving File", e + "");
}
isSaved=true;
}
});
btnshare = (Button)findViewById(R.id.sharebtn);
btnshare.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if((isSaved)&&(isCaptured)){
// TODO sharing what ever we saved
// take the path
}
}
});
}
ShutterCallback cameraShutterCallback = new ShutterCallback()
{
@Override
public void onShutter()
{
// TODO Auto-generated method stub
}
};
PictureCallback cameraPictureCallbackRaw = new PictureCallback()
{
@Override
public void onPictureTaken(byte[] data, Camera camera)
{
// TODO Auto-generated method stub
}
};
PictureCallback cameraPictureCallbackJpeg = new PictureCallback()
{
@Override
public void onPictureTaken(byte[] data, Camera camera)
{
// TODO Auto-generated method stub
Bitmap cameraBitmap = BitmapFactory.decodeByteArray
(data, 0, data.length);
int wid = cameraBitmap.getWidth();
int hgt = cameraBitmap.getHeight();
// Toast.makeText(getApplicationContext(), wid+""+hgt, Toast.LENGTH_SHORT).show();
Bitmap newImage = Bitmap.createBitmap
(wid, hgt, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(newImage);
canvas.drawBitmap(cameraBitmap, 0f, 0f, null);
camera.startPreview();
newImage.recycle();
newImage = null;
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
startActivity(intent);
}
};
@Override
public void surfaceChanged(SurfaceHolder holder,
int format, int width, int height)
{
// TODO Auto-generated method stub
if(previewing)
{
camera.stopPreview();
previewing = false;
}
try
{
Camera.Parameters parameters = camera.getParameters();
parameters.setPreviewSize(640, 480);
parameters.setPictureSize(640, 480);
if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
camera.setDisplayOrientation(-90);
}
// parameters.setRotation(90);
camera.setParameters(parameters);
camera.setPreviewDisplay(cameraSurfaceHolder);
camera.startPreview();
previewing = true;
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void surfaceCreated(SurfaceHolder holder)
{
// TODO Auto-generated method stub
try
{
camera = Camera.open();
}
catch(RuntimeException e)
{
Toast.makeText(getApplicationContext(), "Device camera is not working properly, please try after sometime.", Toast.LENGTH_LONG).show();
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder)
{
// TODO Auto-generated method stub
try{
camera.stopPreview();
camera.release();
camera = null;
previewing = false;
}catch(Exception e){
e.printStackTrace();
}
}
}
and i think now i should give you the full XML part too. so here it is:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android1="http://schemas.android.com/apk/res/android"
android:id="@+id/containerImg"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android1:layout_gravity="bottom"
android:orientation="vertical"
android1:gravity="bottom" >
<FrameLayout
android:id="@+id/frameLayout1"
android1:layout_width="wrap_content"
android1:layout_height="wrap_content"
android:gravity="center|top"
>
<SurfaceView
android1:id="@+id/surfaceView1"
android1:layout_width="100dip"
android1:layout_height="150dip"
android1:layout_gravity="center_horizontal" />
<ImageView
android1:id="@+id/imageView1"
android1:layout_width="fill_parent"
android1:layout_height="fill_parent"
android:contentDescription="@string/app_dress_desc"
android:gravity="center|bottom"
android1:scaleType="center"
android1:src="@drawable/dress" />
</FrameLayout>
<GridLayout
android1:id="@+id/gridLayout1"
android1:layout_width="match_parent"
android1:layout_height="wrap_content"
android1:layout_alignParentBottom="true"
android1:layout_alignParentLeft="true"
android1:columnCount="1"
android1:gravity="center|bottom"
android1:orientation="vertical" >
<ImageButton
android1:id="@+id/capturebtn"
android1:layout_width="60dp"
android1:layout_height="wrap_content"
android1:layout_gravity="left"
android1:src="@drawable/camera"
android:contentDescription="@string/app_icon_camera_desc" />
<ImageButton
android1:id="@+id/savebtn"
android1:layout_width="60dp"
android1:layout_height="wrap_content"
android1:layout_column="0"
android1:layout_gravity="center_horizontal|top"
android1:layout_row="0"
android1:src="@drawable/save"
android:contentDescription="@string/app_icon_save_desc" />
<ImageButton
android1:id="@+id/sharebtn"
android1:layout_width="60dp"
android1:layout_height="wrap_content"
android1:layout_column="0"
android1:layout_gravity="right|top"
android1:layout_row="0"
android1:src="@drawable/share"
android:contentDescription="@string/app_icon_share_desc" />
</GridLayout>
share button doesn't work at this point but it saves the whole frame layout on capture clicked. hope it will be helpful.
You can do that with the help of FrameLayout
like this:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<android.view.SurfaceView
android:id="@+id/surface"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<ImageView
android:id = "@+id/header"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content" />
</FrameLayout>
This camera project will help you.
You can use SurfaceView and create a CustomView that will open the camera and you can adjust its size in the xml accordingly. Below is a pseudo code.
Create a class that extends SurfaceView and open camera inside that
CapturePreview.java
public class CapturePreview extends SurfaceView implements SurfaceHolder.Callback{
public static Bitmap mBitmap;
SurfaceHolder holder;
static Camera mCamera;
public CapturePreview(Context context, AttributeSet attrs) {
super(context, attrs);
holder = getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {
Camera.Parameters parameters = mCamera.getParameters();
parameters.getSupportedPreviewSizes();
mCamera.setParameters(parameters);
mCamera.startPreview();
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
mCamera = Camera.open();
mCamera.setPreviewDisplay(holder);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mCamera.stopPreview();
mCamera.release();
}
/***
*
* Take a picture and and convert it from bytes[] to Bitmap.
*
*/
public static void takeAPicture(){
Camera.PictureCallback mPictureCallback = new PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
BitmapFactory.Options options = new BitmapFactory.Options();
mBitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options);
}
};
mCamera.takePicture(null, null, mPictureCallback);
}
}
Now you have to include the view that you created using SurfaceView in your xml like this
main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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/mySurfaceView"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<com.cam.CapturePreview
android:layout_width="fill_parent"
android:layout_height="wrap_content">
</com.cam.CapturePreview>
</FrameLayout>
<LinearLayout
android:layout_below="@id/mySurfaceView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center">
<ImageView android:id="@+id/myImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/icon"/>
</LinearLayout>
</RelativeLayout>
Now you can use this main.xml in any Acitivty
that will open a camera with a ImageView
.
Thanks....
You will have to handle the whole camera preview and taking picture yourself. Take a look at the Samples at samples/ApiDemos/src/com/example/android/apis/graphics/CameraPreview
. You can have your own layout over the preview area and add your graphic to it.
https://developer.android.com/training/camera/cameradirect#java
I'm afraid you have to implement camera preview screen yourself. In theory an overlay can be added to other application by modifying its layout or by creating an overlay window. The first way is impossible to implement and the second way can be implemented I think but it's kind of a hack and a error prone method.
Implementing you own camera activity is not a very difficult task but it's rather challenging. I would recommend you to take a look at the default Camera application. Here's its source code: https://github.com/android/platform_packages_apps_camera.
A workaround alternative is to overlay the Activity XML file with another XML file which contains the header image. To do so:
overlay.xml
Insert an ImageView
inside it, something like:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<ImageView
android:id="@+id/imageView1"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/android" />
</RelativeLayout>
Then inside the Activity java file, ie MotionDetector.java
file ,
create a new method addView()
:
private void addView()
{
controlInflater = LayoutInflater.from(getBaseContext());
View viewControl = controlInflater.inflate(R.layout.overlay, null);
LayoutParams layoutParamsControl = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
this.addContentView(viewControl, layoutParamsControl);
}
Finally invoke the addView()
method from onCreate()
to add the image:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.header);
addView();
Then end result would be an image overlay above the SurfaceView
. Subject to the quality of the header image, the rendered quality of the header shall seem original. Hope it helps.