
Android 头像上传至服务器 (OkHttpClient请求)
发布日期:2021-05-06 03:14:51
浏览次数:30
分类:原创文章
本文共 14182 字,大约阅读时间需要 47 分钟。
Android 头像上传至服务器 (OkHttpClient请求)
1.导入本章内容要使用的第三方库
implementation 'com.squareup.okhttp3:okhttp:3.12.1' debugImplementation 'com.squareup.okhttp3:logging-interceptor:3.12.1' implementation 'com.google.code.gson:gson:2.8.5' implementation 'com.github.bumptech.glide:glide:4.9.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0' implementation 'de.hdodenhof:circleimageview:2.1.0'
2.添加权限
<uses-permission android:name="android.permission.INTERNET" /> <!-- 读写获取网络文件的权限 --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
3.界面布局
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity"> <de.hdodenhof.circleimageview.CircleImageView android:id="@+id/c1" android:layout_width="80dp" android:layout_height="100dp" android:layout_gravity="center" android:src="@mipmap/logo"> </de.hdodenhof.circleimageview.CircleImageView> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:textSize="20sp" android:layout_marginTop="10dp" android:text="点击头像更换"/></LinearLayout>
界面展示
4.点击头像监听内容
采用弹出底部菜单从而进行选择图片上传样式
界面展示
界面布局代码
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#fff"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <ImageView android:layout_width="35dp" android:layout_height="50dp" android:src="@mipmap/a1" android:layout_marginLeft="50dp"/> <TextView android:id="@+id/tv_take_photo" android:layout_width="match_parent" android:layout_height="50dp" android:layout_marginRight="50dp" android:text="拍摄" android:gravity="center" android:textSize="16sp" android:textColor="@android:color/background_dark"/> </LinearLayout> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="@android:color/darker_gray"/><LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <ImageView android:layout_width="35dp" android:layout_height="50dp" android:src="@mipmap/a2" android:layout_marginLeft="50dp"/> <TextView android:id="@+id/tv_take_pic" android:layout_width="match_parent" android:layout_height="50dp" android:text="从手机相册选择" android:layout_marginRight="50dp" android:gravity="center" android:textSize="16sp" android:textColor="@android:color/background_dark"/></LinearLayout> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="@android:color/darker_gray"/> <TextView android:id="@+id/tv_cancel" android:layout_width="match_parent" android:layout_height="50dp" android:text="取消" android:gravity="center" android:textSize="16sp" android:textColor="@android:color/background_dark"/></LinearLayout>
(1)style.xml文件添加样式
<style name="DialogTheme" parent="@android:style/Theme.Dialog"> <!-- 边框 --> <item name="android:windowFrame">@null</item> <!-- 是否浮现在activity之上 --> <item name="android:windowIsFloating">true</item> <!-- 半透明 --> <item name="android:windowIsTranslucent">true</item> <!-- 无标题 --> <item name="android:windowNoTitle">true</item> <item name="android:background">@android:color/transparent</item> <!-- 背景透明 --> <item name="android:windowBackground">@android:color/transparent</item> <!-- 模糊 --> <item name="android:backgroundDimEnabled">true</item> <!-- 遮罩层 --> <item name="android:backgroundDimAmount">0.5</item> </style> <style name="main_menu_animStyle"> windowEnterAnimation 进入的动画 代码里面 <item name="android:windowEnterAnimation">@anim/dialog_in_anim</item> <item name="android:windowExitAnimation">@anim/dialog_out_anim</item> </style>
(2)添加动画
在res文件下创建命名为anim的文件
第一个动画文件命名为dialog_in_anim.xml
<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android" > <translate android:duration="500" android:fromXDelta="0" android:fromYDelta="1000" android:toXDelta="0" android:toYDelta="0" /></set>
第二个动画文件命名为dialog_out_anim.xml
<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android" > <translate android:duration="500" android:fromXDelta="0" android:fromYDelta="0" android:toXDelta="0" android:toYDelta="1000" /></set>
(3)功能实现
绑定ID,并实现监听器
底部菜单核心代码
private void showBottomDialog(){ //1、使用Dialog、设置style final Dialog dialog = new Dialog(this,R.style.DialogTheme); //2、设置布局 View view = View.inflate(this,R.layout.dialog_custom_layout,null); dialog.setContentView(view); Window window = dialog.getWindow(); //设置弹出位置 window.setGravity(Gravity.BOTTOM); //设置弹出动画 window.setWindowAnimations(R.style.main_menu_animStyle); //设置对话框大小 window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT); dialog.show(); dialog.findViewById(R.id.tv_take_photo).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { } }); dialog.findViewById(R.id.tv_take_pic).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { } }); dialog.findViewById(R.id.tv_cancel).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { dialog.dismiss(); } }); }
完成,下面开始实现图片上传到服务器
5.图片上传到服务器
定义
如果安卓版本为7.0以上,需要添加下面的代码避免打开相机报错
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) private void initPhotoError() { // android 7.0系统解决拍照的问题 StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder(); StrictMode.setVmPolicy(builder.build()); builder.detectFileUriExposure(); }
初始化文件
file = new File(Environment.getExternalStorageDirectory(), "headPicture.jpg");//新建一个文件(路径,文件名称) if (file.exists()) { file.delete(); } try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } imageUri = Uri.fromFile(file);
图片裁剪代码
private void cropPicture(Uri uri) { //新建一个表示裁剪的Intent Intent intent = new Intent("com.android.camera.action.CROP"); //表明我要裁剪的目标是uri这个地址,文件类型是图片 intent.setDataAndType(uri,"image/*"); //指定长宽的比例为1:1 intent.putExtra("aspectX", 1); intent.putExtra("aspectY", 1); //指定宽高为1000 intent.putExtra("outputX", 1000); intent.putExtra("outputY", 1000); intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); startActivityForResult(intent,2); }
保存图片文件路径
private void setHeadPicture() { try { //根据imageUri用getContentResolver来获取流对象 再转化成bitmap Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri)); if (bitmap==null) { //判断bitmap是否为空 Toast.makeText(this,"图像没有存储到sd卡根目录",Toast.LENGTH_SHORT).show(); } c1.setImageBitmap(bitmap); } catch (FileNotFoundException e) { } }
图片裁剪
private void cropPicture(Uri uri) { //新建一个表示裁剪的Intent Intent intent = new Intent("com.android.camera.action.CROP"); //表明我要裁剪的目标是uri这个地址,文件类型是图片 intent.setDataAndType(uri,"image/*"); //指定长宽的比例为1:1 intent.putExtra("aspectX", 1); intent.putExtra("aspectY", 1); //指定宽高为1000 intent.putExtra("outputX", 200); intent.putExtra("outputY", 200); intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); startActivityForResult(intent,2); }
定义OkhttpUtils类
package com.example.note1;import org.json.JSONObject;import java.io.File;import java.io.IOException;import okhttp3.Call;import okhttp3.Callback;import okhttp3.MediaType;import okhttp3.MultipartBody;import okhttp3.OkHttpClient;import okhttp3.Request;import okhttp3.RequestBody;import okhttp3.Response;public class OkhttpUtils { //定义一个JSON的MediaType(互联网媒体类型) private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); //1.定义一个OkhttpClient private static OkHttpClient client = new OkHttpClient(); public static void doPost(final String url, final File file,JSONObject jsonObject, final com.example.note1.HttpResponseCallBack httpResponseCallBack) { //建立body RequestBody body = RequestBody.create(JSON,jsonObject.toString()); //建立请求 Request request = new Request.Builder().post(body).url(url).build(); Call call = client.newCall(request); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { httpResponseCallBack.error(e); } @Override public void onResponse(Call call, Response response) throws IOException { String s = response.body().string(); httpResponseCallBack.response(s); if (file!=null)//如果有文件需要传输的话 { doPostPicture(url, file,new com.example.note1.HttpResponseCallBack() { @Override public void response(String response) { //做操作 } @Override public void error(Exception e) { //做操作 } }); } } }); } //参数为要上传的网址,本地照片在本地的地址,我们自己定义的接口 private static void doPostPicture(String url, File file,final com.example.note1.HttpResponseCallBack httpResponseCallBack) { //2.创建一个请求体 RequestBody body; //3.创建一个请求体建造器 MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM); System.out.println(file); builder.addFormDataPart("file", "headPicture.jpg", RequestBody.create(MediaType.parse("image/jpg"), file)) .addFormDataPart("port","3") .build(); body = builder.build(); //3.创建一个请求,利用构建器方式添加url和请求体。 Request request = new Request.Builder() .post(body) .addHeader("Authorization", "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczpcL1wveHVlemkuY2hhbmppYW9yb25nLmNvbVwvYXBpXC9jb21tb25cL2xvZ2luXC9wd2RMb2dpbiIsImlhdCI6MTYyMDEzODMwNCwiZXhwIjoxNjIzMzMwMzA0LCJuYmYiOjE2MjAxMzgzMDQsImp0aSI6IkJFSmI4UFNsdE1wdWRyOEwiLCJzdWIiOjcsInBydiI6IjljMmViNzg4ZjYyM2NlMTE3OWU2NDYzZDE0OTAxZWY1YzY1MTA0YTUiLCJyb2xlIjoiYXBpIn0.-e5EbtMDjokahHtY6lLpEnEegXzlTWyhhQ5my1WyhD8") .addHeader("Accept","") .addHeader("port","3") .url(url) .build(); //4.定义一个call,利用okhttpclient的newcall方法来创建对象。因为Call是一个接口不能利用构造器实例化。 Call call = client.newCall(request); //5.这是异步调度方法,上传和接受的工作都在子线程里面运作,如果要使用同步的方法就用call.excute(),此方法返回的就是Response call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { httpResponseCallBack.error(e);//错误发生时的处理 } @Override public void onResponse(Call call, Response response) throws IOException { String reslt=response.body().string(); System.out.println(reslt); } }); }}
监听功能
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { case 0: //拍照 if (resultCode == RESULT_OK) { cropPicture(imageUri); } break; case 1: //从相册获取 if (resultCode == RESULT_OK) { cropPicture(data.getData()); } break; case 2: //裁剪之后 if (resultCode == RESULT_OK) { setHeadPicture(); //点击以后上传用户id和用户图片到服务器 JSONObject jsonObject = new JSONObject(); OkhttpUtils.doPost(url, file, token,jsonObject, new HttpResponseCallBack() { @Override public void response(String response) { runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(MainActivity4.this,"上传成功",Toast.LENGTH_SHORT).show(); } }); } @Override public void error(Exception e) { } }); } break; } }
实现功能
源代码
https://download.csdn.net/download/Scxioi0/18384366
发表评论
最新留言
表示我来过!
[***.240.166.169]2025年03月13日 22时57分52秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
【POJ 1148】Utopia Divided
2019-03-04
【ybt高效进阶3-4-1】【luogu P3387】有向图缩点 / 【模板】缩点
2019-03-04
【python】理解列表推导式以及列表推导式嵌套
2019-03-04
【DG特长生2019 T4】【SSL 2892】文档恢复
2019-03-04
学校初一模拟赛(2019.5.11)
2019-03-04
恐怖的奴隶主
2019-03-04
python快速入门——从零开始学python
2019-03-04
pythonBug入门——从零开始学python
2019-03-04
solidity笔记——第一篇
2019-03-04
爬虫快速入门——发送post请问
2019-03-04
FISCO BCOS群组特性
2019-03-04
学习随笔——计算机硬件——2020.11.3
2019-03-04
Vue——options选项——2020.11.13
2019-03-04
Vue——定义template——2020.11.13
2019-03-04
Vue——v-once指令的用法——2020.11.14
2019-03-04
Vue——v-text指令的用法——2020.11.14
2019-03-04
ES6——const的使用和注意点——2020.11.15
2019-03-04
ES6——对象字面量增强写法——2020.11.15
2019-03-04
Vue.js——v-model结合checkbox类型——2020.11.22
2019-03-04
Vue.js——子访问父-parent-root——2020.11.30
2019-03-04