欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android头像上传功能的实现代码(获取头像加剪切)

程序员文章站 2023-12-10 14:00:04
因为项目中需要用到头像上传的功能,所以就下个ddmo先来实现下。 demo我是类似仿微信的,在一个gridview中展示所有的图片,其中第一个item可以去照相;获取到图...

因为项目中需要用到头像上传的功能,所以就下个ddmo先来实现下。

demo我是类似仿微信的,在一个gridview中展示所有的图片,其中第一个item可以去照相;获取到图片后再进行剪切。

图片的剪切是从网上找的感觉不错就用,暂时也没有测试。

获取图片可以用:https://github.com/lovetuzitong/multiimageselector来实现

这里的圆形图像是用https://github.com/hdodenhof/circleimageview来实现的

demo写的比较粗糙,效果只是在4.4的手机和7.0的模拟器跑了一遍,所以可能会出现问题的。

如下是demo的效果图:

Android头像上传功能的实现代码(获取头像加剪切)

Android头像上传功能的实现代码(获取头像加剪切)

如下是选择图片中的代码

通过loadermanager来获取到所有的图片,然后第一个进行拍照的处理

package com.item.demo.photo.activity;
import android.manifest;
import android.app.loadermanager;
import android.content.contentresolver;
import android.content.context;
import android.content.cursorloader;
import android.content.intent;
import android.content.loader;
import android.content.pm.packagemanager;
import android.database.cursor;
import android.net.uri;
import android.os.build;
import android.os.environment;
import android.provider.mediastore;
import android.support.annotation.nonnull;
import android.support.v4.content.contextcompat;
import android.support.v4.content.fileprovider;
import android.support.v7.app.appcompatactivity;
import android.os.bundle;
import android.text.textutils;
import android.util.log;
import android.view.view;
import android.widget.adapterview;
import android.widget.gridview;
import android.widget.imageview;
import com.item.demo.photo.buildconfig;
import com.item.demo.photo.r;
import com.item.demo.photo.adapter.myphotoadapter;
import com.item.demo.photo.uilts.image;
import java.io.file;
import java.util.arraylist;
import java.util.list;
/**
 * 图片选择界面
 */
public class myphotoactivity extends appcompatactivity {
  private static final int request_capture = 100;
  //private static final int request_pick = 101;
  private static final int request_crop_photo = 102;
  public static final int finsh_result = 104;//截图后的返回
  private static final int loader_id = 0x0100;
  private loadcallback mload = new loadcallback();
  private myphotoadapter madapter;
  private list<image> images = new arraylist<>();
  //调用照相机返回图片文件
  private file tempfile;
  private static final int min_image_file_size = 10 * 1024; // 最小的图片大小
  @override
  protected void oncreate(bundle savedinstancestate) {
    super.oncreate(savedinstancestate);
    setcontentview(r.layout.activity_my_photo);
    gridview gv_photo = (gridview)findviewbyid(r.id.gv_photo);
    imageview img_back = (imageview)findviewbyid(r.id.iv_back);
    images.add(new image());
    madapter = new myphotoadapter(this,images);
    gv_photo.setadapter(madapter);
    gv_photo.setonitemclicklistener(new adapterview.onitemclicklistener() {
      @override
      public void onitemclick(adapterview<?> adapterview, view view, int i, long l) {
        if(i == 0){
          //第一个就去照相
          if(haspermission(new string[]{manifest.permission.camera,manifest.permission.write_external_storage})){
            gotocamera();
          }else {
            requestpermission(0x02,new string[]{manifest.permission.camera,manifest.permission.write_external_storage});
          }
        }else {
          //这里点击获取到图片地址然后裁剪
          gotoclipactivity(uri.parse(images.get(i).getpath()));
        }
      }
    });
    img_back.setonclicklistener(new view.onclicklistener() {
      @override
      public void onclick(view view) {
        finish();
      }
    });
  }
  @override
  protected void onstart() {
    super.onstart();
    if(haspermission(new string[]{manifest.permission.read_external_storage})){
      getloadermanager().initloader(loader_id,null,mload);
    }else {
      requestpermission(0x01,new string[]{manifest.permission.read_external_storage});
    }
  }
  private class loadcallback implements loadermanager.loadercallbacks<cursor>{
    private final string[] image_projection = new string[]{
        mediastore.images.media._id,//id
        mediastore.images.media.data,//图片路径
        mediastore.images.media.date_added//图片的创建时间
    };
    @override
    public loader<cursor> oncreateloader(int id, bundle args) {
      //创建一个loader
      if(id == loader_id){
        //如果是我们的id则进行初始化
        return new cursorloader(getbasecontext(),
            mediastore.images.media.external_content_uri,
            image_projection,
            null,
            null,
            image_projection[2] + " desc");
      }
      return null;
    }
    @override
    public void onloadfinished(loader<cursor> loader, cursor data) {
      //当loader加载完成时
      list<image> images = new arraylist<>();
      //判断是否有数据
      if(data != null){
        int count = data.getcount();
        if(count > 0){
          data.movetofirst();
          // 得到对应的列的index坐标
          int indexid = data.getcolumnindexorthrow(image_projection[0]);
          int indexpath = data.getcolumnindexorthrow(image_projection[1]);
          int indexdate = data.getcolumnindexorthrow(image_projection[2]);
          do {
            // 循环读取,直到没有下一条数据
            int id = data.getint(indexid);
            string path = data.getstring(indexpath);
            long datetime = data.getlong(indexdate);
            file file = new file(path);
            if (!file.exists() || file.length() < min_image_file_size) {
              // 如果没有图片,或者图片大小太小,则跳过
              continue;
            }
            // 添加一条新的数据
            image image = new image();
            image.setid(id);
            image.setpath(path);
            image.setdate(datetime);
            images.add(image);
          } while (data.movetonext());
        }
      }
      updatesource(images);
    }
    @override
    public void onloaderreset(loader<cursor> loader) {
      updatesource(null);
    }
  }
  /**
   * 通知adapter数据更改的方法
   * @param images 新的数据
   */
  private void updatesource(list<image> images){
    this.images.clear();
    this.images.add(new image());
    if(images == null || images.size() == 0) return;
    this.images.addall(images);
    madapter.notifydatasetchanged();
  }
  /**
   *权限的返回
   */
  @override
  public void onrequestpermissionsresult(int requestcode, @nonnull string[] permissions, @nonnull int[] grantresults) {
    super.onrequestpermissionsresult(requestcode, permissions, grantresults);
    switch(requestcode){
      case 0x02:
        if(grantresults.length > 0 && grantresults[0] == packagemanager.permission_granted){
          gotocamera();
        }
        break;
      case 0x01:
        if(grantresults.length > 0 && grantresults[0] == packagemanager.permission_granted){
          getloadermanager().initloader(loader_id,null,mload);
        }
    }
  }
  @override
  protected void onactivityresult(int requestcode, int resultcode, intent data) {
    super.onactivityresult(requestcode, resultcode, data);
    switch (requestcode){
      case request_capture://系统相机返回
        if(resultcode == result_ok){
          log.d("jiejie","--------相机---------" + uri.fromfile(tempfile).tostring());
          log.d("jiejie","--------path----------" + getrealfilepathfromuri(myphotoactivity.this,uri.fromfile(tempfile)));
          gotoclipactivity(uri.fromfile(tempfile));
        }
        break;
      case request_crop_photo:
        if(resultcode == result_ok){
          if(data != null){
            uri uri = data.getdata();
            log.d("jiejie","-------------" + data.getdata().getpath());
            string cropimagepath = getrealfilepathfromuri(myphotoactivity.this,uri);
            log.d("jiejie","------crop--------" + cropimagepath);
            intent intent = new intent();
            intent.putextra("image",cropimagepath);
            setresult(finsh_result,intent);
            myphotoactivity.this.finish();
          }
        }
        break;
    }
  }
  /**
   * 跳转到系统照相机
   */
  private void gotocamera(){
    string sdstate = environment.getexternalstoragestate();
    //判断sd卡是否存在
    if(sdstate.equals(environment.media_mounted)){
      tempfile = new file(checkdirpath(environment.getexternalstoragedirectory().getpath()+ "/image/"), system.currenttimemillis() + ".jpg");
      //隐式的打开调用系统相册
      intent intent = new intent(mediastore.action_image_capture);
      if(build.version.sdk_int >= build.version_codes.n){
        intent.setflags(intent.flag_grant_write_uri_permission);
        //如果是7.0及以上的系统使用fileprovider的方式创建一个uri
        uri contenturi = fileprovider.geturiforfile(myphotoactivity.this, buildconfig.application_id + ".fileprovider", tempfile);
        intent.putextra(mediastore.extra_output, contenturi);
      }else {
        intent.putextra(mediastore.extra_output, uri.fromfile(tempfile));
      }
      startactivityforresult(intent,request_capture);
    }
  }
  /**
   * 打开截图的界面
   * @param uri
   */
  private void gotoclipactivity(uri uri){
    if(uri == null){
      return;
    }
    intent intent = new intent(this,clipimageactivity.class);
    intent.putextra("type",1);
    intent.setdata(uri);
    startactivityforresult(intent,request_crop_photo);
  }
  /**
   * 检查文件是否存在
   */
  private static string checkdirpath(string dirpath) {
    if (textutils.isempty(dirpath)) {
      return "";
    }
    file dir = new file(dirpath);
    if (!dir.exists()) {
      dir.mkdirs();
    }
    return dirpath;
  }
  /**
   * 判断是否有指定的权限
   */
  public boolean haspermission(string... permissions) {
    for (string permisson : permissions) {
      if (contextcompat.checkselfpermission(this, permisson)
          != packagemanager.permission_granted) {
        return false;
      }
    }
    return true;
  }
  /**
   * 申请指定的权限.
   */
  public void requestpermission(int code, string... permissions) {
    if (build.version.sdk_int >= 23) {
      requestpermissions(permissions, code);
    }
  }
  /**
   * 根据uri返回文件绝对路径
   * 兼容了file:///开头的 和 content://开头的情况
   */
  public static string getrealfilepathfromuri(final context context, final uri uri) {
    if (null == uri) return null;
    final string scheme = uri.getscheme();
    string data = null;
    if (scheme == null)
      data = uri.getpath();
    else if (contentresolver.scheme_file.equals(scheme)) {
      data = uri.getpath();
    } else if (contentresolver.scheme_content.equals(scheme)) {
      cursor cursor = context.getcontentresolver().query(uri, new string[]{mediastore.images.imagecolumns.data}, null, null, null);
      if (null != cursor) {
        if (cursor.movetofirst()) {
          int index = cursor.getcolumnindex(mediastore.images.imagecolumns.data);
          if (index > -1) {
            data = cursor.getstring(index);
          }
        }
        cursor.close();
      }
    }
    return data;
  }
}

其中处理动态的权限还需要添加7.0的照相处理

在清单文件中加如下配置:

  <provider
      android:name="android.support.v4.content.fileprovider"
      android:authorities="com.item.demo.photo.fileprovider"
      android:granturipermissions="true"
      android:exported="false">
      <meta-data
        android:name="android.support.file_provider_paths"
        android:resource="@xml/file_paths" />
    </provider>

图片的剪切

package com.item.demo.photo.activity;
import android.content.intent;
import android.graphics.bitmap;
import android.net.uri;
import android.support.v7.app.appcompatactivity;
import android.os.bundle;
import android.util.log;
import android.view.view;
import android.widget.imageview;
import android.widget.textview;
import com.item.demo.photo.r;
import com.item.demo.photo.view.clipviewlayout;
import java.io.file;
import java.io.ioexception;
import java.io.outputstream;
/**
 * 图片剪切
 */
public class clipimageactivity extends appcompatactivity implements view.onclicklistener {
  private clipviewlayout clipviewlayout1;
  private clipviewlayout clipviewlayout2;
  private imageview back;
  private textview tv_ok;
  //类别 1:圆形 2:方形
  private int type;
  @override
  protected void oncreate(bundle savedinstancestate) {
    super.oncreate(savedinstancestate);
    setcontentview(r.layout.activity_clip_image);
    type = getintent().getintextra("type",1);
    initview();
  }
  private void initview() {
    clipviewlayout1 = (clipviewlayout)findviewbyid(r.id.clipviewlayout1);
    clipviewlayout2 = (clipviewlayout)findviewbyid(r.id.clipviewlayout2);
    back = (imageview)findviewbyid(r.id.iv_back);
    tv_ok = (textview)findviewbyid(r.id.tv_ok);
    back.setonclicklistener(this);
    tv_ok.setonclicklistener(this);
  }
  @override
  protected void onresume() {
    super.onresume();
    if(type == 1){
      clipviewlayout1.setvisibility(view.visible);
      clipviewlayout2.setvisibility(view.gone);
      //设置图片资源
      clipviewlayout1.setimagesrc(getintent().getdata());
    }else {
      clipviewlayout2.setvisibility(view.visible);
      clipviewlayout1.setvisibility(view.gone);
      clipviewlayout2.setimagesrc(getintent().getdata());
    }
  }
  @override
  public void onclick(view view) {
    switch (view.getid()){
      case r.id.iv_back:
        finish();
        break;
      case r.id.tv_ok:
        generateuriandreturn();
        break;
    }
  }
  /**
   * 生成uri并且通过setresult返回给打开的activity
   */
  private void generateuriandreturn() {
    //调用返回剪切图
    bitmap zoomedcropbitmap;
    if (type == 1) {
      zoomedcropbitmap = clipviewlayout1.clip();
    } else {
      zoomedcropbitmap = clipviewlayout2.clip();
    }
    if (zoomedcropbitmap == null) {
      log.e("android", "zoomedcropbitmap == null");
      return;
    }
    uri msaveuri = uri.fromfile(new file(getcachedir(), "cropped_" + system.currenttimemillis() + ".jpg"));
    if (msaveuri != null) {
      outputstream outputstream = null;
      try {
        outputstream = getcontentresolver().openoutputstream(msaveuri);
        if (outputstream != null) {
          zoomedcropbitmap.compress(bitmap.compressformat.jpeg, 90, outputstream);
        }
      } catch (ioexception ex) {
        log.e("android", "cannot open file: " + msaveuri, ex);
      } finally {
        if (outputstream != null) {
          try {
            outputstream.close();
          } catch (ioexception e) {
            e.printstacktrace();
          }
        }
      }
      intent intent = new intent();
      intent.setdata(msaveuri);
      setresult(result_ok, intent);
      finish();
    }
  }
}

总结

以上所述是小编给大家介绍的android头像上传功能的实现代码(获取头像加剪切),希望对大家有所帮助