Android--利用Bmob实现头像上传下载功能

声明: 本文使用Bmob作为云后台,实现一个简简单单的头像的选取、截取、上传、下载功能的实现。

编码环境:Android Studio2.1.1

运行环境:Miui8.6.8.18(安卓版本号6.0.1MMB29M)

手机型号:小米3

如有错误,欢迎指正!

准备工作:

添加必要的权限,Bmob的配置这里不再进行介绍。


    <!--相机的权限-->
    <uses-permission android:name="android.permission.CAMERA"/>
    <!--sd卡读取权限-->
    <!--获取sd卡写的权限,用于文件上传和下载-->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
    <!--允许联网 -->
    <uses-permission android:name="android.permission.INTERNET" />
    <!--获取GSM(2g)、WCDMA(联通3g)等网络状态的信息  -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <!--获取wifi网络状态的信息 -->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <!--保持CPU 运转,屏幕和键盘灯有可能是关闭的,用于文件上传和下载 -->
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <!--允许读取手机状态 用于创建BmobInstallation-->
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.RECEIVE_SMS" />
    <uses-permission android:name="android.permission.READ_SMS" />
    <uses-permission android:name="android.permission.GET_TASKS" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

  另外Bmob上传文件和下载文件需要okhttp库,所以需要导入okhttp和ok.io依赖,如果导入的是bmob.3.5这样的依赖的话,内含了ok.io依赖,所以只需要导入okhttp就好。下边是两个build.gradle文件

apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.3"
    //**兼容Android6.0系统所需,如果这句话报错,可在dependencies标签下使用compile 'cn.bmob.android:http-legacy:1.0'**
    useLibrary 'org.apache.http.legacy'

    defaultConfig {
        applicationId "com.example.no_clay.demolist"
        minSdkVersion 15
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.4.0'
    //以下SDK开发者请根据需要自行选择
    //bmob-sdk:Bmob的android sdk包,包含了Bmob的数据存储、文件等服务,以下是最新的bmob-sdk:
    compile 'cn.bmob.android:bmob-sdk:3.5.0'
    //如果你想应用能够兼容Android6.0,请添加此依赖(org.apache.http.legacy.jar)
    compile 'cn.bmob.android:http-legacy:1.0'
    //    compile 'com.squareup.okhttp:okhttp:2.4.0'
    //    compile 'com.squareup.okio:okio:1.5.0'
    compile files('libs/okhttp-2.4.0.jar')
}

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.1.2'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
        maven { url "https://raw.github.com/bmob/bmob-android-sdk/master" }
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}



Step1:选取图片:

选取图片通常有两种思路,一是利用相机进行拍照选取,而是利用SD卡中现成的图片设置为头像,首先贴一波代码,关于更加详细的“ android.intent.action.GET_CONTENT ”的使用,请查看博客 Android--利用相机或相册截取用户头像(解决了miui无法截取,以及部分机型拍照无返回Uri)
chooseUserImage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                menuWindow = new SelectPicPopupWindow(context, new
                        View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                menuWindow.dismiss();
                                switch (v.getId()) {
                                    case R.id.takePhotoBtn: {
                                        String state = Environment.getExternalStorageState();
                                        if (state.equals(Environment.MEDIA_MOUNTED)) {
                                            Intent getImageByCamera = new
                                                    Intent("android.media.action.IMAGE_CAPTURE");
                                            startActivityForResult(getImageByCamera,
                                                    REQUEST_CODE_CAPTURE_CAMEIA);
                                        } else {
                                            Toast.makeText(getApplicationContext(),
                                                    "请确认已经插入SD卡", Toast.LENGTH_LONG).show();
                                        }
                                        break;
                                    }
                                    case R.id.pickPhotoBtn:
                                        Intent intent = new Intent(Intent.ACTION_PICK);//从相册中选取图片
//                                        Intent intent = new Intent("android.intent.action.GET_CONTENT");//从相册/文件管理中选取图片
                                        intent.setType("image/*");//相片类型
                                        startActivityForResult(intent, REQUEST_CODE_PICK_IMAGE);
                                        break;
                                    case R.id.cancelBtn: {
                                        break;
                                    }
                                }
                            }
                        });
                menuWindow.showAtLocation(findViewById(R.id.mainLayout),
                        Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, 0);
            }
        });

在返回事件中处理返回的图片(详细请查看博客 Android--利用相机或相册截取用户头像(解决了miui无法截取,以及部分机型拍照无返回Uri)):

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        Uri imageUri;
        if (resultCode == RESULT_CANCELED) {
            Toast.makeText(context, "获取失败", Toast.LENGTH_SHORT).show();
            chooseUserImage.setImageDrawable(getResources().getDrawable(R.drawable.img_1));//预设的图片
        } else if (resultCode == RESULT_OK) {//选取成功后进行裁剪
            switch (requestCode) {
                case REQUEST_CODE_PICK_IMAGE: {
                    //从图库中选择图片作为头像
                    imageUri = data.getData();
                    reSizeImage(imageUri);
                    break;
                }
                case REQUEST_CODE_CAPTURE_CAMEIA: {
                    //使用相机获取头像
                    imageUri = data.getData();
                    Log.d(TAG, "onActivityResult: " + imageUri);
                    if (imageUri == null) {
                        //use bundle to get data
                        Bundle bundle = data.getExtras();
                        if (bundle != null) {
                            Bitmap bitMap = (Bitmap) bundle.get("data"); //get bitmap
                            imageUri = Uri.parse(MediaStore.Images.Media.
                                    insertImage(getContentResolver(), bitMap, null, null));
                            Log.d(TAG, "onActivityResult: bndle != null" + imageUri);
                            reSizeImage(imageUri);
                        } else {
                            Toast.makeText(getApplicationContext(), "Error", Toast.LENGTH_SHORT).show();
                        }
                    }
                    break;
                }
                case RESIZE_REQUEST_CODE: {
                    //剪切图片返回
                    Log.d(TAG, "onActivityResult: UserImage" + userImageUri);
                    if (userImageUri == null) {
                        Toast.makeText(context, "Error", Toast.LENGTH_SHORT).show();
                    } else {
                        showImage(userImageUri);
                    }
                    break;
                }
            }
        }
    }


Step2:截取图片

利用系统库 com.android.camera.action.CROP 进行截取图片的操作,代码如下:
   
private void reSizeImage(Uri uri) {//重新剪裁图片的大小
        File outputImage = new File(Environment.getExternalStorageDirectory(), "crop.jpg");
        try {
            if (outputImage.exists()) {
                outputImage.delete();
            }
            outputImage.createNewFile();
        } catch (Exception e) {
            e.printStackTrace();
        }//删除输出路径的文件,保证输出的Uri是一个具有路径的空文件,可以解决某些机型截取后返回为null
        userImageUri = Uri.fromFile(outputImage);
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setType("image");
        intent.setDataAndType(uri, "image/*");
        // 下面这个crop=true是设置在开启的Intent中设置显示的VIEW可裁剪
        intent.putExtra("crop", true);//允许剪切
        intent.putExtra("scale", true);//支持缩放
        intent.putExtra("scaleUpIfNeeded", true);// 去黑边
        // aspectX aspectY 是宽高的比例
        intent.putExtra("aspectX", 1);//输出是X方向的比例
        intent.putExtra("aspectY", 1);
        // outputX outputY 是裁剪图片宽高,切忌不要再改动下列数字,会卡死
        intent.putExtra("outputX", 500);//输出X方向的像素
        intent.putExtra("outputY", 500);//
        intent.putExtra("noFaceDetection", true);
        intent.putExtra("return-data", false);//设置为不返回数据
        /**
         * 此方法返回的图片只能是小图片(测试为高宽160px的图片)
         * 故将图片保存在Uri中,调用时将Uri转换为Bitmap,此方法还可解决miui系统不能return data的问题
         */
//        intent.putExtra("return-data", true);
//        intent.putExtra("output", Uri.fromFile(new File("/mnt/sdcard/temp")));//保存路径
        intent.putExtra(MediaStore.EXTRA_OUTPUT, userImageUri);//输出的Uri
        Log.d(TAG, "reSizeImage() called with: " + "uri = [" + userImageUri + "]");
        startActivityForResult(intent, RESIZE_REQUEST_CODE);
    }

Step3:上传头像

利用Bmob的云后台上传文件的方法是,首先将BmobFile上传到云端,然后通过保存表的方法,让文件与表数据之间产生联系,下面是表结构(帐号和头像):

package com.example.no_clay.demolist.ChooseImage;

import cn.bmob.v3.BmobObject;
import cn.bmob.v3.datatype.BmobFile;

/**
 * Created by 寒 on 2016/6/5.
 */
public class SignUserImage extends BmobObject {
    private String phoneNumber = null;
    private BmobFile image = null;

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    public BmobFile getImage() {
        return image;
    }

    public void setImage(BmobFile image) {
        this.image = image;
    }
}


上传功能的实现:


uploadButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (userImageUri == null) {
                    Toast.makeText(context, "还没有选择照片", Toast.LENGTH_SHORT);
                } else {
                    try {
                        Log.d(TAG, "onClick() called with: " + "uri = [" + userImageUri + "]");
                        final BmobFile bmobFile = new BmobFile(new File(new URI(userImageUri.toString())));
                        bmobFile.upload(new UploadFileListener() {
                            @Override
                            public void done(BmobException e) {
                                if (e == null) {
                                    signUserImage.setPhoneNumber("测试");
                                    signUserImage.setImage(bmobFile);
                                    signUserImage.save(new SaveListener<String>() {
                                        @Override
                                        public void done(String s, BmobException e) {
                                            if (e == null) {
                                                Toast.makeText(context, "上传成功", Toast.LENGTH_SHORT).show();
                                            } else {
                                                Toast.makeText(context, "上传失败", Toast.LENGTH_SHORT).show();
                                            }
                                        }
                                    });
                                    Log.d(TAG, "done() called with: " + "true");
                                } else {
                                    Log.d(TAG, "done() called with: " + "false");

                                }
                            }
                        });
                    } catch (URISyntaxException e) {
                        e.printStackTrace();
                    }
                }

            }
        });

Step4:下载功能的实现

这里设置一个下载按钮,和一个圆形的头像显示ImageView,下载的话,首先查表找到当前的用户,我这里为了方便,直接使用了ObjectId,可以采用其他查询表的方法进行查询,然后查看与之关联的头像是否为null,不为空则利用BmobFile的下载方法进行下载,这里分别利用BmobFile的两种下载方法实现,我个人推荐后一种,使用简便。代码如下:

downloadButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                BmobQuery<SignUserImage> query = new BmobQuery<SignUserImage>();
                query.getObject("5d5bb7a60c", new QueryListener<SignUserImage>() {
                    @Override
                    public void done(SignUserImage signUserImage, BmobException e) {
                        BmobFile bmobFile = signUserImage.getImage();
                        Log.d(TAG, "done() called with: " + "signUserImage = [" + signUserImage.getObjectId() + "]");
                        if (bmobFile != null) {//如果有头像
                            Log.d(TAG, "done() called with: " + "下载中...");
                            //方法一
//                            bmobFile.download(new DownloadFileListener() {
//                                @Override
//                                public void done(String s, BmobException e) {
//                                    Log.d(TAG, "done() called with: " + "s = [" + s + "]");
//                                    if(e == null){
//                                        Message message = new Message();
//                                        message.what = DOWNLOAD_IMAGE_MSG;
//                                        message.obj = s;
//                                        handler.sendMessage(message);
//                                    }
//                                }
//
//                                @Override
//                                public void onProgress(Integer integer, long l) {
//                                    Log.d(TAG, "onProgress() called with: " + "integer = [" + integer + "], l = [" + l + "]");
//                                }
//                            });
                            //方法二
                            bmobFile.download(new File(Environment.
                                            getExternalStorageDirectory() + "/userImage.jpg"),//设置保存的路径
                                    new DownloadFileListener() {
                                        @Override
                                        public void done(String s, BmobException e) {
                                            Log.d(TAG, "done() called with: " + "s = [" + s + "]");
                                            if (e == null) {
                                                Message message = new Message();
                                                message.what = DOWNLOAD_IMAGE_MSG;
                                                message.obj = s;
                                                handler.sendMessage(message);
                                            }
                                        }

                                        @Override
                                        public void onProgress(Integer integer, long l) {
                                            Log.d(TAG, "onProgress() called with: " + "integer = [" + integer + "], l = [" + l + "]");
                                        }
                                    });

                        }
                    }
                });
            }
        });
    }


Step5:将下载的图片显示出来

首先贴上一个自定义的圆形ImageView,我们上边设置正方形的剪切范围,就是为了显示圆形的头像,这里现贴出圆形的自定义ImageView:
<span style="font-size:18px;">package com.example.no_clay.demolist.ChooseImage;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;

/**
 * Created by 82661 on 2016/8/31.
 */
public class MyCircleImageView extends ImageView {
    private Paint paint;

    public MyCircleImageView(Context context) {
        this(context, null);
    }

    public MyCircleImageView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyCircleImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        paint = new Paint();

    }

    /**
     * 绘制圆形图片
     *
     * @author caizhiming
     */
    @Override
    protected void onDraw(Canvas canvas) {

        Drawable drawable = getDrawable();
        if (null != drawable) {
            Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
            Bitmap b = getCircleBitmap(bitmap, 14);
            final Rect rectSrc = new Rect(0, 0, b.getWidth(), b.getHeight());
            final Rect rectDest = new Rect(0, 0, getWidth(), getHeight());
            paint.reset();
            canvas.drawBitmap(b, rectSrc, rectDest, paint);

        } else {
            super.onDraw(canvas);
        }
    }

    /**
     * 获取圆形图片方法
     *
     * @param bitmap
     * @param pixels
     * @return Bitmap
     * @author caizhiming
     */
    private Bitmap getCircleBitmap(Bitmap bitmap, int pixels) {
        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
                bitmap.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(output);
        final int color = 0xff424242;
        final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
        paint.setAntiAlias(true);
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(color);
        int x = bitmap.getWidth();

        canvas.drawCircle(x / 2, x / 2, x / 2, paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(bitmap, rect, rect, paint);
        return output;
    }
}
</span>


处理下载的头像,只需要在Handler里边将路径设置转换为Uri设置给ImageView就可以:

 Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case DOWNLOAD_IMAGE_MSG: {
                    String path = (String) msg.obj;
                    showUserImage.setImageURI(Uri.parse(path));
                    Toast.makeText(context, "下载头像成功", Toast.LENGTH_SHORT).show();
                    break;
                }
            }
        }
    };

这里是最终的效果图

   

具体的代码可以到这里下载
几个小Demo的合集的下载
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值