Android:在Android相机预览上叠加
我正在使用Camera API并调用相机。
我想在相机预览的顶部显示标题(用于品牌)。 标题是一个JPEG图像。
可能吗? 任何帮助赞赏。
提前致谢。
我的代码如下。
public class CameraActivity extends Activity { @Override protected void onPause() { super.onPause(); } private static final int CAMERA_PIC_REQUEST = 2500; private Bitmap image2; private Bitmap bm; public static String imagepath; public static int x=1; private RdmsDbAdapter dbHelper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.header); setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); //caling new incident if(IncidentFormActivity.incident_id == null || IncidentFormActivity.isDisable==true){ //DBAdapter instance created and connection opened. dbHelper = new RdmsDbAdapter(CameraActivity.this); dbHelper.open(); //setting up flags NewIncidentHelper nih = new NewIncidentHelper(); nih.setUpNewIncident(); //setting up incident_id String Date= IncidentIdGenerator.getDate(); String Time = IncidentIdGenerator.getTime(); IncidentFormActivity.incident_id = IncidentIdGenerator.now("ddMMyyyyHHmmss"); dbHelper.executeSQL("insert into incident values ('" + IncidentFormActivity.incident_id + "', ' ', ' ', ' ', ' ', '"+Date+"', '0','0','0','0','0','0','0','0','0','"+Time+"')"); dbHelper.close(); } //calling camera Intent cameraIntent = new Intent( android.provider.MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResult(cameraIntent, CAMERA_PIC_REQUEST); } public String getPath(Uri uri) { String[] projection = { MediaStore.Images.Media.DATA }; Cursor cursor = managedQuery(uri, projection, null, null, null); int column_index = cursor .getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst(); return cursor.getString(column_index); } //back key on phone pressed @Override public boolean onKeyDown(int keyCode, KeyEvent event) { switch (keyCode) { case KeyEvent.KEYCODE_BACK: Intent i= new Intent(CameraActivity.this, IncidentFormActivity.class); startActivity(i); this.finish(); break; default: break; } return super.onKeyDown(keyCode, event); } //handle response came from camera when the picture is taken. protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == CAMERA_PIC_REQUEST && resultCode == RESULT_OK) { final ImageView img = new ImageView(this); img.setLayoutParams(new LayoutParams(100, 100)); image2 = (Bitmap) data.getExtras().get("data"); img.setImageBitmap(image2); String incident_ID = IncidentFormActivity.incident_id; //l2.addView(img); imagepath="/sdcard/RDMS/"+incident_ID+ x + ".png"; File file = new File(imagepath); try { bm = Bitmap.createScaledBitmap( image2,400, 300, true); file.createNewFile(); FileOutputStream ostream = new FileOutputStream(file); bm.compress(CompressFormat.PNG, 90, ostream); ostream.close(); //Initialising db class and inserting values dbHelper = new RdmsDbAdapter(CameraActivity.this); dbHelper.open(); dbHelper.executeSQL("insert into files values ('"+imagepath+"', '"+IncidentFormActivity.incident_id+"')"); dbHelper.close(); } catch (Exception e) { e.printStackTrace(); Toast.makeText(getApplicationContext(),"yourfirst error message is " + e.toString(), 1000).show(); } x++; final AlertDialog.Builder alert = new AlertDialog.Builder( CameraActivity.this); alert.setTitle(getString(R.string.anotherimage)); alert.setCancelable(false); //alert.setMessage("Play or Delete the Video selected"); //alert.setIcon(R.drawable.vid_red); alert.setPositiveButton(getString(R.string.yes), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { Intent sendingpage = new Intent(CameraActivity.this, CameraActivity.class); startActivity(sendingpage); } }); alert.setNegativeButton(getString(R.string.no), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { Intent callback = new Intent (CameraActivity.this, IncidentFormActivity.class); startActivity(callback); } }); alert.show(); } if(resultCode==RESULT_CANCELED) { AlertDialog.Builder builder = new AlertDialog.Builder(CameraActivity.this); builder.setMessage(getString(R.string.areuexit)).setCancelable( false).setPositiveButton(getString(R.string.yes), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { Intent i= new Intent(CameraActivity.this, IncidentFormActivity.class); startActivity(i); CameraActivity.this.finish(); } }).setNegativeButton(getString(R.string.no), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); Intent i= new Intent(CameraActivity.this, CameraActivity.class); startActivity(i); CameraActivity.this.finish(); } }); builder.show(); } } }
您可以使用SurfaceView并创build一个CustomView来打开相机,并可以相应地调整xml的大小。 下面是一个伪代码。
创build一个扩展SurfaceView并打开相机的类
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); } }
现在你必须在你的xml中包含你使用SurfaceView创build的视图
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>
现在,您可以在任何使用ImageView
打开相机的Acitivty
中使用main.xml。 谢谢….
你将不得不处理整个相机预览,并自己拍照。 看samples/ApiDemos/src/com/example/android/apis/graphics/CameraPreview
。 您可以在预览区域拥有自己的布局,并将graphics添加到预览区域。
示例链接:
你可以在FrameLayout
的帮助下做到这一点:
<?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>
这个相机项目将帮助你。
恐怕你必须自己实现相机预览屏幕。 理论上,可以通过修改布局或创build覆盖窗口来将覆盖图添加到其他应用程序。 第一种方式是不可能实现的,第二种方式是可以实现的,但是这种方式是一种黑客攻击和容易出错的方法。
实现你自己的摄像头活动不是一件非常困难的事情,但是这是相当具有挑战性的。 我会build议你看看默认的相机应用程序。 这是它的源代码: https : //github.com/android/platform_packages_apps_camera 。
看你的XML会是这样的:
<?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>
对于java代码,您应该在您的活动中扩展SurfaceHolder.Callback,然后像这样将相机连接到表面视图,其完整的代码请注意位图和canvas,这是棘手的部分:
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(); } }
}
我想现在我应该给你完整的XML部分。 所以这里是:
<?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>
分享button在这一点上不起作用,但它保存点击捕捉整个框架布局。 希望这会有所帮助。
解决方法替代方法是将Activity XML文件与包含标题图像的另一个XML文件叠加。 要做到这一点:
- 在布局文件夹中创build一个新的布局文件。 例如:
overlay.xml
-
在里面插入一个
ImageView
,像这样:<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>
-
然后在Activity的java文件里面,即
MotionDetector.java
文件中,创build一个新的方法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); }
-
最后调用
onCreate()
的addView()
方法添加图像:protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.header); addView();
然后最终的结果将是在SurfaceView
之上的图像叠加。 根据标题图像的质量,标题的渲染质量应该是原始的。 希望能帮助到你。