首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 移动开发 > Android >

Android照相,上传,预览综合

2012-07-22 
Android拍照,上传,预览综合?最近需要做手机拍照([1]、调用系统相机【博客最后】;[2]、自己写照相机布局),预览,

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就行,我做的很简单(参考代码)。

?

附上流程图:
Android照相,上传,预览综合
?拍照功能:【预览尺寸有知道的朋友留言告知。】
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) {        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() {@Overridepublic 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);if(!file.exists()){file.mkdir();}}else{new AlertDialog.Builder(this).setMessage("检测到手机没有存储卡!请插入手机存储卡再开启本应用。").setPositiveButton("确定", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {finish();}}).show();}}/** * 点击拍照按钮,启动拍照 */private final OnClickListener TakePicListener = new OnClickListener(){@Overridepublic void onClick(View v) {mCamera.autoFocus(new AutoFoucus());  //自动对焦}};/** * 自动对焦后拍照 * @author aokunsang * @Date 2011-12-5 */private final class AutoFoucus implements AutoFocusCallback{@Overridepublic void onAutoFocus(boolean success, Camera camera) {if(success && mCamera!=null){mCamera.takePicture(mShutterCallback, null, mPictureCallback);}}}/** * 重点对象、 此处实例化了一个本界面的PictureCallback * 当用户拍完一张照片的时候触发,这时候对图片处理并保存操作。 *  */private final PictureCallback mPictureCallback = new PictureCallback() {@Overridepublic 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);/** * 设置预览尺寸【这里需要注意:预览尺寸有些数字正确,有些会报错,不清楚为啥】 *///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;}@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event) {if(keyCode == KeyEvent.KEYCODE_CAMERA){   //按下相机实体按键,启动本程序照相功能mCamera.autoFocus(new AutoFoucus());  //自动对焦return true;}else{return false;}}}
??xml:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    ><SurfaceView android:id="@+id/surface_camera"android:layout_width="fill_parent"android:layout_height="fill_parent"android:layout_weight="1"/><LinearLayout android:orientation="horizontal"android:layout_width="fill_parent"android:layout_height="wrap_content"><Button android:text="拍照"android:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/takepic"/><Button android:text="退出"android:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/exit"/></LinearLayout></LinearLayout>
?预览功能:
import java.io.File;import java.util.ArrayList;import java.util.List;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<String> photoList;    private int downX,upX;    private String newFilePath;@Overrideprotected 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() {@Overridepublic 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);}@Overridepublic void onNothingSelected(AdapterView<?> arg0) {}});}/** * 注册一个触摸事件 */private OnTouchListener touchListener = new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) { if(event.getAction()==MotionEvent.ACTION_DOWN)                  {                      downX=(int) event.getX();//取得按下时的坐标                      return true;                  }                  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<String> readFileList(){List<String> fileList = new ArrayList<String>();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());}}}return fileList;}@Overridepublic 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;@Overridepublic boolean onCreateOptionsMenu(Menu menu) {super.onCreateOptionsMenu(menu);menu.add(0, ITEM_1_ID, 0, "我要上传");menu.add(0, ITEM_2_ID, 1, "我要拍照");return true;}@Overridepublic 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;}}
??ImageAdapter适配器:
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<String> picList;private Context mContext;public ImageAdapter(Context mContext,List<String> picList){this.mContext = mContext;this.picList = picList;}@Overridepublic int getCount() {return picList.size();}/* (non-Javadoc) * @see android.widget.Adapter#getItem(int) */@Overridepublic Object getItem(int position) {// TODO Auto-generated method stubreturn picList.get(position);}/* (non-Javadoc) * @see android.widget.Adapter#getItemId(int) */@Overridepublic long getItemId(int position) {// TODO Auto-generated method stubreturn position;}@Overridepublic 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 version="1.0" encoding="utf-8"?><RelativeLayout  xmlns:android="http://schemas.android.com/apk/res/android"  android:layout_width="match_parent"  android:layout_height="match_parent">      <ImageSwitcher     android:id="@+id/switcher"android:layout_width="match_parent"android:layout_height="match_parent"    ></ImageSwitcher>       <Gallery    android:id="@+id/gallery"   android:layout_width="match_parent"   android:background="#55000000"   android:layout_height="100dip"   android:layout_alignParentBottom="true"          android:layout_alignParentLeft="true"   android:gravity="center_vertical"   android:spacing="8dip"   /> </RelativeLayout>
?上传工具类:
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 */public String post(String actionUrl,Map<String,String> 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();//-----------------------------------  发送请求数据结束  ----------------------------    //----------------------------------   接收返回信息 ------------------------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<String,String> params,FileInfo fileInfo){return post(actionUrl, params, new FileInfo[]{fileInfo});}/** * 封装表单文本数据 * @param paramText * @return */private String bulidFormText(Map<String,String> paramText){if(paramText==null || paramText.isEmpty()) return "";StringBuffer sb = new StringBuffer("");for(Entry<String,String> 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对象,照片的缩略图(这个地方可以做各种修改,我没用到不说了),上代码:
 @Override     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();   }} /** * 检测手机是否存在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() {@Overridepublic 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的Bitmap对象是个Null,我发现小米照完相片之后,他会先跳到一个预览的界面(系统自带的页面),所以得不到Bitmap对象了。因此我就先保存照片以及其路径,然后在onActivityResult中获取图片,做业务操作,代码如下:
   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);   }
?

1 楼 zgycsmb 2011-12-15  
你好,android中拍照,上传图片到服务器中的功能,哪位有例子吗,求发一份给我
350038760@qq.com
多谢
2 楼 wzx_dd 2012-03-29   虚心学习了!!! 3 楼 dubo1020 2012-05-08   哥们,写的很好!求源码!不胜感激! 4 楼 dubo1020 2012-05-08   哥们,写的很好,求源码,不胜感激,dubo1020@126.com 5 楼 a86970012 2012-05-22   import com.peacemap.photo.po.Const;  
这个类在那里啊?干撒用的啊 6 楼 a86970012 2012-05-22   import com.peacemap.photo.po.FileInfo; 

这个类又在那里的啊 7 楼 kwangunistars 2012-06-12   大侠,能发一份源码给我吗,谢谢!116356754@qq.com

热点排行