Android拍照,上传,预览

taco696 贡献于2012-07-10

作者 王春平  创建于2012-02-08 09:04:00   修改者王春平  修改于2012-02-08 09:10:00字数18075

文档摘要:最近需要做手机拍照([1]、调用系统相机【博客最后】;[2]、自己写照相机布局),预览,上传功能。特地研究了下android的手机拍照,其实不难。
关键词:

 / 19 Android拍照,上传,预览综合 最近需要做手机拍照([1]、调用系统相机【博客最后】;[2]、自己写照相机布局),预览,上传功能。特地研究了下android的手机拍照,其实不难。 参考: http://blog.csdn.net/cfwdl/article/details/5746708 http://mjbb.iteye.com/blog/1018006 http://blog.csdn.net/hellogv/article/details/5962494 1、上传文件功能没啥好说的,网上很多讲的,只要细心点,按照格式来写发送的数据,都是没有问题的。如果遇到问题,欢迎留言讨论、 2、预览也没啥讲的,就用Gallery和ImageSwitcher就行,我做的很简单(参考代码)。 附上流程图:   拍照功能:【预览尺寸有知道的朋友留言告知。】 Java代码   / 19 import java.io.BufferedOutputStream;   import java.io.File;   import java.io.FileOutputStream;   import java.io.IOException;      import android.app.Activity;   import android.app.AlertDialog;   import android.content.DialogInterface;   import android.content.Intent;   import android.graphics.Bitmap;   import android.graphics.BitmapFactory;   import android.graphics.PixelFormat;   import android.hardware.Camera;   import android.hardware.Camera.AutoFocusCallback;   import android.hardware.Camera.PictureCallback;   import android.hardware.Camera.ShutterCallback;   import android.os.Bundle;   import android.os.Environment;   import android.util.Log;   import android.view.KeyEvent;   import android.view.SurfaceHolder;   import android.view.SurfaceView;   import android.view.View;   import android.view.View.OnClickListener;   import android.widget.Button;      import com.peacemap.photo.po.Const;   /**   * 拍照   * @author Administrator   */   public class TakePhotoAct extends Activity implements SurfaceHolder.Callback{              private static String imgPath = Environment.getExternalStorageDirectory().getPath() + "/"+Const.imageDir;              private SurfaceView surfaceView;   //相机画布       private SurfaceHolder surfaceHolder;        private Button takePicView,exitView;              private Camera mCamera;    //照相机              @Override       public void onCreate(Bundle savedInstanceState) {   / 19                    super.onCreate(savedInstanceState);           setContentView(R.layout.main);   //这里我在AndroidManifest.xml的activity中添加了android:theme="@android:style/Theme.NoTitleBar.Fullscreen"              /**           * 隐藏状态栏和标题栏                     this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);          requestWindowFeature(Window.FEATURE_NO_TITLE);          */           //setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);  //横屏           /**           * 获取Button并且设置事件监听           */           takePicView = (Button)this.findViewById(R.id.takepic);           takePicView.setOnClickListener(TakePicListener);           exitView = (Button)this.findViewById(R.id.exit);           exitView.setOnClickListener(new OnClickListener() {               @Override               public void onClick(View v) {                   finish();               }           });           surfaceView = (SurfaceView)this.findViewById(R.id.surface_camera);           surfaceHolder = surfaceView.getHolder();           surfaceHolder.addCallback(this);           surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);                      checkSoftStage();  //首先检测SD卡是否存在       }              /**       * 检测手机是否存在SD卡,网络连接是否打开       */       private void checkSoftStage(){           if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){  //判断是否存在SD卡   //          String rootPath = Environment.getExternalStorageDirectory().getPath();  //获取SD卡的根目录               File file = new File(imgPath);   / 19             if(!file.exists()){                   file.mkdir();               }           }else{               new AlertDialog.Builder(this).setMessage("检测到手机没有存储卡!请插入手机存储卡再开启本应用。")                   .setPositiveButton("确定", new DialogInterface.OnClickListener() {                       @Override                       public void onClick(DialogInterface dialog, int which) {                           finish();                       }                   }).show();           }       }              /**       * 点击拍照按钮,启动拍照       */       private final OnClickListener TakePicListener = new OnClickListener(){           @Override           public void onClick(View v) {               mCamera.autoFocus(new AutoFoucus());  //自动对焦           }       };              /**       * 自动对焦后拍照       * @author aokunsang       * @Date 2011-12-5       */       private final class AutoFoucus implements AutoFocusCallback{           @Override           public void onAutoFocus(boolean success, Camera camera) {               if(success && mCamera!=null){                   mCamera.takePicture(mShutterCallback, null, mPictureCallback);               }           }       }       /**       * 重点对象、 此处实例化了一个本界面的PictureCallback       * 当用户拍完一张照片的时候触发,这时候对图片处理并保存操作。       *        */       private final PictureCallback mPictureCallback = new PictureCallback() {   / 19         @Override           public void onPictureTaken(byte[] data, Camera camera) {               try {                   String fileName = System.currentTimeMillis()+".jpg";                   File file = new File(imgPath,fileName);                   Bitmap bm = BitmapFactory.decodeByteArray(data, 0, data.length);                   BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));                   bm.compress(Bitmap.CompressFormat.JPEG, 60, bos);                   bos.flush();                   bos.close();                                      Intent intent = new Intent(TakePhotoAct.this,PictureViewAct.class);                   intent.putExtra("imagePath", file.getPath());                   startActivity(intent);               } catch (Exception e) {                   e.printStackTrace();               }           }       };       /**       * 在相机快门关闭时候的回调接口,通过这个接口来通知用户快门关闭的事件,       * 普通相机在快门关闭的时候都会发出响声,根据需要可以在该回调接口中定义各种动作, 例如:使设备震动       */         private final ShutterCallback mShutterCallback = new ShutterCallback() {             public void onShutter() {                 Log.d("ShutterCallback", "...onShutter...");             }         };              @Override       /**       * 初始化相机参数,比如相机的参数: 像素, 大小,格式       */       public void surfaceChanged(SurfaceHolder holder, int format, int width,               int height) {           Camera.Parameters param = mCamera.getParameters();           /**           * 设置拍照图片格式           */           param.setPictureFormat(PixelFormat.JPEG);           /**  / 19          * 设置预览尺寸【这里需要注意:预览尺寸有些数字正确,有些会报错,不清楚为啥】           */           //param.setPreviewSize(320, 240);           /**           * 设置图片大小           */           param.setPictureSize(Const.width, Const.height);           mCamera.setParameters(param);           /**           * 开始预览           */           mCamera.startPreview();       }       @Override       /**       * 打开相机,设置预览       */       public void surfaceCreated(SurfaceHolder holder) {           try {               mCamera = Camera.open();  //打开摄像头               mCamera.setPreviewDisplay(holder);           } catch (IOException e) {               mCamera.release();               mCamera = null;           }       }              @Override       /**       * 预览界面被关闭时,或者停止相机拍摄;释放相机资源       */       public void surfaceDestroyed(SurfaceHolder holder) {           mCamera.stopPreview();           if(mCamera!=null) mCamera.release();           mCamera = null;       }              @Override       public boolean onKeyDown(int keyCode, KeyEvent event) {           if(keyCode == KeyEvent.KEYCODE_CAMERA){   //按下相机实体按键,启动本程序照相功能               mCamera.autoFocus(new AutoFoucus());  //自动对焦               return true;   / 19         }else{               return false;           }       }   }     xml: Xml代码                                               预览功能: Java代码   import java.io.File;   import java.util.ArrayList;   import java.util.List;      / 19 import android.app.Activity;   import android.app.AlertDialog;   import android.content.ComponentName;   import android.content.DialogInterface;   import android.content.Intent;   import android.graphics.Bitmap;   import android.graphics.BitmapFactory;   import android.graphics.drawable.BitmapDrawable;   import android.os.Bundle;   import android.os.Environment;   import android.util.Log;   import android.view.Menu;   import android.view.MenuItem;   import android.view.MotionEvent;   import android.view.View;   import android.view.View.OnTouchListener;   import android.view.animation.AnimationUtils;   import android.widget.AdapterView;   import android.widget.Gallery;   import android.widget.ImageSwitcher;   import android.widget.ImageView;   import android.widget.LinearLayout.LayoutParams;   import android.widget.ViewSwitcher.ViewFactory;      import com.peacemap.photo.adapter.ImageAdapter;   import com.peacemap.photo.po.Const;      /**   * 图片浏览   * @author aokunsang   * @Date 2011-12-6   */   public class PhotoScanAct extends Activity implements ViewFactory{                 private static String imgPath = Environment.getExternalStorageDirectory().getPath() + "/"+Const.imageDir;              private ImageSwitcher imageSwitcher;         private Gallery gallery;       private List photoList;       private int downX,upX;       private String newFilePath;          / 19     @Override       protected void onCreate(Bundle savedInstanceState) {           super.onCreate(savedInstanceState);           setContentView(R.layout.photoscan);                      photoList = readFileList();                      imageSwitcher = (ImageSwitcher)findViewById(R.id.switcher);           imageSwitcher.setFactory(this);           /*           * 淡入淡出效果           */           imageSwitcher.setInAnimation(AnimationUtils.loadAnimation(this,                     android.R.anim.fade_in));             imageSwitcher.setOutAnimation(AnimationUtils.loadAnimation(this,                     android.R.anim.fade_out));           imageSwitcher.setOnTouchListener(touchListener);           gallery = (Gallery)findViewById(R.id.gallery);           gallery.setAdapter(new ImageAdapter(this, photoList));           gallery.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {               @Override               public void onItemSelected(AdapterView arg0, View arg1,                       int position, long when) {                   newFilePath = photoList.get(position);                   Bitmap bm = BitmapFactory.decodeFile(photoList.get(position));                   BitmapDrawable bd = new BitmapDrawable(bm);                   imageSwitcher.setImageDrawable(bd);               }               @Override               public void onNothingSelected(AdapterView arg0) {}           });       }              /**       * 注册一个触摸事件       */       private OnTouchListener touchListener = new View.OnTouchListener() {           @Override           public boolean onTouch(View v, MotionEvent event) {                if(event.getAction()==MotionEvent.ACTION_DOWN)                     {                         downX=(int) event.getX();//取得按下时的坐标                         return true;     / 19                 }                     else if(event.getAction()==MotionEvent.ACTION_UP)                     {                         upX=(int) event.getX();//取得松开时的坐标                         int index=0;                         if(upX-downX>100)//从左拖到右,即看前一张                         {                             //如果是第一,则去到尾部                             if(gallery.getSelectedItemPosition()==0)                                index=gallery.getCount()-1;                             else                                 index=gallery.getSelectedItemPosition()-1;                         }                         else if(downX-upX>100)//从右拖到左,即看后一张                         {                             //如果是最后,则去到第一                             if(gallery.getSelectedItemPosition()==(gallery.getCount()-1))                                 index=0;                             else                                 index=gallery.getSelectedItemPosition()+1;                         }                         //改变gallery图片所选,自动触发ImageSwitcher的setOnItemSelectedListener                         gallery.setSelection(index, true);                         return true;                     }                     return false;                 }       };       /**       * 获取SD卡中的所有图片路径       * @return       */       private List readFileList(){           List fileList = new ArrayList();           File fileDir = new File(imgPath);           File[] files = fileDir.listFiles();           if(files!=null){               for(File file:files){                   String fileName = file.getName();                   if (fileName.lastIndexOf(".") > 0                             && fileName.substring(fileName.lastIndexOf(".") + 1,                             fileName.length()).equals("jpg")){                       fileList.add(file.getPath());   / 19                 }               }           }           return fileList;       }          @Override       public View makeView() {           ImageView imageView = new ImageView(this);           imageView.setScaleType(ImageView.ScaleType.CENTER);           imageView.setLayoutParams(new ImageSwitcher.LayoutParams(//自适应图片大小                     LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));           return imageView;       }              //声明2个menu键按钮       public final static int ITEM_1_ID = Menu.FIRST;       public final static int ITEM_2_ID = Menu.FIRST+1;              @Override       public boolean onCreateOptionsMenu(Menu menu) {           super.onCreateOptionsMenu(menu);           menu.add(0, ITEM_1_ID, 0, "我要上传");           menu.add(0, ITEM_2_ID, 1, "我要拍照");           return true;       }              @Override       public boolean onOptionsItemSelected(MenuItem item) {           super.onOptionsItemSelected(item);           switch(item.getItemId()){               case 1:{  //调出系统设置界面                   Intent intent = new Intent(PhotoScanAct.this,PictureViewAct.class);                   intent.putExtra("imagePath",newFilePath);                   startActivity(intent);                   break;               }               case 2:{ //拍照                   startActivity(new Intent(this,TakePhotoAct.class));                   break;               }           }           return true;   / 19     }   }     ImageAdapter适配器: Java代码   import java.util.List;      import android.content.Context;   import android.graphics.Bitmap;   import android.graphics.BitmapFactory;   import android.view.View;   import android.view.ViewGroup;   import android.widget.BaseAdapter;   import android.widget.Gallery;   import android.widget.ImageView;      /**   * 图片适配器   * @author aokunsang   * @Date 2011-12-6   */   public class ImageAdapter extends BaseAdapter {          private List picList;       private Context mContext;       public ImageAdapter(Context mContext,List picList){           this.mContext = mContext;           this.picList = picList;       }              @Override       public int getCount() {           return picList.size();       }          /* (non-Javadoc)       * @see android.widget.Adapter#getItem(int)       */       @Override       public Object getItem(int position) {           // TODO Auto-generated method stub           return picList.get(position);       }          /* (non-Javadoc)  / 19      * @see android.widget.Adapter#getItemId(int)       */       @Override       public long getItemId(int position) {           // TODO Auto-generated method stub           return position;       }          @Override       public View getView(int position, View convertView, ViewGroup parent) {           ImageView image = new ImageView(mContext);           Bitmap bm = BitmapFactory.decodeFile(picList.get(position));           image.setImageBitmap(bm);           image.setScaleType(ImageView.ScaleType.CENTER_CROP);           image.setLayoutParams(new Gallery.LayoutParams(100, 100));           return image;       }   }    xml: Xml代码                                       上传工具类: / 19 Java代码   import java.io.BufferedReader;   import java.io.DataOutputStream;   import java.io.FileInputStream;   import java.io.InputStream;   import java.io.InputStreamReader;   import java.net.HttpURLConnection;   import java.net.URL;   import java.util.Map;   import java.util.Map.Entry;      import android.util.Log;      import com.peacemap.photo.po.FileInfo;      /**   * POST上传文件   * @author aokunsang   * @Date 2011-12-6   */   public class PostFile {          private static PostFile postFile = new PostFile();              private final static String LINEND = "\r\n";       private final static String BOUNDARY = "---------------------------7da2137580612"; //数据分隔线       private final static String PREFIX = "--";       private final static String MUTIPART_FORMDATA = "multipart/form-data";       private final static String CHARSET = "utf-8";       private final static String CONTENTTYPE = "application/octet-stream";              private PostFile(){}       public static PostFile getInstance(){           return postFile;       }              /**       * HTTP上传文件       * @param actionUrl  请求服务器的路径       * @param params     传递的表单内容       * @param files      多个文件信息       * @return       */   / 19     public String post(String actionUrl,Map params,FileInfo[] files){           try {               URL url = new URL(actionUrl);               HttpURLConnection urlConn = (HttpURLConnection)url.openConnection();               urlConn.setDoOutput(true);   //允许输出               urlConn.setDoInput(true);   //允许输入               urlConn.setUseCaches(false);               urlConn.setRequestMethod("POST");               urlConn.setRequestProperty("connection", "Keep-Alive");               urlConn.setRequestProperty("Charset", CHARSET);               urlConn.setRequestProperty("Content-Type", MUTIPART_FORMDATA+";boundary="+BOUNDARY);                              DataOutputStream dos = new DataOutputStream(urlConn.getOutputStream());               //构建表单数据               String entryText = bulidFormText(params);               Log.i("-------描述信息---------------", entryText);               dos.write(entryText.getBytes());                              StringBuffer sb = new StringBuffer("");                      for(FileInfo file : files){                   sb.append(PREFIX).append(BOUNDARY).append(LINEND);                   sb.append("Content-Disposition: form-data; name=\""+file.getFileTextName()+"\"; filename=\""+file.getFile().getAbsolutePath()+"\""+LINEND);                   sb.append("Content-Type:"+CONTENTTYPE+";charset="+CHARSET+LINEND);                   sb.append(LINEND);                   dos.write(sb.toString().getBytes());                                      InputStream is = new FileInputStream(file.getFile());                   byte[] buffer = new byte[1024];                   int len = 0;                   while ((len = is.read(buffer)) != -1) {                       dos.write(buffer, 0, len);                   }                   is.close();                   dos.write(LINEND.getBytes());               }               //请求的结束标志               byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINEND).getBytes();               dos.write(end_data);               dos.flush();   / 19     //-----------------------------------  发送请求数据结束  ----------------------------                      //----------------------------------   接收返回信息 ------------------------                              int code = urlConn.getResponseCode();               if(code!=200){                   urlConn.disconnect();                   return "";               }else{                   BufferedReader br = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));                   String result = "";                   String line = null;                   while((line = br.readLine())!=null){                       result += line;                   }                   br.close();                   urlConn.disconnect();                   return result;               }           } catch (Exception e) {               Log.e("--------上传图片错误--------", e.getMessage());               return null;           }       }              /**       * HTTP上传单个文件       * @param actionUrl  请求服务器的路径       * @param params     传递的表单内容       * @param files      单个文件信息       * @return       */       public String post(String actionUrl,Map params,FileInfo fileInfo){           return post(actionUrl, params, new FileInfo[]{fileInfo});       }              /**       * 封装表单文本数据       * @param paramText       * @return       */       private String bulidFormText(Map paramText){           if(paramText==null || paramText.isEmpty()) return "";   / 19         StringBuffer sb = new StringBuffer("");           for(Entry entry : paramText.entrySet()){                sb.append(PREFIX).append(BOUNDARY).append(LINEND);               sb.append("Content-Disposition:form-data;name=\""                       + entry.getKey() + "\"" + LINEND);   //          sb.append("Content-Type:text/plain;charset=" + CHARSET + LINEND);               sb.append(LINEND);               sb.append(entry.getValue());               sb.append(LINEND);           }           return sb.toString();       }       /**       * 封装文件文本数据       * @param files       * @return       */       private String buildFromFile(FileInfo[] files){           StringBuffer sb = new StringBuffer();           for(FileInfo file : files){               sb.append(PREFIX).append(BOUNDARY).append(LINEND);               sb.append("Content-Disposition: form-data; name=\""+file.getFileTextName()+"\"; filename=\""+file.getFile().getAbsolutePath()+"\""+LINEND);               sb.append("Content-Type:"+CONTENTTYPE+";charset="+CHARSET+LINEND);               sb.append(LINEND);           }           return sb.toString();       }   }     -------------------------------------我是个华丽的分割线,哇哈哈----------------------------------------------- 做完这个拍照后,感觉功能太简单,比如:设置图片大小,白天夜晚照相等等一些系统照相机带的功能都没有,因此用在项目中感觉不炫。 然后就用了简单点的,直接调用系统照相机了。本来想着简单呢,后来也遇到点问题。     (1)根据Camera Activity返回的时候,会带一个名为data的Bitmap对象,照片的缩略图(这个地方可以做各种修改,我没用到不说了),上代码: Java代码    @Override        public void onCreate(Bundle savedInstanceState) {          super.onCreate(savedInstanceState);          checkSoftStage();   / 19                  try {              Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);              startActivityForResult(intent, TAKE_PICTURE);           } catch (Exception e) {              e.printStackTrace();          }   }    /**       * 检测手机是否存在SD卡,网络连接是否打开       */       private void checkSoftStage(){           if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){  //判断是否存在SD卡               File file = new File(imgPath);               if(!file.exists()){                   file.mkdir();               }           }else{               new AlertDialog.Builder(this).setMessage("检测到手机没有存储卡!请插入手机存储卡再开启本应用。")                   .setPositiveButton("确定", new DialogInterface.OnClickListener() {                       @Override                       public void onClick(DialogInterface dialog, int which) {                           finish();                       }                   }).show();           }       }    protected void onActivityResult(int requestCode, int resultCode, Intent data)  {                        if (resultCode == TAKE_PICTURE)      {                             //  拍照Activity保存图像数据的key是data,返回的数据类型是Bitmap对象                             Bitmap cameraBitmap = (Bitmap) data.getExtras().get("/sdcard/rtest.jpg");                            //  在ImageView组件中显示拍摄的照片                            image.setImageBitmap(cameraBitmap);                       // 做自己的业务操作。。。。                   }               super.onActivityResult(requestCode, resultCode, data);                     }         (2)以上代码在我的小米手机上测试时,出现问题了。 返回的name为data的 / 19 Bitmap对象是个Null,我发现小米照完相片之后,他会先跳到一个预览的界面(系统自带的页面),所以得不到Bitmap对象了。 因此我就先保存照片以及其路径,然后在onActivityResult中获取图片,做业务操作,代码如下: Java代码     public void onCreate(Bundle savedInstanceState) {      super.onCreate(savedInstanceState);      checkSoftStage();            try {          Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);          startActivityForResult(intent, TAKE_PICTURE);       } catch (Exception e) {          e.printStackTrace();      }            try {          Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);          String fileName = System.currentTimeMillis()+".jpg";          newImgPath = imgPath + "/" + fileName;          Uri uri = Uri.fromFile(new File(imgPath,fileName));          intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);          startActivityForResult(intent, TAKE_PICTURE);          } catch (Exception e) {             e.printStackTrace();         }      }   @Override      protected void onActivityResult(int requestCode,       int resultCode, Intent data) {           Log.i("--------图片路径---------", "------"+newImgPath+"---------");         //.....做一些业务操作       } catch (Exception e) {           e.printStackTrace();       }       super.onActivityResult(requestCode, resultCode, data);     }  

下载文档到电脑,查找使用更方便

文档的实际排版效果,会与网站的显示效果略有不同!!

需要 5 金币 [ 分享文档获得金币 ] 9 人已下载

下载文档