Android头像上传功能的实现代码(获取头像加剪切)
程序员文章站
2023-12-16 11:37:58
因为项目中需要用到头像上传的功能,所以就下个ddmo先来实现下。
demo我是类似仿微信的,在一个gridview中展示所有的图片,其中第一个item可以去照相;获取到图...
因为项目中需要用到头像上传的功能,所以就下个ddmo先来实现下。
demo我是类似仿微信的,在一个gridview中展示所有的图片,其中第一个item可以去照相;获取到图片后再进行剪切。
图片的剪切是从网上找的感觉不错就用,暂时也没有测试。
获取图片可以用:https://github.com/lovetuzitong/multiimageselector来实现
这里的圆形图像是用https://github.com/hdodenhof/circleimageview来实现的
demo写的比较粗糙,效果只是在4.4的手机和7.0的模拟器跑了一遍,所以可能会出现问题的。
如下是demo的效果图:
如下是选择图片中的代码
通过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头像上传功能的实现代码(获取头像加剪切),希望对大家有所帮助