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

【OkHttp】OkHttp 上传图片 ( 获取 SD 卡动态权限 | 跳转到相册界面选择图片 | 使用 OkHttp 上传图片文件 )相关推荐

  1. termux获取sd卡读写权限_索尼发布“世界最快”USB-C Hub及TOUGH SF-M系列SD卡

    7月14日消息,据Cool3c报道,索尼宣布推出新的TOUGH SF-M系列SD卡及USB-C扩展坞MRW-S3.这款MRW-S3号称"世界最快"的UHS-II SD和microS ...

  2. termux获取sd卡读写权限_原来是用错了读卡器,雷克沙lexar 1667X 真实读写性能测试...

    上一篇文章结合泥坑D3300套装老设备对雷克沙新版1667x 进行兼容性部分的测试,可以正常使用,而且在拍摄性能上有了很大的提升.当然雷克沙新版1667x 主要还是用来搭配SONY A6100来进行视 ...

  3. termux获取sd卡读写权限_TF卡戴套客串SD卡真的靠谱吗?用数据说话

    大家好,我是黄昏百分百,今天为大家带来一次硬核测试,看一看TF卡搭配卡套,能否当作SD卡使用,卡套是否会降低其读写性能.包括我在内,很多朋友都对这个问题感兴趣,但是貌似全网没有几个人做过类似的测试,所 ...

  4. termux获取sd卡读写权限_stm32 SPI读写储存卡(MicroSD TF卡)

    简述 花了较长的时间,来弄读写储存卡(大部分教程讲的比较全但是不是很容易懂),这里希望我的代码经验能够帮助到你. 操作分析及实现 0.整个流程 1.上电以后储存卡的初始化 2.如何进行读写 实现 1. ...

  5. termux获取sd卡读写权限_我牵手金士顿小蓝TF卡成功上岛啦

    春风吹,战鼓擂,我中奖了我怕sei~啦啦啦,激动的心情难以言表,今天来分享一下我在一个Switch活动中获奖的金士顿的Canvas Go!Plus小蓝128G TF卡. 其实...我是盯着那个特等奖N ...

  6. termux获取sd卡读写权限_重回SD市场 三星128GB/256GB PRO Plus存储卡评测

    当前数码相机的性能越来越强,视频/照片双修的拍摄能力也逐步得到提高,对于大多数人来说,大容量的存储卡需求也在逐渐增大,一款好的SD卡不但能够进行快速的视频.照片捕捉,而且在抗磁.耐高温等一些特定环境的 ...

  7. 【Android 性能优化】应用启动优化 ( 方法追踪代码模板 | 示例项目 | SD 卡访问权限 | 示例代码 | 获取 Trace 文件 | Android Studio 查看文件)

    文章目录 一. 方法追踪代码模板 二. 追踪 Launch 页面的 onCreate 方法执行情况 1. 示例项目 2. SD 卡访问权限问题 ( 动态权限申请 ) 3. MainActivity o ...

  8. android sd卡列目录文件_Android正确获取SD卡目录及使用SD卡目录

    此文乃是转载,原文在这里链接 SD卡作为手机的扩展存储设备,在手机中充当硬盘角色,可以让我们手机存放更多的数据以及多媒体等大体积文件.因此查看SD卡的内存就跟我们查看硬盘的剩余空间一样,是我们经常操作 ...

  9. Android 外置 SD 卡写入权限问题

    https://busy.im/post/android-sdcard-write/ 最近升级到 Android 9.0 后,发现文件管理器在写入外置 SD 卡时出现了写入失败的问题,定位到 File ...

最新文章

  1. 钉钉接入access_无需开发,IT事件接入钉钉的方法详解
  2. python小程序-python学习—几个简单小程序
  3. 26Exchange Server 2010跨站点部署-内外网邮件流测试
  4. zookeeper的名词复盘-版本-保证分布式数据原子性
  5. SVN客户端--TortoiseSVN使用说明
  6. qt设置鼠标追踪后,鼠标还是需要点击后才能变样式
  7. Vant-UI 表单组件(Field组件):验证表单元素表单提交 - 踩坑篇
  8. FFmpeg源代码简单分析:av_find_decoder()和av_find_encoder()
  9. iOS 提交app到iTunes Connect预览截图截取方法及尺寸大小
  10. 【LOJ】#2187. 「SHOI2014」三叉神经树
  11. 苹果内容拦截器在哪_苹果全家桶,真的有别人说的那么香吗?
  12. 数据类型和Json格式[zt]
  13. WBS——工作分解结构
  14. 【运筹学】分支定界法 ( 分支定界法相关概念 | 分支定界法求解整数规划步骤 | 分支定界理论分析 | 分支过程示例 )
  15. python 读取地震道头数据_[宜配屋]听图阁
  16. 非常不错的Solaris文章,适合入门
  17. 2022“杭电杯”中国大学生算法设计超级联赛(7) 2022杭电多校第七场
  18. RecyclerView点击某个条目保持选中
  19. mysql超卖问题处理_mysql 解决超卖问题的锁分析
  20. 荆棘鸟(The Thorn bird)

热门文章

  1. pku3661 Running
  2. Bit,Byte,Word,Dword,Qword
  3. 小功告成:ReadIE beta
  4. 黑马lavarel教程---4、csrf验证及相关
  5. 2018-2019-1 20165223 20165218 实验二 固件程序设计
  6. 分享几篇VMP研究和分析的文章
  7. 洛谷—— P1714 切蛋糕
  8. JavaScript编码规范[百度]
  9. 摄影师张梦格App项目总结
  10. 纹理过滤模式中的Bilinear、Trilinear以及Anistropic Filtering