您好,欢迎来到源码搜藏网!分享精神,快乐你我!
[加入VIP] 设为首页 | 收藏本站 | 网站地图 | Sitemap | TAG标签
  • 首 页
  • 在线工具
  • jquery手册
  • 当前位置:首页 > 安卓源码 > 技术博客 >

    android图片上传功能实现

    时间:2017-02-22 00:03 来源:互联网 作者:源码搜藏 浏览:收藏 挑错 推荐 打印

    先看一下效果图: (一)头像裁切、上传服务器 (效果图) 一般都是有圆形显示头像的,这里我自定义了一个ImageView,页面很干净但是看着很上档次吧! 点击头像从底部弹出一个对话框,提示用户头像来自相机或者相册,这都是常规流程。 上传完成后默认的程序

    先看一下效果图:

    (一)头像裁切、上传服务器(效果图)

    一般都是有圆形显示头像的,这里我自定义了一个ImageView,页面很干净但是看着很上档次吧!

    点击头像从底部弹出一个对话框,提示用户头像来自相机或者相册,这都是常规流程。

    上传完成后默认的“程序员头像”换成了萌妹子


    android图片上传功能实现
    android图片上传功能实现
    android图片上传功能实现

    (二)普通图片上传服务器(效果图)

    模仿QQ空间发动态的布局随意捏造一个界面出来

    点击添加图片从底部弹出一个对话框,提示用户图片来自相机或者相册,这也都是常规流程。

    上传过程中,有可能图片很大,显示一个进度圈(其实头像上传也有,只是文件小,还没显示就上传完成了)

    上传完成后把刚才的照片亮出来显示到按钮的地方,当然大家根据需要还可以自己扩展(比如长按抖动出现删除、继续添加N张等等)。

    android图片上传功能实现
    android图片上传功能实现
    android图片上传功能实现
    android图片上传功能实现

    下面简单铺一下代码:

    (一)头像裁切、上传服务器(代码)

    这里上边的按钮是头像的点击事件,弹出底部的头像选择框,下边的按钮跳到下个页面,进行原图上传。

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.avatarImg:// 更换头像点击事件
            menuWindow = new SelectPicPopupWindow(mContext, itemsOnClick); 
            menuWindow.showAtLocation(findViewById(R.id.mainLayout),
                    Gravity.BOTTOM|Gravity.CENTER_HORIZONTAL, 0, 0);
            break;
        case R.id.loginBtn://登录按钮跳转事件
            startActivity(new Intent(mContext, UploadActivity.class));
            break;
     
        default:
            break;
        }
    }
    弹出窗绑定一个按钮事件
    //为弹出窗口实现监听类 
    private OnClickListener itemsOnClick = new OnClickListener() {
        @Override
        public void onClick(View v) {
            menuWindow.dismiss();
            switch (v.getId()) {
            // 拍照
            case R.id.takePhotoBtn:
                Intent takeIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                //下面这句指定调用相机拍照后的照片存储的路径
                takeIntent.putExtra(MediaStore.EXTRA_OUTPUT,
                        Uri.fromFile(new File(Environment.getExternalStorageDirectory(), IMAGE_FILE_NAME)));
                startActivityForResult(takeIntent, REQUESTCODE_TAKE);
                break;
            // 相册选择图片
            case R.id.pickPhotoBtn:
                Intent pickIntent = new Intent(Intent.ACTION_PICK, null);
                // 如果朋友们要限制上传到服务器的图片类型时可以直接写如:image/jpeg 、 image/png等的类型
                pickIntent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, image/*);
                startActivityForResult(pickIntent, REQUESTCODE_PICK);
                break;
            default:
                break;
            }
        }
    };

    为图像选取返回的接收处理

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        
        switch (requestCode) {
        case REQUESTCODE_PICK:// 直接从相册获取
            try {
                startPhotoZoom(data.getData());
            } catch (NullPointerException e) {
                e.printStackTrace();// 用户点击取消操作
            }
            break;
        case REQUESTCODE_TAKE:// 调用相机拍照
            File temp = new File(Environment.getExternalStorageDirectory() + / + IMAGE_FILE_NAME);
            startPhotoZoom(Uri.fromFile(temp));
            break;
        case REQUESTCODE_CUTTING:// 取得裁剪后的图片
            if (data != null) {
                setPicToView(data);
            }
            break;
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    把图片显示出来,然后上传

    /**
     * 裁剪图片方法实现
     * @param uri
     */
    public void startPhotoZoom(Uri uri) {
        Intent intent = new Intent(com.android.camera.action.CROP);
        intent.setDataAndType(uri, image/*);
        // crop=true是设置在开启的Intent中设置显示的VIEW可裁剪
        intent.putExtra(crop, true);
        // aspectX aspectY 是宽高的比例
        intent.putExtra(aspectX, 1);
        intent.putExtra(aspectY, 1);
        // outputX outputY 是裁剪图片宽高
        intent.putExtra(outputX, 300);
        intent.putExtra(outputY, 300);
        intent.putExtra(return-data, true);
        startActivityForResult(intent, REQUESTCODE_CUTTING);
    }
        
    /**
     * 保存裁剪之后的图片数据
     * @param picdata
     */
    private void setPicToView(Intent picdata) {
        Bundle extras = picdata.getExtras();
        if (extras != null) {
            // 取得SDCard图片路径做显示
            Bitmap photo = extras.getParcelable(data);
            Drawable drawable = new BitmapDrawable(null, photo);
            urlpath = FileUtil.saveFile(mContext, temphead.jpg, photo);
            avatarImg.setImageDrawable(drawable);
     
            // 新线程后台上传服务端
            pd = ProgressDialog.show(mContext, null, 正在上传图片,请稍候...);
            new Thread(uploadImageRunnable).start();
        }
    }
     
    /**
     * 使用HttpUrlConnection模拟post表单进行文件
     * 上传平时很少使用,比较麻烦
     * 原理是: 分析文件上传的数据格式,然后根据格式构造相应的发送给服务器的字符串。
     */
    Runnable uploadImageRunnable = new Runnable() {
        @Override
        public void run() {
            
            if(TextUtils.isEmpty(imgUrl)){
                Toast.makeText(mContext, 还没有设置上传服务器的路径!, Toast.LENGTH_SHORT).show();
                return;
            }
            
            Map<string, string=""> textParams = new HashMap<string, string="">();
            Map<string, file=""> fileparams = new HashMap<string, file="">();
            
            try {
                // 创建一个URL对象
                URL url = new URL(imgUrl);
                textParams = new HashMap<string, string="">();
                fileparams = new HashMap<string, file="">();
                // 要上传的图片文件
                File file = new File(urlpath);
                fileparams.put(image, file);
                // 利用HttpURLConnection对象从网络中获取网页数据
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                // 设置连接超时(记得设置连接超时,如果网络不好,Android系统在超过默认时间会收回资源中断操作)
                conn.setConnectTimeout(5000);
                // 设置允许输出(发送POST请求必须设置允许输出)
                conn.setDoOutput(true);
                // 设置使用POST的方式发送
                conn.setRequestMethod(POST);
                // 设置不使用缓存(容易出现问题)
                conn.setUseCaches(false);
                conn.setRequestProperty(Charset, UTF-8);//设置编码  
                // 在开始用HttpURLConnection对象的setRequestProperty()设置,就是生成HTML文件头
                conn.setRequestProperty(ser-Agent, Fiddler);
                // 设置contentType
                conn.setRequestProperty(Content-Type, multipart/form-data; boundary= + NetUtil.BOUNDARY);
                OutputStream os = conn.getOutputStream();
                DataOutputStream ds = new DataOutputStream(os);
                NetUtil.writeStringParams(textParams, ds);
                NetUtil.writeFileParams(fileparams, ds);
                NetUtil.paramsEnd(ds);
                // 对文件流操作完,要记得及时关闭
                os.close();
                // 服务器返回的响应吗
                int code = conn.getResponseCode(); // 从Internet获取网页,发送请求,将网页以流的形式读回来
                // 对响应码进行判断
                if (code == 200) {// 返回的响应码200,是成功
                    // 得到网络返回的输入流
                    InputStream is = conn.getInputStream();
                    resultStr = NetUtil.readString(is);
                } else {
                    Toast.makeText(mContext, 请求URL失败!, Toast.LENGTH_SHORT).show();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            handler.sendEmptyMessage(0);// 执行耗时的方法之后发送消给handler
        }
    };
     
    Handler handler = new Handler(new Handler.Callback() {
        
        @Override
        public boolean handleMessage(Message msg) {
            switch (msg.what) {
            case 0:
                pd.dismiss();
                
                try {
                    // 返回数据示例,根据需求和后台数据灵活处理
                    // {status:1,statusMessage:上传成功,imageUrl:http://120.24.219.49/726287_temphead.jpg}
                    JSONObject jsonObject = new JSONObject(resultStr);
                    
                    // 服务端以字符串“1”作为操作成功标记
                    if (jsonObject.optString(status).equals(1)) {
                        BitmapFactory.Options option = new BitmapFactory.Options();
                        // 压缩图片:表示缩略图大小为原始图片大小的几分之一,1为原图,3为三分之一
                        option.inSampleSize = 1;
                        
                        // 服务端返回的JsonObject对象中提取到图片的网络URL路径
                        String imageUrl = jsonObject.optString(imageUrl);
                        Toast.makeText(mContext, imageUrl, Toast.LENGTH_SHORT).show();
                    }else{
                        Toast.makeText(mContext, jsonObject.optString(statusMessage), Toast.LENGTH_SHORT).show();
                    }
                    
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                
                break;
                
            default:
                break;
            }
            return false;
        }
    });</string,></string,></string,></string,></string,></string,>

    (二)普通图片上传服务器(代码)

    直接从这里开始,和头像那里基本没什么区别,我把拍照什么的单独抽出了方法,思路更清晰

    //为弹出窗口实现监听类 
    private OnClickListener itemsOnClick = new OnClickListener() {
        @Override
        public void onClick(View v) {
            // 隐藏弹出窗口
            menuWindow.dismiss();
            
            switch (v.getId()) {
            case R.id.takePhotoBtn:// 拍照
                takePhoto();
                break;
            case R.id.pickPhotoBtn:// 相册选择图片
                pickPhoto();
                break;
            case R.id.cancelBtn:// 取消
                break;
            default:
                break;
            }
        }
    };
     
    ;
    /**
     * 拍照获取图片
     */
    private void takePhoto() {
        // 执行拍照前,应该先判断SD卡是否存在
        String SDState = Environment.getExternalStorageState();
        if (SDState.equals(Environment.MEDIA_MOUNTED)) {
     
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            /***
             * 需要说明一下,以下操作使用照相机拍照,拍照后的图片会存放在相册中的
             * 这里使用的这种方式有一个好处就是获取的图片是拍照后的原图
             * 如果不使用ContentValues存放照片路径的话,拍照后获取的图片为缩略图不清晰
             */
            ContentValues values = new ContentValues();
            photoUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
            intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, photoUri);
            startActivityForResult(intent, SELECT_PIC_BY_TACK_PHOTO);
        } else {
            Toast.makeText(this, 内存卡不存在, Toast.LENGTH_LONG).show();
        }
    }
     
    /***
     * 从相册中取图片
     */
    private void pickPhoto() {
        Intent intent = new Intent();
        // 如果要限制上传到服务器的图片类型时可以直接写如:image/jpeg 、 image/png等的类型
        intent.setType(image/*);
        intent.setAction(Intent.ACTION_GET_CONTENT);
        startActivityForResult(intent, SELECT_PIC_BY_PICK_PHOTO);
    }

    处理一下图片选取的页面回调

    @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            // 点击取消按钮
            if(resultCode == RESULT_CANCELED){
                return;
            }
            
            // 可以使用同一个方法,这里分开写为了防止以后扩展不同的需求
            switch (requestCode) {
            case SELECT_PIC_BY_PICK_PHOTO:// 如果是直接从相册获取
                doPhoto(requestCode, data);
                break;
            case SELECT_PIC_BY_TACK_PHOTO:// 如果是调用相机拍照时
                doPhoto(requestCode, data);
                break;
            }
            super.onActivityResult(requestCode, resultCode, data);
        }

    接下来就是显示图片和上传服务器了,上传和头像是同一个流程,只是不进行裁切

    /**
     * 选择图片后,获取图片的路径
     *
     * @param requestCode
     * @param data