【OkHttp】OkHttp 上传图片 ( 获取 SD 卡动态权限 | 跳转到相册界面选择图片 | 使用 OkHttp 上传图片文件 )
OkHttp 系列文章目录
【OkHttp】OkHttp 简介 ( OkHttp 框架特性 | Http 版本简介 )
【OkHttp】Android 项目导入 OkHttp ( 配置依赖 | 配置 networkSecurityConfig | 配置 ViewBinding | 代码示例 )
【OkHttp】OkHttp Get 和 Post 请求 ( 同步 Get 请求 | 异步 Get 请求 | 同步 Post 请求 | 异步 Post 请求 )
【OkHttp】OkHttp 上传图片 ( 获取 SD 卡动态权限 | 跳转到相册界面选择图片 | 使用 OkHttp 上传图片文件 )
文章目录
- OkHttp 系列文章目录
- 前言
- 一、获取 SD 卡动态权限
- 二、跳转到相册界面
- 三、选择完相册图片后回到本界面
- 四、使用 OkHttp 上传图片文件 ( 核心步骤 )
- 五、完整代码示例
- 六、博客资源
前言
在上一篇博客 【OkHttp】OkHttp Get 和 Post 请求 ( 同步 Get 请求 | 异步 Get 请求 | 同步 Post 请求 | 异步 Post 请求 ) 中介绍了 OkHttp 的 同步 / 异步 的 Get / Post 请求 , 本篇博客开始讲解文件的上传 ;
一、获取 SD 卡动态权限
在清单文件中 , 注册如下权限 ;
<uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />在 Activity 中 , 动态申请权限 , 这里使用到了一个动态权限库 ;
此处也可以使用原生代码自己开发动态权限申请 【Android 应用开发】动态权限管理示例 ( 使用原生代码实现 | 申请权限 | 判定权限申请结果 | 判定 “ 不再询问 “ 情况 ) ,
也可以使用 Google 官方的 EasyPermission 权限框架 【Android 应用开发】Google 官方 EasyPermissions 权限申请库 ( 完整代码示例 | 申请权限 | 申请权限原理对话框 | 引导用户手动设置权限对话框 ) ;
// 申请权限AndPermission.with(this).runtime().permission(// 申请 SD 卡权限Permission.WRITE_EXTERNAL_STORAGE,Permission.READ_EXTERNAL_STORAGE).onGranted(new Action<List<String>>() {@Overridepublic void onAction(List<String> data) {// 所有权限都通过}}).onDenied(new Action<List<String>>() {@Overridepublic void onAction(List<String> data) {// 存在至少 1 个权限被拒绝}}).start();二、跳转到相册界面
使用下面的 Intent 设置 , 跳转到相册图片选择界面 ;
// 跳转到相册界面 Intent intent = new Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI); startActivityForResult(intent, REQUEST_CODE);三、选择完相册图片后回到本界面
① 首先 , 判定是否获取成功 , 如果图片获取成功 , 再向下继续执行 ;
//获取图片路径if (requestCode == REQUEST_CODE&& resultCode == Activity.RESULT_OK&& data != null) {② 其次 , 获取图像的 Uri , 这是查找图片的唯一依据 ;
// 获取图像 Uri Uri imageUri = data.getData();③ 再次 , 查询数据库中 , Uri 对应图片的文件路径 ; 文件路径所在的字段是 MediaStore.Images.Media.DATA 字段 , 列明为 _data ;
// 要查询的列字段名称 String[] filePathColumns = {MediaStore.Images.Media.DATA};// 到数据库中查询 , 查询 _data 列字段信息 Cursor cursor = getContentResolver().query(imageUri,filePathColumns,null,null,null);cursor.moveToFirst(); // 获取 _data 列所在的列索引 int columnIndex = cursor.getColumnIndex(filePathColumns[0]); // 获取图片的存储路径 String filePath = cursor.getString(columnIndex);// 获取数据完毕后, 关闭游标 cursor.close();④ 最后 , 使用 OkHttp 上传获取的图片对应的文件路径 ;
完整代码示例 :
/*** 在相册中选择图片返回* @param requestCode* @param resultCode* @param data*/@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);//获取图片路径if (requestCode == REQUEST_CODE&& resultCode == Activity.RESULT_OK&& data != null) {// 获取图像 UriUri imageUri = data.getData();// 要查询的列字段名称String[] filePathColumns = {MediaStore.Images.Media.DATA};// 到数据库中查询 , 查询 _data 列字段信息Cursor cursor = getContentResolver().query(imageUri,filePathColumns,null,null,null);cursor.moveToFirst();// 获取 _data 列所在的列索引int columnIndex = cursor.getColumnIndex(filePathColumns[0]);// 获取图片的存储路径String filePath = cursor.getString(columnIndex);// 使用 OkHttp 上传图片upload(filePath);// 获取数据完毕后, 关闭游标cursor.close();}}四、使用 OkHttp 上传图片文件 ( 核心步骤 )
① 首先 , 构造请求体 ;
File file = new File(filePath);// 请求体RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM).addFormDataPart("file",file.getName(),MultipartBody.create(MediaType.parse("multipart/form-data"), file)).build();② 然后 , 创建 Post 请求 ;
// Post 请求Request request = new Request.Builder().url("https://www.baidu.com").post(body).build();③ 最后 , 执行异步 Post 请求 , 上传图片 ;
// 执行异步请求mOkHttpClient.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {}@Overridepublic void onResponse(Call call, Response response) throws IOException {String result = response.body().string();// 上传完毕}});完整代码示例 :
/*** 使用 OkHttp 上传图片* @param filePath*/private void upload(String filePath){File file = new File(filePath);// 请求体RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM).addFormDataPart("file",file.getName(),MultipartBody.create(MediaType.parse("multipart/form-data"), file)).build();// Post 请求Request request = new Request.Builder().url("https://www.baidu.com").post(body).build();// 执行异步请求mOkHttpClient.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {}@Overridepublic void onResponse(Call call, Response response) throws IOException {String result = response.body().string();// 上传完毕}});}五、完整代码示例
package com.example.okhttp;import androidx.appcompat.app.AppCompatActivity;import android.Manifest; import android.app.Activity; import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.provider.MediaStore; import android.util.Log; import android.view.View;import com.example.okhttp.databinding.ActivityMainBinding; import com.yanzhenjie.permission.Action; import com.yanzhenjie.permission.AndPermission; import com.yanzhenjie.permission.runtime.Permission;import java.io.File; import java.io.IOException; import java.util.List;import okhttp3.Call; import okhttp3.Callback; import okhttp3.FormBody; import okhttp3.MediaType; import okhttp3.MultipartBody; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; import pub.devrel.easypermissions.EasyPermissions;public class MainActivity extends AppCompatActivity {private static final String TAG = "MainActivity";/*** ViewBinding 类* activity_main 布局映射出来的类* 该类主要作用是封装组件的获取*/ActivityMainBinding binding;/*** OkHttp 客户端* 注意 : 该类型对象较大, 尽量在应用中创建较少的该类型对象* 推荐使用单例*/OkHttpClient mOkHttpClient;/*** Activity 跨页访问的面请求码*/public static final int REQUEST_CODE = 1;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);binding = ActivityMainBinding.inflate(getLayoutInflater());setContentView(binding.getRoot());EasyPermissions.requestPermissions(this,"权限申请原理对话框 : 描述申请权限的原理",100,// 下面是要申请的权限 可变参数列表Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE);mOkHttpClient = new OkHttpClient();binding.button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//httpSynchronousGet();//httpAsynchronousGet();//httpSynchronousPost();//httpAsynchronousPost();httpUploadPhoto();}});}/*** OkHttp 同步 Get 请求*/private void httpSynchronousGet() {// Request 中封装了请求相关信息Request request = new Request.Builder().url("https://www.baidu.com") // 设置请求地址.get() // 使用 Get 方法.build();// 同步 Get 请求new Thread(new Runnable() {@Overridepublic void run() {Response response = null;try {response = mOkHttpClient.newCall(request).execute();} catch (IOException e) {e.printStackTrace();}String result = null;try {result = response.body().string();} catch (IOException e) {e.printStackTrace();}Log.i(TAG, "result : " + result);}}).start();}/*** OkHttp 异步 Get 请求*/private void httpAsynchronousGet() {// Request 中封装了请求相关信息Request request = new Request.Builder().url("https://www.baidu.com") // 设置请求地址.get() // 使用 Get 方法.build();// 创建异步回调Callback callback = new Callback(){@Overridepublic void onFailure(Call call, IOException e) {// 请求失败的情况}@Overridepublic void onResponse(Call call, Response response) throws IOException {// 请求成功 , 获取String result = response.body().string();Log.i(TAG, "result : " + result);runOnUiThread(new Runnable() {@Overridepublic void run() {// 主线程中执行相关代码}});}};// 异步 Get 请求mOkHttpClient.newCall(request).enqueue(callback);}/*** OkHttp 同步 Post 请求*/private void httpSynchronousPost() {// 创建 Post 表单 , 主要用于设置 Post 请求键值对FormBody formBody = new FormBody.Builder().add("Key", "Value").build();// Request 中封装了请求相关信息Request request = new Request.Builder().url("https://www.baidu.com") // 设置请求地址.post(formBody) // 使用 Post 方法.build();// 同步 Get 请求new Thread(new Runnable() {@Overridepublic void run() {Response response = null;try {response = mOkHttpClient.newCall(request).execute();} catch (IOException e) {e.printStackTrace();}String result = null;try {result = response.body().string();} catch (IOException e) {e.printStackTrace();}Log.i(TAG, "result : " + result);}}).start();}/*** OkHttp 异步 Post 请求*/private void httpAsynchronousPost() {// 创建 Post 表单 , 主要用于设置 Post 请求键值对FormBody formBody = new FormBody.Builder().add("Key", "Value").build();// Request 中封装了请求相关信息Request request = new Request.Builder().url("https://www.baidu.com") // 设置请求地址.post(formBody) // 使用 Post 方法.build();// 创建异步回调Callback callback = new Callback(){@Overridepublic void onFailure(Call call, IOException e) {// 请求失败的情况}@Overridepublic void onResponse(Call call, Response response) throws IOException {// 请求成功 , 获取String result = response.body().string();Log.i(TAG, "result : " + result);runOnUiThread(new Runnable() {@Overridepublic void run() {// 主线程中执行相关代码}});}};// 异步 Get 请求mOkHttpClient.newCall(request).enqueue(callback);}/*** 上传图片*/private void httpUploadPhoto() {// 申请权限AndPermission.with(this).runtime().permission(// 申请 SD 卡权限Permission.WRITE_EXTERNAL_STORAGE,Permission.READ_EXTERNAL_STORAGE).onGranted(new Action<List<String>>() {@Overridepublic void onAction(List<String> data) {// 所有权限都通过// 跳转到相册界面Intent intent = new Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);startActivityForResult(intent, REQUEST_CODE);}}).onDenied(new Action<List<String>>() {@Overridepublic void onAction(List<String> data) {// 存在至少 1 个权限被拒绝}}).start();}/*** 在相册中选择图片返回* @param requestCode* @param resultCode* @param data*/@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);//获取图片路径if (requestCode == REQUEST_CODE&& resultCode == Activity.RESULT_OK&& data != null) {// 获取图像 UriUri imageUri = data.getData();// 要查询的列字段名称String[] filePathColumns = {MediaStore.Images.Media.DATA};// 到数据库中查询 , 查询 _data 列字段信息Cursor cursor = getContentResolver().query(imageUri,filePathColumns,null,null,null);cursor.moveToFirst();// 获取 _data 列所在的列索引int columnIndex = cursor.getColumnIndex(filePathColumns[0]);// 获取图片的存储路径String filePath = cursor.getString(columnIndex);// 使用 OkHttp 上传图片upload(filePath);// 获取数据完毕后, 关闭游标cursor.close();}}/*** 使用 OkHttp 上传图片* @param filePath*/private void upload(String filePath){File file = new File(filePath);// 请求体RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM).addFormDataPart("file",file.getName(),MultipartBody.create(MediaType.parse("multipart/form-data"), file)).build();// Post 请求Request request = new Request.Builder().url("https://www.baidu.com").post(body).build();// 执行异步请求mOkHttpClient.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {}@Overridepublic void onResponse(Call call, Response response) throws IOException {String result = response.body().string();// 上传完毕}});}}
六、博客资源
GitHub : https://github.com/han1202012/OkHttp
《新程序员》:云原生和全面数字化实践50位技术专家共同创作,文字、视频、音频交互阅读总结
以上是生活随笔为你收集整理的【OkHttp】OkHttp 上传图片 ( 获取 SD 卡动态权限 | 跳转到相册界面选择图片 | 使用 OkHttp 上传图片文件 )的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: 【Android 应用开发】动态权限管理
- 下一篇: 【OkHttp】OkHttp 源码分析