zoukankan      html  css  js  c++  java
  • 假期学习记录17(Android拍照并将图片上传到服务器)

    首先在layout文件中布局如下,很简单就是一个ImageView用于显示图片,一个按钮拍照,一个按钮上传

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/activity_up_photo"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:gravity="center"
        tools:context="com.example.sportrecord.UpPhoto">
    <ImageView
        android:id="@+id/photoshow"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <Button
                android:layout_marginLeft="10dp"
                android:text="拍照打卡"
                android:id="@+id/takephoto"
                android:layout_width="180dp"
                android:layout_height="match_parent" />
            <Button
                android:layout_marginRight="0dp"
                android:text="确认上传"
                android:id="@+id/upphoto"
                android:layout_width="180dp"
                android:layout_height="match_parent" />
        </LinearLayout>
    </LinearLayout>

    然后再activity的java文件中代码如下

    package com.example.sportrecord;
    
    import android.app.Activity;
    import android.content.Intent;
    import android.content.SharedPreferences;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.net.Uri;
    import android.os.Build;
    import android.provider.MediaStore;
    import android.support.v4.content.FileProvider;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Base64;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.ImageView;
    import android.widget.Toast;
    
    import com.example.sportrecord.Util.BitmapUtils;
    import com.example.sportrecord.Util.NetUtil;
    
    import java.io.ByteArrayOutputStream;
    import java.io.File;
    
    public class UpPhoto extends Activity {
        public static final int TAKE_PHOTO=1;
        private ImageView photoshow;
        private Uri imageUri;
        private Button takephoto;
        private Button upphoto;
        public  Bitmap bitmap1;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_up_photo);
            takephoto=(Button)findViewById(R.id.takephoto);
            upphoto=(Button)findViewById(R.id.upphoto);
            photoshow=(ImageView)findViewById(R.id.photoshow);
            Intent intent=getIntent();
            String point=intent.getStringExtra("point");
            takephoto.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    File outputImage =new File(getExternalCacheDir(),"output_image.jpg");//将拍照文件存在本地
                    try{
                        if (outputImage.exists()){
                            outputImage.delete();
                        }
                        outputImage.createNewFile();
                    }catch (Exception e){
    
                    }
                    if(Build.VERSION.SDK_INT>=24){
                        imageUri= FileProvider.getUriForFile(UpPhoto.this,"com.example.SportRecord.fileprovider",outputImage);//fileprovider下面会定义
                    }else {
                        imageUri=Uri.fromFile(outputImage);
                    }
                    Intent intent=new Intent("android.media.action.IMAGE_CAPTURE");//打开相机
                    intent.putExtra(MediaStore.EXTRA_OUTPUT,imageUri);
                    startActivityForResult(intent,TAKE_PHOTO);
                }
    
            });
            upphoto.setOnClickListener(new View.OnClickListener() {//上传图片
                @Override
                public void onClick(View v) {
                    if (bitmap1==null){
                        Toast.makeText(UpPhoto.this,"无图片",Toast.LENGTH_LONG).show();
                    }else {
                    SharedPreferences pref=getSharedPreferences("userMessage",MODE_PRIVATE);//获取用户id,项目需要,例子中直接删了就好
                    String useraccount=pref.getString("useraccount","");
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            NetUtil.getPhotoMes(UpPhoto.this,bitmap1,useraccount,point);//NetUtil.getPhotoMes是一个自定义函数用来和服务器连接,下面有代码
                        }
                    }).start();
                   Toast.makeText(UpPhoto.this,"成功",Toast.LENGTH_LONG).show();
                   UpPhoto.this.finish();
                }
                }
            });
        }
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {//显示图片startActivityForResult启动的intent会自动跳到这里
            switch (requestCode) {
                case TAKE_PHOTO:
                    if (resultCode == RESULT_OK) {
                        try {
                            Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
                            bitmap1= BitmapUtils.zoomImage(bitmap,400,550);//压缩图片,下面也有源码
                            photoshow.setImageBitmap(bitmap1);
                        } catch (Exception e) {
    
                        }
                    }
                    break;
                default:
                    break;
            }
        }
    }

    服务器连接函数NetUtil.getPhotoMes

    public static void getPhotoMes(Context cont, Bitmap photodata, String user_account, String point) {
            try {
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
    
                //将bitmap一字节流输出 Bitmap.CompressFormat.PNG 压缩格式,100:压缩率,baos:字节流
                photodata.compress(Bitmap.CompressFormat.PNG, 100, baos);
                baos.close();
                byte[] buffer = baos.toByteArray();
                System.out.println("图片的大小:"+buffer.length);
    
                //将图片的字节流数据加密成base64字符输出
                String photo = Base64.encodeToString(buffer, 0, buffer.length,Base64.DEFAULT);
    
                //photo=URLEncoder.encode(photo,"UTF-8");
                RequestParams params = new RequestParams();
                params.put("photo", photo);
                params.put("user_account", user_account);//传输的字符数据
                params.put("point", point);//传输的字符数据
                String url = "服务器sevlet地址";
    
    
                AsyncHttpClient client = new AsyncHttpClient();
                client.post(url, params, new AsyncHttpResponseHandler() {
                });
    
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }




    /图片压缩函数BitmapUtils.zoomImage,我给的函数较多,我使用的是zoomImage这个函数输入一个bitmap返回一个压缩后的bitmap,嫌累直接看zoomImage就好

    package com.example.sportrecord.Util;
    
    import android.content.Context;
    import android.content.CursorLoader;
    import android.content.res.Resources;
    import android.database.Cursor;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.Matrix;
    import android.net.Uri;
    import android.provider.MediaStore;
    
    public class BitmapUtils {
    
        private static int mDesiredWidth;
        private static int mDesiredHeight;
    
        /**
         * @description 从Resources中加载图片
         *
         * @param res
         * @param resId
         * @param reqWidth
         * @param reqHeight
         * @return
         */
        public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) {
            BitmapFactory.Options options = new BitmapFactory.Options();
            //Bitmap bmp = BitmapFactory.decodeFile(path,options);
            // 设置成了true,不占用内存,只获取bitmap宽高
            options.inJustDecodeBounds = true;
            // 初始化options对象
            BitmapFactory.decodeResource(res, resId, options);
            // 得到计算好的options,目标宽、目标高
            options = getBestOptions(options, reqWidth, reqHeight);
            Bitmap src = BitmapFactory.decodeResource(res, resId, options); // 载入一个稍大的缩略图
            return createScaleBitmap(src, mDesiredWidth, mDesiredHeight); // 进一步得到目标大小的缩略图
        }
        public static Bitmap zoomImage(Bitmap bgimage, double newWidth,
                                       double newHeight) {
            // 获取这个图片的宽和高
            float width = bgimage.getWidth();
            float height = bgimage.getHeight();
            // 创建操作图片用的matrix对象
            Matrix matrix = new Matrix();
            // 计算宽高缩放率
            float scaleWidth = ((float) newWidth) / width;
            float scaleHeight = ((float) newHeight) / height;
            // 缩放图片动作
            matrix.postScale(scaleWidth, scaleHeight);
            Bitmap bitmap = Bitmap.createBitmap(bgimage, 0, 0, (int) width,
                    (int) height, matrix, true);
            return bitmap;
        }
        /**
         * @description 从SD卡上加载图片
         *
         * @param pathName
         * @param reqWidth
         * @param reqHeight
         * @return
         */
        public static Bitmap decodeSampledBitmapFromFile(String pathName, int reqWidth, int reqHeight) {
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeFile(pathName, options);
            options = getBestOptions(options, reqWidth, reqHeight);
            Bitmap src = BitmapFactory.decodeFile(pathName, options);
            return createScaleBitmap(src, mDesiredWidth, mDesiredHeight);
        }
    
        /**
         * @description 计算目标宽度,目标高度,inSampleSize
         *
         * @param options
         * @param reqWidth
         * @param reqHeight
         * @return BitmapFactory.Options对象
         */
        private static BitmapFactory.Options getBestOptions(BitmapFactory.Options options, int reqWidth, int reqHeight) {
            // 读取图片长宽
            int actualWidth = options.outWidth;
            int actualHeight = options.outHeight;
            // Then compute the dimensions we would ideally like to decode to.
            mDesiredWidth = getResizedDimension(reqWidth, reqHeight, actualWidth, actualHeight);
            mDesiredHeight = getResizedDimension(reqHeight, reqWidth, actualHeight, actualWidth);
            // 根据现在得到计算inSampleSize
            options.inSampleSize = calculateBestInSampleSize(actualWidth, actualHeight, mDesiredWidth, mDesiredHeight);
            // 使用获取到的inSampleSize值再次解析图片
            options.inJustDecodeBounds = false;
            return options;
        }
    
        /**
         * Scales one side of a rectangle to fit aspect ratio. 最终得到重新测量的尺寸
         *
         * @param maxPrimary
         *            Maximum size of the primary dimension (i.e. width for max
         *            width), or zero to maintain aspect ratio with secondary
         *            dimension
         * @param maxSecondary
         *            Maximum size of the secondary dimension, or zero to maintain
         *            aspect ratio with primary dimension
         * @param actualPrimary
         *            Actual size of the primary dimension
         * @param actualSecondary
         *            Actual size of the secondary dimension
         */
        private static int getResizedDimension(int maxPrimary, int maxSecondary, int actualPrimary, int actualSecondary) {
            double ratio = (double) actualSecondary / (double) actualPrimary;
            int resized = maxPrimary;
            if (resized * ratio > maxSecondary) {
                resized = (int) (maxSecondary / ratio);
            }
            return resized;
        }
    
        /**
         * Returns the largest power-of-two divisor for use in downscaling a bitmap
         * that will not result in the scaling past the desired dimensions.
         *
         * @param actualWidth
         *            Actual width of the bitmap
         * @param actualHeight
         *            Actual height of the bitmap
         * @param desiredWidth
         *            Desired width of the bitmap
         * @param desiredHeight
         *            Desired height of the bitmap
         */
        // Visible for testing.
        private static int calculateBestInSampleSize(int actualWidth, int actualHeight, int desiredWidth, int desiredHeight) {
            double wr = (double) actualWidth / desiredWidth;
            double hr = (double) actualHeight / desiredHeight;
            double ratio = Math.min(wr, hr);
            float inSampleSize = 1.0f;
            while ((inSampleSize * 2) <= ratio) {
                inSampleSize *= 2;
            }
    
            return (int) inSampleSize;
        }
    
    
        private static Bitmap createScaleBitmap(Bitmap tempBitmap, int desiredWidth, int desiredHeight) {
            // If necessary, scale down to the maximal acceptable size.
            if (tempBitmap != null && (tempBitmap.getWidth() > desiredWidth || tempBitmap.getHeight() > desiredHeight)) {
                // 如果是放大图片,filter决定是否平滑,如果是缩小图片,filter无影响
                Bitmap bitmap = Bitmap.createScaledBitmap(tempBitmap, desiredWidth, desiredHeight, true);
                tempBitmap.recycle(); // 释放Bitmap的native像素数组
                return bitmap;
            } else {
                return tempBitmap; // 如果没有缩放,那么不回收
            }
        }
        public static String getRealPathFromUri(Context context, Uri uri) {
            if (context == null || uri == null) {
                return null;
            }
            if ("file".equalsIgnoreCase(uri.getScheme())) {
                return getRealPathFromUri_Byfile(context, uri);
            } else if ("content".equalsIgnoreCase(uri.getScheme())) {
                return getRealPathFromUri_Api11To18(context, uri);
            }
            return null;
        }
    
    
    
    
        public static String getRealPathFromUri_Byfile(Context context,Uri uri){
            String uri2Str = uri.toString();
            String filePath = uri2Str.substring(uri2Str.indexOf(":") + 3);
            return filePath;
        }
        private static String getRealPathFromUri_Api11To18(Context context, Uri uri) {
            String filePath = null;
            String[] projection = { MediaStore.Images.Media.DATA };
    
            CursorLoader loader = new CursorLoader(context, uri, projection, null,
                    null, null);
            Cursor cursor = loader.loadInBackground();
    
            if (cursor != null) {
                cursor.moveToFirst();
                filePath = cursor.getString(cursor.getColumnIndex(projection[0]));
                cursor.close();
            }
            return filePath;
        }
    
    }

    然后我们需要一些配置

    在androidManifest中加入一个provider,写在appliation中

       <provider
                android:exported="false"
                android:grantUriPermissions="true"
                android:authorities="com.example.SportRecord.fileprovider"
                android:name="android.support.v4.content.FileProvider">
                <meta-data android:name="android.support.FILE_PROVIDER_PATHS"
                    android:resource="@xml/file_paths"/>
            </provider>

    然后右击res建立新目录xml文件夹然后创建一个file_paths.xml文件代码如下

    <?xml version="1.0" encoding="utf-8"?>
    <paths xmlns:android="http://schemas.android.com/apk/res/android">
        <external-path name="my_images" path=""></external-path>
    </paths>


    最后需要声明下权限androidManifest中

        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
        <!-- SD卡权限 -->

    接下来是服务器代码

    package org.java.servlet;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.java.write.WriteMorningWay;
    
    import sun.misc.BASE64Decoder;
    
    /**
     * Servlet implementation class getPhotoMes
     */
    @WebServlet("/getPhotoMes")
    public class getPhotoMes extends HttpServlet {
        private static final long serialVersionUID = 1L;
           
        /**
         * @see HttpServlet#HttpServlet()
         */
        public getPhotoMes() {
            super();
            // TODO Auto-generated constructor stub
        }
    
        /**
         * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
         */
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // TODO Auto-generated method stub
                request.setCharacterEncoding("utf-8");
                response.setCharacterEncoding("utf-8");
                response.setContentType("text/html");
                String photo = request.getParameter("photo");
                String user_account = request.getParameter("user_account");
                String point = request.getParameter("point");
                try {
         
                    // 对base64数据进行解码 生成 字节数组,不能直接用Base64.decode();进行解密
                    byte[] photoimg = new BASE64Decoder().decodeBuffer(photo);
                    for (int i = 0; i < photoimg.length; ++i) {
                        if (photoimg[i] < 0) {
                            // 调整异常数据
                            photoimg[i] += 256;
                        }
                    }
         
                    // byte[] photoimg = Base64.decode(photo);//此处不能用Base64.decode()方法解密,我调试时用此方法每次解密出的数据都比原数据大  所以用上面的函数进行解密,在网上直接拷贝的,花了好几个小时才找到这个错误(菜鸟不容易啊)
                    String savePath = this.getServletContext().getRealPath("/photoUpload/");
                    SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");//设置日期格式来命名图片
                    String string=df.format(new Date());
                    String photoname=string+user_account+".png";
                    System.out.print("length:"+savePath);
                    File file = new File(savePath, photoname);
                    if (!file.exists()) {
                        file.createNewFile();
                    }
                
                    FileOutputStream out = new FileOutputStream(file);
                    out.write(photoimg);
                    out.flush();
                    out.close();
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
        }
    
        /**
         * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
         */
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // TODO Auto-generated method stub
            doGet(request, response);
        }
    
    }
  • 相关阅读:
    Spring Boot学习笔记
    打造高效率的软件测试
    如何将测试结果在jenkins上发布
    如何在docker container中运行web自动化测试
    Jmeter中随机读取测试文件的内容
    如何提高UI自动化测试的质量
    mac系统上添加定时任务
    keypass口令管理实践
    GPG实践
    树的遍历
  • 原文地址:https://www.cnblogs.com/837634902why/p/12617173.html
Copyright © 2011-2022 走看看