【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 卡動態(tài)權限 | 跳轉到相冊界面選擇圖片 | 使用 OkHttp 上傳圖片文件 )
文章目錄
- OkHttp 系列文章目錄
- 前言
- 一、獲取 SD 卡動態(tài)權限
- 二、跳轉到相冊界面
- 三、選擇完相冊圖片后回到本界面
- 四、使用 OkHttp 上傳圖片文件 ( 核心步驟 )
- 五、完整代碼示例
- 六、博客資源
前言
在上一篇博客 【OkHttp】OkHttp Get 和 Post 請求 ( 同步 Get 請求 | 異步 Get 請求 | 同步 Post 請求 | 異步 Post 請求 ) 中介紹了 OkHttp 的 同步 / 異步 的 Get / Post 請求 , 本篇博客開始講解文件的上傳 ;
一、獲取 SD 卡動態(tài)權限
在清單文件中 , 注冊如下權限 ;
<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 中 , 動態(tài)申請權限 , 這里使用到了一個動態(tài)權限庫 ;
此處也可以使用原生代碼自己開發(fā)動態(tài)權限申請 【Android 應用開發(fā)】動態(tài)權限管理示例 ( 使用原生代碼實現(xiàn) | 申請權限 | 判定權限申請結果 | 判定 “ 不再詢問 “ 情況 ) ,
也可以使用 Google 官方的 EasyPermission 權限框架 【Android 應用開發(fā)】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);三、選擇完相冊圖片后回到本界面
① 首先 , 判定是否獲取成功 , 如果圖片獲取成功 , 再向下繼續(xù)執(zhí)行 ;
//獲取圖片路徑if (requestCode == REQUEST_CODE&& resultCode == Activity.RESULT_OK&& data != null) {② 其次 , 獲取圖像的 Uri , 這是查找圖片的唯一依據(jù) ;
// 獲取圖像 Uri Uri imageUri = data.getData();③ 再次 , 查詢數(shù)據(jù)庫中 , Uri 對應圖片的文件路徑 ; 文件路徑所在的字段是 MediaStore.Images.Media.DATA 字段 , 列明為 _data ;
// 要查詢的列字段名稱 String[] filePathColumns = {MediaStore.Images.Media.DATA};// 到數(shù)據(jù)庫中查詢 , 查詢 _data 列字段信息 Cursor cursor = getContentResolver().query(imageUri,filePathColumns,null,null,null);cursor.moveToFirst(); // 獲取 _data 列所在的列索引 int columnIndex = cursor.getColumnIndex(filePathColumns[0]); // 獲取圖片的存儲路徑 String filePath = cursor.getString(columnIndex);// 獲取數(shù)據(jù)完畢后, 關閉游標 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};// 到數(shù)據(jù)庫中查詢 , 查詢 _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);// 獲取數(shù)據(jù)完畢后, 關閉游標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();② 然后 , 創(chuàng)建 Post 請求 ;
// Post 請求Request request = new Request.Builder().url("https://www.baidu.com").post(body).build();③ 最后 , 執(zhí)行異步 Post 請求 , 上傳圖片 ;
// 執(zhí)行異步請求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();// 執(zhí)行異步請求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 客戶端* 注意 : 該類型對象較大, 盡量在應用中創(chuàng)建較少的該類型對象* 推薦使用單例*/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,// 下面是要申請的權限 可變參數(shù)列表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();// 創(chuàng)建異步回調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() {// 主線程中執(zhí)行相關代碼}});}};// 異步 Get 請求mOkHttpClient.newCall(request).enqueue(callback);}/*** OkHttp 同步 Post 請求*/private void httpSynchronousPost() {// 創(chuàng)建 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() {// 創(chuàng)建 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();// 創(chuàng)建異步回調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() {// 主線程中執(zhí)行相關代碼}});}};// 異步 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};// 到數(shù)據(jù)庫中查詢 , 查詢 _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);// 獲取數(shù)據(jù)完畢后, 關閉游標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();// 執(zhí)行異步請求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
《新程序員》:云原生和全面數(shù)字化實踐50位技術專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的【OkHttp】OkHttp 上传图片 ( 获取 SD 卡动态权限 | 跳转到相册界面选择图片 | 使用 OkHttp 上传图片文件 )的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Android 应用开发】动态权限管理
- 下一篇: 【OkHttp】OkHttp 源码分析