Android 自定義拍照,解決圖片旋轉,拍照參數設置兼容問題


  今天客戶提了一個需求: 需要結合攝像頭將拍照的圖片和自己的產品(圖片)整合到一張圖片上面,如下圖:  
 
20150908143828051.jpg
 
針對這個功能需要做自定義相機,根據Camera相機類和SurfaceView類來實現自定義圖形預覽拍照功能。
但在實現過程中出現幾個難點:
1.如何將自己產品圖片(上圖的台燈)和攝像頭預覽的圖片結合成一張圖片。
2.拍照的圖片在有些手機上面出現旋轉了90度的情況(Android兼容性問題)。
3.某些手機會出現在camera.setParameters(parameters)的調用時候出現設置失敗的異常 java.lang.RuntimeException: setParameters failed
 
針對第一個問題:
     開始的考慮是在布局中SurfaceView上加一層ImageView來顯示產品圖片,然后通過截取View的方法截取SurfaceView和ImageView的父布局來實現,但截取view的時候發現只能截取靜態的方法,對於像surfaceview之類的動態的view是不能夠截取的(具體的截取方法請參考下面的源碼),后來才有的是繪圖的方式將預覽圖片的bitmap和產品圖片的bitmap繪制到一張圖片實現圖片的合並(具體方法請參考下面源碼)。
 
針對第二個問題:
    這個顯然是android手機的兼容性問題,網上也有很大類似的網友提出此類問題,但給出的解決方法大都是先通過ExifInterface類來 讀取bitmap的旋轉角度,然后根據旋轉角度旋轉bitmap實現,我也用這個方法檢驗過,但實際上此方法並不靠譜,原因是讀取bitmap的角度始終為0,即使我圖片在拍照后出現的旋轉了90度,也是讀取不了的。后來找一篇文章: http://www.xuebuyuan.com/1223069.html 該文章介紹了ExifInterface類在某些機型的有兼容性問題,並指出了問題產生的原因,我采用,拍照完成后,強制調用 setPictureDegreeZero方法(具體實現參考下面源碼)來重新將圖片的旋轉角度設置為0,終於以次方解決了問題。終於松了口氣,啊哈哈。
 
 
針對第三個問題:  
  某些機型出現了設置拍照參數失敗,是因為某些參數設置對應該機型不支持,這里我需要做到的是需要確認哪些參數有兼容性問題的,經測試發現,
// parameters.setPreviewFrameRate(3);// 每秒3幀 每秒從攝像頭里面獲得3個畫面, 此參數在小米2上面支持,在紅米note2上面不支持,
// parameters . setPreviewSize ( PreviewWidth , PreviewHeight ); // 獲得攝像區域的大小
// parameters.setPictureSize(PreviewWidth,PreviewHeight);// 獲得保存圖片的大小 ----這個兩個參數也會有兼容性問題。
 
    目前發現這里3個參數有兼容性問題,其它若有發現在補充,同時如果網友們發現了其它參數存在兼容性問題也煩請指出,謝謝。
針對不兼容性問題,盡量避免去設置它,
對應setPreviewSize和setPictureSize可以通過以下方式取得合適的預覽尺寸進行設置,具體方法請參考下面源代碼。
// 選擇合適的預覽尺寸 List < Camera . Size > sizeList = parameters . getSupportedPreviewSizes ();
 
 
具體實現代碼:
  1. package com.example.eclipsetest;
    
    import java.io.BufferedOutputStream;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.lang.reflect.Method;
    import java.util.Iterator;
    import java.util.List;
    
    import android.app.Activity;
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.Bitmap.Config;
    import android.graphics.BitmapFactory;
    import android.graphics.Canvas;
    import android.graphics.Matrix;
    import android.graphics.PixelFormat;
    import android.graphics.drawable.Drawable;
    import android.hardware.Camera;
    import android.hardware.Camera.AutoFocusCallback;
    import android.hardware.Camera.Parameters;
    import android.hardware.Camera.PictureCallback;
    import android.hardware.Camera.ShutterCallback;
    import android.hardware.Camera.Size;
    import android.media.ExifInterface;
    import android.os.Build;
    import android.os.Bundle;
    import android.os.Environment;
    import android.util.DisplayMetrics;
    import android.util.Log;
    import android.view.Display;
    import android.view.Gravity;
    import android.view.SurfaceHolder;
    import android.view.SurfaceView;
    import android.view.View;
    import android.view.View.MeasureSpec;
    import android.view.View.OnClickListener;
    import android.view.WindowManager;
    import android.widget.Button;
    import android.widget.FrameLayout;
    import android.widget.ImageView;
    import android.widget.ImageView.ScaleType;
    import android.widget.Toast;
    
    /**
     * 自定義拍照,將特定圖片添加到預覽圖片中保存起來
     * 
     * @ClassName: MyCameraDemo
     * @Description:
     * @author xiaoxiao
     * @date modify by 2015-9-8 下午2:09:16
     * 
     */
    public class MyCameraDemo extends Activity {
    	private SurfaceView surface = null;
    	private Button but = null;
    	private SurfaceHolder holder = null;
    	private Camera cam = null;
    	private boolean previewRunning = true;
    	private Button but2;
    	private ImageView iv_img;
    	private FrameLayout flay_view;
    
    	@Override
    	public void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		super.setContentView(R.layout.main);
    		this.but = (Button) super.findViewById(R.id.but);
    		this.but2 = (Button) super.findViewById(R.id.but2);
    		this.surface = (SurfaceView) super.findViewById(R.id.surface);
    		iv_img = (ImageView) findViewById(R.id.iv_img);
    		flay_view = (FrameLayout) findViewById(R.id.flay_view);
    		this.holder = this.surface.getHolder();
    		this.holder.addCallback(new MySurfaceViewCallback());
    		this.holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    		this.holder.setFixedSize(500, 350);
    		this.but.setOnClickListener(new OnClickListenerImpl());
    		but2.setOnClickListener(new OnClickListener() {
    
    			@Override
    			public void onClick(View v) {
    				iv_img.setVisibility(View.VISIBLE);
    				iv_img.setImageResource(R.drawable.taideng);
    			}
    		});
    	}
    
    	private class OnClickListenerImpl implements OnClickListener {
    
    		@Override
    		public void onClick(View v) {
    			if (cam != null) {
    				cam.autoFocus(new AutoFocusCallbackImpl());
    			}
    		}
    
    	}
    
    	private class MySurfaceViewCallback implements SurfaceHolder.Callback {
    
    		@Override
    		public void surfaceChanged(SurfaceHolder holder, int format, int width,
    				int height) {
    
    		}
    
    		@Override
    		public void surfaceCreated(SurfaceHolder holder) {
    			if (cam != null) {
    				cam.stopPreview();// 停掉原來攝像頭的預覽
    				cam.release();// 釋放資源
    				cam = null;// 取消原來攝像頭
    			}
    			try {
    				cam = Camera.open(0); // 取得第一個攝像頭
    			} catch (Exception e) {
    				// TODO: handle exception
    				Toast.makeText(MyCameraDemo.this, "攝像頭打開失敗", 0).show();
    				return;
    			}
    			cam = deal2(cam);
    		}
    
    		@Override
    		public void surfaceDestroyed(SurfaceHolder holder) {
    			if (cam != null) {
    				if (MyCameraDemo.this.previewRunning) {
    					cam.stopPreview(); // 停止預覽
    					MyCameraDemo.this.previewRunning = false;
    				}
    				cam.stopPreview();
    				cam.release();
    				cam = null;
    			}
    		}
    
    	}
    
    	private class AutoFocusCallbackImpl implements AutoFocusCallback {
    
    		@Override
    		public void onAutoFocus(boolean success, Camera camera) {
    			if (success) { // 成功
    				cam.takePicture(sc, pc, jpgcall);
    			}
    		}
    
    	}
    
    	private PictureCallback jpgcall = new PictureCallback() {
    
    		@Override
    		public void onPictureTaken(byte[] data, Camera camera) { // 保存圖片的操作
    			Bitmap bmp = BitmapFactory.decodeByteArray(data, 0, data.length);
    			// Bitmap bmp2 = new BitmapDrawable(iv_img).getDrawable();
    			// Bitmap bmp2 = BitmapFactory.decodeResource(getResources(),
    			// R.drawable.taideng);
    			// Bitmap bmp2 = drawableToBitamp(iv_img.getDrawable());
    			String fileName = "test_" + System.currentTimeMillis() + ".jpg";
    			String filePath = Environment.getExternalStorageDirectory()
    					.toString()
    					+ File.separator
    					+ "xiao"
    					+ File.separator
    					+ fileName;
    			bmp = rotateBitmapByDegree(bmp, 90);
    
    			save(bmp, filePath, fileName);
    			bmp = loadBitmap(filePath, true);
    			setPictureDegreeZero(filePath);
    
    			Bitmap bmp2 = getSmallBitmap(MyCameraDemo.this,
    					R.drawable.taideng, dip2px(MyCameraDemo.this, 200),
    					dip2px(MyCameraDemo.this, 200));
    			Bitmap bmp3 = combineBitmap(bmp, bmp2);
    			save(bmp3, filePath, fileName);
    			cam.stopPreview();
    			cam.startPreview();
    		}
    
    	};
    
    	private ShutterCallback sc = new ShutterCallback() {
    		@Override
    		public void onShutter() {
    			// 按下快門之后進行的操作
    		}
    	};
    	private PictureCallback pc = new PictureCallback() {
    
    		@Override
    		public void onPictureTaken(byte[] data, Camera camera) {
    
    		}
    
    	};
    
    	/**
    	 * 開始考慮用剪切的方法,但是截取只適合靜態界面,這里surfaceView是動態的(在不斷重繪)不能剪切,后來考慮用繪圖的方式將兩個bitmap合在一起。
    	 * 
    	 * @param view
    	 * @return
    	 */
    	private Bitmap cropView(View view) {
    		view.measure(MeasureSpec.makeMeasureSpec(100, MeasureSpec.UNSPECIFIED),
    				MeasureSpec.makeMeasureSpec(100, MeasureSpec.UNSPECIFIED));
    		view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
    		view.buildDrawingCache();
    		Bitmap bitmap = view.getDrawingCache();
    		return bitmap;
    	}
    
    	
    	/**
    	 * 合並兩張bitmap為一張
    	 * 
    	 * @param background
    	 * @param foreground
    	 * @return Bitmap
    	 */
    	public static Bitmap combineBitmap(Bitmap background, Bitmap foreground) {
    		if (background == null) {
    			return null;
    		}
    		int bgWidth = background.getWidth();
    		int bgHeight = background.getHeight();
    		int fgWidth = foreground.getWidth();
    		int fgHeight = foreground.getHeight();
    		Bitmap newmap = Bitmap
    				.createBitmap(bgWidth, bgHeight, Config.ARGB_8888);
    		Canvas canvas = new Canvas(newmap);
    		canvas.drawBitmap(background, 0, 0, null);
    		canvas.drawBitmap(foreground, (bgWidth - fgWidth) / 2,
    				(bgHeight - fgHeight) / 2, null);
    		canvas.save(Canvas.ALL_SAVE_FLAG);
    		canvas.restore();
    		return newmap;
    	}
    
    	private void save(Bitmap bitmap, String filePath, String fileName) {
    		File file = new File(filePath);
    		if (!file.getParentFile().exists()) {
    			file.getParentFile().mkdirs(); // 創建文件夾
    		}
    		try {
    			BufferedOutputStream bos = new BufferedOutputStream(
    					new FileOutputStream(file));
    			bitmap.compress(Bitmap.CompressFormat.JPEG, 80, bos); // 向緩沖區之中壓縮圖片
    			bos.flush();
    			bos.close();
    			Toast.makeText(MyCameraDemo.this,
    					"拍照成功,照片已保存在" + fileName + "文件之中!", Toast.LENGTH_SHORT)
    					.show();
    		} catch (Exception e) {
    			Toast.makeText(MyCameraDemo.this, "拍照失敗!", Toast.LENGTH_SHORT)
    					.show();
    		}
    	}
    
    	private Bitmap bitmap;
    
    	private Bitmap drawableToBitamp(Drawable drawable) {
    		int w = drawable.getIntrinsicWidth();
    		int h = drawable.getIntrinsicHeight();
    		System.out.println("Drawable轉Bitmap");
    		Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
    				: Bitmap.Config.RGB_565;
    		bitmap = Bitmap.createBitmap(w, h, config);
    		// 注意,下面三行代碼要用到,否在在View或者surfaceview里的canvas.drawBitmap會看不到圖
    		Canvas canvas = new Canvas(bitmap);
    		drawable.setBounds(0, 0, w, h);
    		drawable.draw(canvas);
    		return bitmap;
    	}
    
    	/**
    	 * 讀取圖片的旋轉的角度, 某些機型此方法無效
    	 * 
    	 * @param path
    	 *            圖片絕對路徑
    	 * @return 圖片的旋轉角度
    	 */
    	private int getBitmapDegree(String path) {
    		int degree = 0;
    		try {
    			// 從指定路徑下讀取圖片,並獲取其EXIF信息
    			ExifInterface exifInterface = new ExifInterface(path);
    			// 獲取圖片的旋轉信息
    			int orientation = exifInterface.getAttributeInt(
    					ExifInterface.TAG_ORIENTATION,
    					ExifInterface.ORIENTATION_NORMAL);
    			switch (orientation) {
    			case ExifInterface.ORIENTATION_ROTATE_90:
    				degree = 90;
    				break;
    			case ExifInterface.ORIENTATION_ROTATE_180:
    				degree = 180;
    				break;
    			case ExifInterface.ORIENTATION_ROTATE_270:
    				degree = 270;
    				break;
    			}
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    		return degree;
    	}
    
    	/**
    	 * 將圖片按照某個角度進行旋轉
    	 * 
    	 * @param bm
    	 *            需要旋轉的圖片
    	 * @param degree
    	 *            旋轉角度
    	 * @return 旋轉后的圖片
    	 */
    	public static Bitmap rotateBitmapByDegree(Bitmap bm, int degree) {
    		Bitmap returnBm = null;
    
    		// 根據旋轉角度,生成旋轉矩陣
    		Matrix matrix = new Matrix();
    		matrix.postRotate(degree);
    		try {
    			// 將原始圖片按照旋轉矩陣進行旋轉,並得到新的圖片
    			returnBm = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(),
    					bm.getHeight(), matrix, true);
    		} catch (OutOfMemoryError e) {
    		}
    		if (returnBm == null) {
    			returnBm = bm;
    		}
    		if (bm != returnBm) {
    			bm.recycle();
    		}
    		return returnBm;
    	}
    
    	// 控制圖像的正確顯示方向
    	private void setDispaly(Camera.Parameters parameters, Camera camera) {
    		if (Integer.parseInt(Build.VERSION.SDK) >= 8) {
    			setDisplayOrientation(camera, 90);
    		} else {
    			parameters.setRotation(90);
    		}
    
    	}
    
    	// 實現的圖像的正確顯示
    	private void setDisplayOrientation(Camera camera, int i) {
    		Method downPolymorphic;
    		try {
    			downPolymorphic = camera.getClass().getMethod(
    					"setDisplayOrientation", new Class[] { int.class });
    			if (downPolymorphic != null) {
    				downPolymorphic.invoke(camera, new Object[] { i });
    			}
    		} catch (Exception e) {
    			Log.e("Came_e", "圖像出錯");
    		}
    	}
    
    	private Camera deal2(Camera mCamera) {
    		// 設置camera預覽的角度,因為默認圖片是傾斜90度的
    		// mCamera.setDisplayOrientation(90);
    
    		int PreviewWidth = 0;
    		int PreviewHeight = 0;
    		WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);// 獲取窗口的管理器
    		Display display = wm.getDefaultDisplay();// 獲得窗口里面的屏幕
    		Camera.Parameters parameters = mCamera.getParameters();
    		// parameters.setFlashMode(Parameters.FLASH_MODE_TORCH); //開啟閃光燈,支持
    		setDispaly(parameters, mCamera);
    		// parameters.setRotation(90);
    		// parameters.setPreviewFrameRate(3);// 每秒3幀 每秒從攝像頭里面獲得3個畫面,
    		// 某些機型(紅米note2)不支持
    		parameters.setPictureFormat(PixelFormat.JPEG);// 設置照片輸出的格式
    		parameters.set("jpeg-quality", 100);// 設置照片質量
    		try {
    			// 選擇合適的預覽尺寸
    			List<Camera.Size> sizeList = parameters.getSupportedPreviewSizes();
    			// 如果sizeList只有一個我們也沒有必要做什么了,因為就他一個別無選擇
    			if (sizeList.size() > 1) {
    				Iterator<Camera.Size> itor = sizeList.iterator();
    				while (itor.hasNext()) {
    					Camera.Size cur = itor.next();
    					if (cur.width >= PreviewWidth
    							&& cur.height >= PreviewHeight) {
    						PreviewWidth = cur.width;
    						PreviewHeight = cur.height;
    						break;
    					}
    				}
    			}
    			parameters.setPreviewSize(PreviewWidth, PreviewHeight); // 獲得攝像區域的大小
    			parameters.setPictureSize(PreviewWidth, PreviewHeight); // 獲得保存圖片的大小
    			// parameters.setPreviewSize(display.getWidth(),
    			// display.getWidth()); // 獲得攝像區域的大小
    			// parameters.setPictureSize(display.getWidth(),
    			// display.getWidth());// 設置拍出來的屏幕大小
    
    		} catch (Exception e) {
    			Log.e("MyCameraDemo", e.toString());
    		}
    		try {
    			cam.setPreviewDisplay(MyCameraDemo.this.holder);
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		mCamera.setParameters(parameters);// 把上面的設置 賦給攝像頭
    		mCamera.startPreview();// 開始預覽
    		mCamera.cancelAutoFocus();// 2如果要實現連續的自動對焦,這一句必須加上
    		previewRunning = true;
    		return mCamera;
    	}
    
    	/** 從給定路徑加載圖片 */
    	public Bitmap loadBitmap(String imgpath) {
    		return BitmapFactory.decodeFile(imgpath);
    	}
    
    	/** 從給定的路徑加載圖片,並指定是否自動旋轉方向 */
    	public Bitmap loadBitmap(String imgpath, boolean adjustOritation) {
    		if (!adjustOritation) {
    			return loadBitmap(imgpath);
    		} else {
    			Bitmap bm = loadBitmap(imgpath);
    			int digree = 0;
    			ExifInterface exif = null;
    			try {
    				exif = new ExifInterface(imgpath);
    			} catch (IOException e) {
    				e.printStackTrace();
    				exif = null;
    			}
    			if (exif != null) {
    				// 讀取圖片中相機方向信息
    				// int ori = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
    				// ExifInterface.ORIENTATION_NORMAL);
    				int ori = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
    						ExifInterface.ORIENTATION_FLIP_VERTICAL);
    				// 計算旋轉角度
    				switch (ori) {
    				case ExifInterface.ORIENTATION_ROTATE_90:
    					digree = 90;
    					break;
    				case ExifInterface.ORIENTATION_ROTATE_180:
    					digree = 180;
    					break;
    				case ExifInterface.ORIENTATION_ROTATE_270:
    					digree = 270;
    					break;
    				default:
    					digree = 0;
    					break;
    				}
    			}
    			if (digree != 0) {
    				// 旋轉圖片
    				Matrix m = new Matrix();
    				m.postRotate(digree);
    				bm = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(),
    						bm.getHeight(), m, true);
    			}
    			return bm;
    		}
    	}
    
    	/**
    	 * 將圖片的旋轉角度置為0  ,此方法可以解決某些機型拍照后圖像,出現了旋轉情況
    	 * 
    	 * @Title: setPictureDegreeZero
    	 * @param path
    	 * @return void
    	 * @date 2012-12-10 上午10:54:46
    	 */
    	private void setPictureDegreeZero(String path) {
    		try {
    			ExifInterface exifInterface = new ExifInterface(path);
    			// 修正圖片的旋轉角度,設置其不旋轉。這里也可以設置其旋轉的角度,可以傳值過去,
    			// 例如旋轉90度,傳值ExifInterface.ORIENTATION_ROTATE_90,需要將這個值轉換為String類型的
    			exifInterface.setAttribute(ExifInterface.TAG_ORIENTATION, "no");
    			exifInterface.saveAttributes();
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    
    	}
    
    	/**
    	 * 根據路徑獲取圖片並壓縮返回bitmap用於顯示
    	 * 
    	 * @param context
    	 * @param id
    	 * @return
    	 */
    
    	private  Bitmap getSmallBitmap(Context context, int id,int width,int height) {
    		final BitmapFactory.Options options = new BitmapFactory.Options();
    		options.inJustDecodeBounds = true;
    		BitmapFactory.decodeResource(context.getResources(), id, options);
    		// 計算 縮略圖大小為原始圖片大小的幾分之一 inSampleSize:縮略圖大小為原始圖片大小的幾分之一
    		options.inSampleSize = calculateInSampleSize(options, width, height);
    		options.inJustDecodeBounds = false;
    
    		return BitmapFactory.decodeResource(context.getResources(), id, options);
    	}
    	
    	/**
    	 * 計算圖片的縮放值
    	 * 
    	 * @param options
    	 * @param reqWidth
    	 * @param reqHeight
    	 * @return
    	 */
    	private  int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
    		// Raw height and width of image
    		final int height = options.outHeight;
    		final int width = options.outWidth;
    		int inSampleSize = 1;
    
    		if (height > reqHeight || width > reqWidth) {
    			final int heightRatio = Math.round((float) height / (float) reqHeight);
    			final int widthRatio = Math.round((float) width / (float) reqWidth);
    			inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
    
    		}
    		return inSampleSize;
    
    	}
    	/**
    	 * 根據手機的分辨率從 dp 的單位 轉成為 px(像素)
    	 */
    	public static int dip2px(Context context, float dpValue) {
    		final float scale = context.getResources().getDisplayMetrics().density;
    		return (int) (dpValue * scale + 0.5f);
    	}
    
    	/**
    	 * 根據手機的分辨率從 px(像素) 的單位 轉成為 dp
    	 */
    	public static int px2dip(Context context, float pxValue) {
    		final float scale = context.getResources().getDisplayMetrics().density;
    		return (int) (pxValue / scale + 0.5f);
    	}
    }
    

      


 
布局文件:
  1. <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >
        <FrameLayout
            android:id="@+id/flay_view"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_weight="1000" >
            <SurfaceView
                android:id="@+id/surface"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:layout_weight="1000" />
            <ImageView 
                android:id="@+id/iv_img"
                android:layout_width="200dp"
                android:layout_height="200dp"
                android:layout_gravity="center"
                android:visibility="gone"
                android:src="@drawable/taideng"
                android:scaleType="fitCenter"/>
        </FrameLayout>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:orientation="horizontal" >
            <Button
                android:id="@+id/but"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="照相" />
            <Button
                android:id="@+id/but2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="添加圖片" />
        </LinearLayout>
    </LinearLayout>  
    

      

 
最后不要忘了權限:
    
  1. <uses-feature android:name="android.hardware.camera" />
        <uses-feature android:name="android.hardware.camera.autofocus" />
        <uses-permission android:name="android.permission.CAMERA" />
        <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 

     

 
 

 



 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM