前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【OkHttp】OkHttp 上传图片 ( 获取 SD 卡动态权限 | 跳转到相册界面选择图片 | 使用 OkHttp 上传图片文件 )

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

作者头像
韩曙亮
发布2023-03-29 14:21:15
2.3K0
发布2023-03-29 14:21:15
举报
文章被收录于专栏:韩曙亮的移动开发专栏

OkHttp 系列文章目录

【OkHttp】OkHttp 简介 ( OkHttp 框架特性 | Http 版本简介 )

【OkHttp】Android 项目导入 OkHttp ( 配置依赖 | 配置 networkSecurityConfig | 配置 ViewBinding | 代码示例 )

【OkHttp】OkHttp Get 和 Post 请求 ( 同步 Get 请求 | 异步 Get 请求 | 同步 Post 请求 | 异步 Post 请求 )

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


文章目录


前言

在上一篇博客 【OkHttp】OkHttp Get 和 Post 请求 ( 同步 Get 请求 | 异步 Get 请求 | 同步 Post 请求 | 异步 Post 请求 ) 中介绍了 OkHttp 的 同步 / 异步 的 Get / Post 请求 , 本篇博客开始讲解文件的上传 ;


一、获取 SD 卡动态权限


在清单文件中 , 注册如下权限 ;

代码语言:javascript
复制
    <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 权限申请库 ( 完整代码示例 | 申请权限 | 申请权限原理对话框 | 引导用户手动设置权限对话框 ) ;

代码语言:javascript
复制
        // 申请权限
        AndPermission.with(this)
                .runtime()
                .permission(
                        // 申请 SD 卡权限
                        Permission.WRITE_EXTERNAL_STORAGE,
                        Permission.READ_EXTERNAL_STORAGE
                ).onGranted(new Action<List<String>>() {
                    @Override
                    public void onAction(List<String> data) {
                        // 所有权限都通过
                    }
                }).onDenied(new Action<List<String>>() {
                    @Override
                    public void onAction(List<String> data) {
                        // 存在至少 1 个权限被拒绝
                    }
                }).start();

二、跳转到相册界面


使用下面的 Intent 设置 , 跳转到相册图片选择界面 ;

代码语言:javascript
复制
// 跳转到相册界面
Intent intent = new Intent(
        Intent.ACTION_PICK,
        android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, REQUEST_CODE);

三、选择完相册图片后回到本界面


① 首先 , 判定是否获取成功 , 如果图片获取成功 , 再向下继续执行 ;

代码语言:javascript
复制
        //获取图片路径
        if (requestCode == REQUEST_CODE
                && resultCode == Activity.RESULT_OK
                && data != null) {

② 其次 , 获取图像的 Uri , 这是查找图片的唯一依据 ;

代码语言:javascript
复制
// 获取图像 Uri
Uri imageUri = data.getData();

③ 再次 , 查询数据库中 , Uri 对应图片的文件路径 ; 文件路径所在的字段是 MediaStore.Images.Media.DATA 字段 , 列明为 _data ;

代码语言:javascript
复制
// 要查询的列字段名称
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 上传获取的图片对应的文件路径 ;

完整代码示例 :

代码语言:javascript
复制
    /**
     * 在相册中选择图片返回
     * @param requestCode
     * @param resultCode
     * @param data
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        //获取图片路径
        if (requestCode == REQUEST_CODE
                && resultCode == Activity.RESULT_OK
                && data != null) {
            // 获取图像 Uri
            Uri 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 上传图片文件 ( 核心步骤 )


① 首先 , 构造请求体 ;

代码语言:javascript
复制
        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 请求 ;

代码语言:javascript
复制
        // Post 请求
        Request request = new Request.Builder()
                .url("https://www.baidu.com")
                .post(body)
                .build();

③ 最后 , 执行异步 Post 请求 , 上传图片 ;

代码语言:javascript
复制
        // 执行异步请求
        mOkHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                String result = response.body().string();
                // 上传完毕
            }
        });

完整代码示例 :

代码语言:javascript
复制
    /**
     * 使用 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() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                String result = response.body().string();
                // 上传完毕
            }
        });
    }

五、完整代码示例


代码语言:javascript
复制
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;

    @Override
    protected 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() {
            @Override
            public 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() {
            @Override
            public 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(){

            @Override
            public void onFailure(Call call, IOException e) {
                // 请求失败的情况
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                // 请求成功 , 获取
                String result = response.body().string();
                Log.i(TAG, "result : " + result);
                runOnUiThread(new Runnable() {
                    @Override
                    public 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() {
            @Override
            public 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(){

            @Override
            public void onFailure(Call call, IOException e) {
                // 请求失败的情况
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                // 请求成功 , 获取
                String result = response.body().string();
                Log.i(TAG, "result : " + result);
                runOnUiThread(new Runnable() {
                    @Override
                    public 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>>() {
                    @Override
                    public 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>>() {
                    @Override
                    public void onAction(List<String> data) {
                        // 存在至少 1 个权限被拒绝
                    }
                }).start();
    }

    /**
     * 在相册中选择图片返回
     * @param requestCode
     * @param resultCode
     * @param data
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        //获取图片路径
        if (requestCode == REQUEST_CODE
                && resultCode == Activity.RESULT_OK
                && data != null) {
            // 获取图像 Uri
            Uri 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() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                String result = response.body().string();
                // 上传完毕
            }
        });
    }


}

六、博客资源

GitHub : https://github.com/han1202012/OkHttp

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-06-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • OkHttp 系列文章目录
    • 文章目录
    • 前言
    • 一、获取 SD 卡动态权限
    • 二、跳转到相册界面
    • 三、选择完相册图片后回到本界面
    • 四、使用 OkHttp 上传图片文件 ( 核心步骤 )
    • 五、完整代码示例
    • 六、博客资源
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档