Android开发:获得相册图片、拍照、照片上传服务器、从服务器读取照片

文章目录

  • 一 整体功能描述
  • 二 功能实现
    • 1 获得图片
    • 2上传到服务器并保存
    • 3从服务器中获得图片并显示
    • 4Common类中的辅助工具

一. 整体功能描述

通过从相册中选择图片或者拍照的方式获得图片,然后将这个图片上传至服务器,同时实现从服务器上读取该图片。

二. 功能实现

1.1 获得图片

(1)通常情况下,有以下两种方式:

  • 从相册中选择图片

    这种方式原理比较简单,就是从SDK中获得照片,转成字节再生产Bitmap对象用于显示即可。

  • 拍照获得图片

    拍照获取的图片原理就是先拍照存储,然后再读取,就和从相册中选择图片的原理一样了。

(2)实现:

下面是实现该功能的代码,由于某种不知名的原因,拍照获得图片的方式一直存在问题:无法加载此图片。解决解决,始终无法解决,就暂且搁下了。本文的重点还是放在了第二部分,关于上传到服务器,第一部分还需要进一步完善,关于图片的选择和处理,推荐一叶飘舟的文章。

  • 首先是点击头像弹出一个dialog供选择读入图片的方式:
 private    CharSequence []its = {"拍照","从相册选择"};
 //上传头像
 headImageView.setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(View v) {
     new AlertDialog.Builder(ModiUserInfoActivity.this)
                    .setTitle("更换头像")
                    .setItems(its, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                    Intent intent = new Intent();
                    switch (which)
                    {
                        case 0://拍照,没有实现的部分,暂时就不贴代码了,其实暗想应该不难,但是问题却一直不能解决。
                            break;
                        case 1://从相册选择
                            intent.setAction(Intent.ACTION_GET_CONTENT);//ACTION_OPEN_DOCUMENT
                            intent.addCategory(Intent.CATEGORY_OPENABLE);
                            intent.setType("image/*");
                            //intent.putExtra("return-data", true);//返回数据
                            //intent.putExtra("crop", "true");//裁剪
                            startActivityForResult(intent,SELECT_PIC);//启动activity,重写onActivityResult获取结果
                            break;
                                }
                            }
                        })
                        .create()
                        .show();
            }
        });
    }
  • 然后就是对图片数据进行处理了
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
   if (resultCode != RESULT_OK)
       return;
       switch (requestCode)
       {
           case SELECT_PIC://相册

              // ContentResolver resolver = getContentResolver();
              //照片的原始资源地址
              // Uri originalUri = data.getData();
              // Log.i("originalUri",originalUri+"");
              Bitmap photo = null;
              // try
              // {
              photo = data.getParcelableExtra("data");
              //photo = BitmapFactory.decodeStream(resolver.openInputStream(originalUri));
               if(photo!=null)
               {
                   headImage = Common.zoomBitmap(photo, 85, 85);//进行了缩放,可以忽视
                   UserController.updateHeadImage(userId, headImage, handler);//上传服务器更新,后面贴代码
                   photo.recycle();//回收
               }
                   //headImageView.setImageBitmap(headImage);
            /*   }catch (IOException e) {
                   e.printStackTrace();
               }*/
               break;
           case SELECT_CAMERA://相机,下面代码写了不少,但是一直存在问题~
               try {
                   // 启动gallery去剪辑这个照片
                   //final Intent intent = Common.getCropImageIntent(Uri.fromFile(photoFile));
                   //startActivityForResult(intent, SELECT_PIC);
                   Intent intent = new Intent("com.android.camera.action.CROP"); //剪裁
                   intent.setDataAndType(photoFile, "image/*");
                   intent.putExtra("scale", true);
                    //设置宽高比例
                   intent.putExtra("aspectX", 1);
                   intent.putExtra("aspectY", 1);
                   intent.putExtra("outputX", 80);
                   intent.putExtra("outputY", 80);
                   intent.putExtra(MediaStore.EXTRA_OUTPUT, photoFile);
                   //Toast.makeText(ModiUserInfoActivity.this, photoFile.toString(), Toast.LENGTH_SHORT).show();
                   //广播刷新相册
                    Intent intentBc = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
                    intentBc.setData(photoFile);
                    this.sendBroadcast(intentBc);
                    startActivityForResult(intent, CROP_PHOTO); //设置裁剪参数显示图片至ImageView
               } catch (Exception e) {
                   e.printStackTrace();
               }
               break;
           case CROP_PHOTO:
               try {
                   //图片解析成Bitmap对象
                   Bitmap bitmap = BitmapFactory.decodeStream(
                           getContentResolver().openInputStream(photoFile));
                   //Toast.makeText(ModiUserInfoActivity.this, imageUri.toString(), Toast.LENGTH_SHORT).show();
                   headImage = Common.zoomBitmap(bitmap, 85, 85);
                   UserController.updateHeadImage(userId, headImage, handler);
               } catch(FileNotFoundException e) {
                   e.printStackTrace();
               }
               break;
           default:
               break;
       }

    }

ok,按照上面的代码,从相册选择照片加裁剪是没有问题了,至于对图片的一些处理,可以参考一叶飘舟的博文。

1.2上传到服务器并保存

查阅了很多资料,使用的方式要么都是那种上传文件那类看起来就特别复杂的方式,看的我真的头大了。后来找了好几个版本自己都没能成功实现把1.1中获取的图片上传到服务器。后来回想了一下http请求不就是传送的字节嘛,那我把图片转成字节不就能传过去了么,另一个问题又来了,有时候我们并不是单单传送一张图片过去,可能还有其他信息,比如一个表单或者一个id之类的,总之要传送的数据还有不仅仅是图片。之前传送数据都是通过json或者map转成String再转成byte[]实现的,那么现在传送的是图片+其他数据,思路便是:图片->String,然后和其他数据一起打包成json->String->byte[]->Bitmap。

  • 客户端

    现在接着写1.1中代码使用到的UserController.updateHeadImage(userId, headImage, handler)。

/**
 * 保存头像
 * @param userId
 * @param handler
 * @param image
 */
 public static void updateHeadImage(final String userId,final Bitmap image, final Handler handler)
 {
     new Thread()
        {
            @Override
            public void run()
            {
                JSONObject jsonObject = new JSONObject();
                try {
                    jsonObject.put("userId",userId);
                    //将Bitmap转成String,其实这是一个加密过程。后面会有Common.Bitmap2String()的代码。
                    jsonObject.put("userImageContent", Common.Bitmap2String(image));

                    String content = String.valueOf(jsonObject);
                    /**
                     * 请求地址
                     */
                    String url =  ConfigModel.getServerURL()+"user/updateImage";
                    String result = Common.httpPost(url,content);//post请求服务器:数据content,请求路径url。这个函数也是自己写在Common类里,其实就是稍微封装了一下post请求的过程,方便复用。
                    Log.i("result",result);
                    /**
                     * 服务器返回结果
                     * 继续干什么事情....
                     */
                    Message message = new Message();
                    Bundle bundle = new Bundle();
                    bundle.putString("result",result);
                    message.setData(bundle);
                    message.what = R.id.save_user_image_result;
                    handler.sendMessage(message);

                }catch (Exception e){}
            }
        }.start();
    }
  • 服务器端

    客户端将图片加密成了String,那么服务端就需要解码就可以获得图片。

//第一步,将数据流转String,自己封装成了一个read函数,方便复用;
String streamIn = ReadStream.read(new BufferedInputStream(request.getInputStream()));
//JSONObject object = JSONObject.fromObject(streamIn).getJSONObject("user");
JSONObject object = JSONObject.fromObject(streamIn);//String转JSON
String userId = object.getString("userId");
String userImageContent = object.getString("userImageContent");//获得图像的数据
//..其他步骤省略
//..比如判断是否是新图像,比如生成图像ID imgId = Tool.getUUID();
//第二步将图像数据String转成Bitmap
byte[] bitmapArray= Base64.decode(imageContent);
try
{
    File imageFile = new File(headImagePath);
    if(!imageFile.exists())
        imageFile.mkdirs();
        //创建输出流
    FileOutputStream outStream = new FileOutputStream(imageFile.getPath()+"\\"+imgId+".png");
        //写入数据
    outStream.write(bitmapArray);
        //关闭输出流
    outStream.close();
}
catch(IOException e)
{
    System.out.println(e);
}

由此就完美的将客户端的图像和数据都上传到服务器上了。下面部分就是从服务器上获得图片和数据再返回给客户端,有了前面部分的思路,那这部分就很容易实现,反其道而行之就可以了。

1.3从服务器中获得图片并显示

  • 服务器端

    服务器端要做的事情就是将Bitmap转成String,然后和其他数据打包成json,返回给客户端。

//读取图片,转成String
    public static String readImage(String imgId)
    {
        //byte []data = imageContent.getBytes();
        File file = new File(headImagePath+imgId+".png");
        try {
            FileInputStream inputStream = new FileInputStream(file);
            byte[] bitmapArray = new byte[(int) file.length()];
            inputStream.read(bitmapArray);
            inputStream.close();
            return Base64.encode(bitmapArray);
        } catch(Exception e)
        {
            return "";
        }
    }
    //*****************************************
    //代码片.....和上面的代码不在同一个java文件中
    //*****************************************
    /**
     * 查询一个user
     *
     * @param userId
     *            主键
     * @return user
     */
    @RequestMapping(value = "/user/get/{id}")
    @ResponseBody
    public JSONObject get(@PathVariable("id") String userId,
            HttpServletResponse response) {
        response.setHeader("Access-Control-Allow-Origin", "*");
        User user = userDAO.getUser(userId);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("user", user);
        if(user.getUserImage()!=null&&!"".equals(user.getUserImage()))
        {
            jsonObject.put("userImageContent", Tool.readImage(user.getUserImage()));
        }
        return jsonObject;
    }
  • 客户端

    这部分我就不贴代码了,因为自己把很多功能都封装了,要贴出来有点麻烦,总之此时的图片数据已经转成了String,只需要在显示的时候,再转成Bitmap。String->Bitmap的实现请参考我的Common类。

1.4Common类中的辅助工具

 /**
     * 图像转字节
     * @param bm
     * @return
     */
    public static byte[] Bitmap2Bytes(Bitmap bm) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
        return baos.toByteArray();
    }

    /**
     * 图像转String
     * @param bitmap
     * @return
     */
    public static String Bitmap2String(Bitmap bitmap)
    {
        return Base64.encodeToString(Bitmap2Bytes(bitmap), Base64.DEFAULT);
    }
    /**
     * string转成bitmap
     *
     * @param st
     */
    public static Bitmap String2Bitmap(String st)
    {
        Bitmap bitmap = null;
        try
        {
            byte[] bitmapArray;
            bitmapArray = Base64.decode(st, Base64.DEFAULT);
            bitmap = BitmapFactory.decodeByteArray(bitmapArray, 0, bitmapArray.length);
            return bitmap;
        }
        catch (Exception e)
        {
            return null;
        }
    }

OK,最后大功告成,后面再解决拍照、以及图片处理的问题!

时间: 2024-12-07 21:06:29

Android开发:获得相册图片、拍照、照片上传服务器、从服务器读取照片的相关文章

Android选择系统相册或拍照上传源码

简单示范获取系统相册图片和拍照获取图片回传压缩处理 下载地址:http://www.devstore.cn/code/info/821.html 运行截图:

Android选择系统相册或拍照上传

PhotoUtils.rar

Android上使用camera拍照,把获取的照片上传到远程服务器

使用Java上传文件 从Apache Software Foundation下载HttpClient 4.3.4. 在工程中添加下面的jar包: 参考sample,写一个简单的上传: public static void main(String[] args) throws Exception {         // TODO Auto-generated method stub         CloseableHttpClient httpclient = HttpClients.crea

基于H5+ API手机相册图片压缩上传

// 母函数 function App(){} /** * 图片压缩,默认同比例压缩 * @param {Object} path * pc端传入的路径可以为相对路径,但是在移动端上必须传入的路径是照相图片储存的绝对路径 * @param {Object} obj * obj 对象 有 width, height, quality(0-1) * @param {Object} callback * 回调函数有一个参数,base64的字符串数据 */ App.prototype.dealImage

Android开发之裁切(拍照+相册)图像并设置头像小结

先看效果:                                                   再贴代码: 自定义选择照片底部弹出对话框布局: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width=&

Android 开发 Camera类的拍照与录像

前言 在开发Android应用的时候,如果需要调用摄像头拍照或者录像,除了通过Intent调用系统现有相机应用进行拍照录像之外,还可以通过直接调用Camera硬件去去获取摄像头进行拍照录像的操作.本篇博客将讲解如何在Android应用中通过Camera拍照录像. 参考博客:https://www.cnblogs.com/plokmju/p/android_Camera.html Camera api 说明 Camera是Android摄像头硬件的相机类,位于硬件包"android.hardwar

Android开发中根据图片名称获取在drawable中的ID

在Android开发中图片资源是必不可少的,如ImageView需要图片资源的ID,ImageButton需要资源的ID等等,我们可以用R.drawable.XXX可以获取图片资源的ID,但是,在某些时候,这样做很费时,我们想动态的获得资源ID,比如说,我传入一个图片名称的字符串,根据字符串来获得资源的ID这样就很方便了,没错,这样确实很方便,我们如果对图片的名称稍加改动,比如用img1.png,img2.png,img3.png...这样就可以在一个循环之内获得所有的ID,对开发来说少写的就不

Android高仿微信图片选择上传工具

源码托管地址:https://github.com/SleepyzzZ/photo-selector 话不多说,先上效果图(高仿微信图片选择器): 图片选择界面: 图片预览界面: 批量上传图片: 实现的功能介绍: 1.图片异步加载,使用Glide开源库实现加载; 2.图片的预览界面,支持左右滑动,双击放大浏览; 3.图片批量上传,使用OkHttp来实现与Servlet服务器的通信; 使用方法(Android Studio): 新建工程,File->New->Import Module导入pho

Android -- 图片异步上传到PHP服务器

背景                                                                                           网上很多上传到java服务器上的,找了好久,找到了上传到php的了,思路跟我当初想的差不多,就是POST过去.废话不多说,直接上图看代码. php代码                                                                                  

Android中利用HTTP协议实现上传文件到服务器

首先我们需要使用HTTP协议发送数据,我们就要知道HTTP发送上传文件到服务器的时候需要哪些头字段已经相关的配置,请看下图 这是使用浏览器模拟上传文件到服务器时候所发送的请求,我们可以看到它包含了请求头字段和实体部分,但是多了一个---------------------------7da2137580612,它实际上是一条分隔线,用于分隔实体数据的,他在使用分隔实体数据的时候会在前面包含多两个"-"而在结束的时候会在除了在前面都出两个减号"-"之外,还会在末尾都出