Android App开发网络通信中使用okhttp下载和上传图片、文件讲解及实战(超详细实现用户注册信息上传 附源码)
创始人
2024-02-11 17:14:06
0

需要源码请点赞关注收藏后评论区留言并且私信~~~

一、使用okhttp下载图片

okhttp不但简化了HTTP接口的调用过程,连下载文件都变得简单了,对于一般的文件下载,按照常规的GET方式调用流程,只要重写回调方法onResponse,在该方法中通过应答对象的body方法即可获得应答的数据包对象,调用数据包对象的string方法即可得到文本形式的字符串,下面以下载网络图片为例,位图工具BitmapFactory刚好提供了decodeStream方法,允许直接从输入流中解码获取位图对象 效果如下

点击下载图片按钮后即可自动实现下载网络图片

二、利用okhttp下载文件

当然,网络文件不止是图片,还有各种各样的文件,这些文件没有专门的解码工具,只能从输入流老老实实的读取字节数据,不过读取字节数据有个好处,就是能够根据已经读写的数据长度计算下载进度,特别在下载大文件的时候,实时展示当前的下载进度非常有用

效果如下 演示视频已上传至个人主页 可自行观看

由下图可见下载进度加载到了百分之一百

  

 代码如下

Java类

package com.example.network;import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;import import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;= "https://ptgl.fujian.gov.cn:8088/masvod/public/2021/03/19/20210319_178498bcae9_r38.mp4";private TextView tv_result; // 声明一个文本视图对象private TextView tv_progress; // 声明一个文本视图对象private ImageView iv_result; // 声明一个图像视图对象@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_okhttp_download);tv_result = findViewById(R.id.tv_result);tv_progress = findViewById(R.id.tv_progress);iv_result = findViewById(R.id.iv_result);findViewById(R.id.btn_download_image).setOnClickListener(v -> downloadImage());findViewById(R.id.btn_download_file).setOnClickListener(v -> downloadFile());}// 下载网络图片private void downloadImage() {tv_progress.setVisibility(View.GONE);iv_result.setVisibility(View.VISIBLE);OkHttpClient client = new OkHttpClient(); // 创建一个okhttp客户端对象// 创建一个GET方式的请求结构Request request = new Request.Builder().url(URL_IMAGE).build();Call call = client.newCall(request); // 根据请求结构创建调用对象// 加入HTTP请求队列。异步调用,并设置接口应答的回调方法call.enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) { // 请求失败// 回到主线程操纵界面runOnUiThread(() -> tv_result.setText("下载网络图片报错:"+e.getMessage()));}@Overridepublic void onResponse(Call call, final Response response) { // 请求成功InputStream is = response.body().byteStream();// 从返回的输入流中解码获得位图数据Bitmap bitmap = BitmapFactory.decodeStream(is);String mediaType = response.body().contentType().toString();long length = response.body().contentLength();String desc = String.format("文件类型为%s,文件大小为%d", mediaType, length);// 回到主线程操纵界面runOnUiThread(() -> {tv_result.setText("下载网络图片返回:"+desc);iv_result.setImageBitmap(bitmap);});}});}// 下载网络文件private void downloadFile() {tv_progress.setVisibility(View.VISIBLE);iv_result.setVisibility(View.GONE);OkHttpClient client = new OkHttpClient(); // 创建一个okhttp客户端对象// 创建一个GET方式的请求结构Request request = new Request.Builder().url(URL_APK).build();Call call = client.newCall(request); // 根据请求结构创建调用对象// 加入HTTP请求队列。异步调用,并设置接口应答的回调方法call.enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) { // 请求失败// 回到主线程操纵界面runOnUiThread(() -> tv_result.setText("下载网络文件报错:"+e.getMessage()));}@Overridepublic void onResponse(Call call, final Response response) { // 请求成功String mediaType = response.body().contentType().toString();long length = response.body().contentLength();String desc = String.format("文件类型为%s,文件大小为%d", mediaType, length);// 回到主线程操纵界面runOnUiThread(() -> tv_result.setText("下载网络文件返回:"+desc));String path = String.format("%s/%s.apk",getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString(),DateUtil.getNowDateTime());// 下面从返回的输入流中读取字节数据并保存为本地文件try (InputStream is = response.body().byteStream();FileOutputStream fos = new FileOutputStream(path)) {byte[] buf = new byte[100 * 1024];int sum=0, len=0;while ((len = is.read(buf)) != -1) {fos.write(buf, 0, len);sum += len;int progress = (int) (sum * 1.0f / length * 100);String detail = String.format("文件保存在%s。已下载%d%%", path, progress);// 回到主线程操纵界面runOnUiThread(() -> tv_progress.setText(detail));}} catch (Exception e) {e.printStackTrace();}}});}
}

XML文件

三、利用okhttp上传文件

okhttp不仅让下载文件变得简单,还让上传文件变得更加灵活易用,比如修改个人资料,头像的时候常常带着文字说明,对于这种组合上传的业务场景,HttpURLConnection编码十分困难,用okhttp就十分简单,它引入分段结构MultipartBody及其建造器,分别适用于文本格式与文件格式的数据

下面举带头像进行用户注册的例子,既要把用户名和密码送给服务端,还要把头像图片传给服务器端

可以自定义用户信息

 

 代码如下

Java类

package com.example.network;import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.text.TextUtils;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;import androidx.appcompat.app.AppCompatActivity;import com.example.network.constant.NetConst;
import com.example.network.util.BitmapUtil;import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;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 OkhttpUploadActivity extends AppCompatActivity {private final static String TAG = "OkhttpUploadActivity";public final static String URL_REGISTER = NetConst.HTTP_PREFIX + "register";private EditText et_username; // 声明一个编辑框对象private EditText et_password; // 声明一个编辑框对象private TextView tv_result; // 声明一个文本视图对象private ImageView iv_face; // 声明一个图像视图对象private int CHOOSE_CODE = 3; // 只在相册挑选图片的请求码private List mPathList = new ArrayList<>(); // 头像文件的路径列表@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_okhttp_upload);et_username = findViewById(R.id.et_username);et_password = findViewById(R.id.et_password);iv_face = findViewById(R.id.iv_face);tv_result = findViewById(R.id.tv_result);iv_face.setOnClickListener(v -> {// 创建一个内容获取动作的意图(准备跳到系统相册)Intent albumIntent = new Intent(Intent.ACTION_GET_CONTENT);albumIntent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, false); // 是否允许多选albumIntent.setType("image/*"); // 类型为图像startActivityForResult(albumIntent, CHOOSE_CODE); // 打开系统相册});findViewById(R.id.btn_register).setOnClickListener(v -> uploadFile());}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent intent) {super.onActivityResult(requestCode, resultCode, intent);if (resultCode == RESULT_OK && requestCode == CHOOSE_CODE) { // 从相册返回mPathList.clear();if (intent.getData() != null) { // 从相册选择一张照片// 把指定Uri的图片复制一份到内部存储空间,并返回存储路径String imagePath = saveImage(intent.getData());mPathList.add(imagePath);}}}// 把指定Uri的图片复制一份到内部存储空间,并返回存储路径private String saveImage(Uri uri) {String uriStr = uri.toString();String imageName = uriStr.substring(uriStr.lastIndexOf("/")+1);String imagePath = String.format("%s/%s.jpg", getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString(), imageName);// 获得自动缩小后的位图对象Bitmap bitmap = BitmapUtil.getAutoZoomImage(this, uri);// 把位图数据保存到指定路径的图片文件BitmapUtil.saveImage(imagePath, bitmap);iv_face.setImageBitmap(bitmap);return imagePath;}// 执行文件上传动作private void uploadFile() {if (mPathList.size() <= 0) {Toast.makeText(this, "请选择待上传的用户头像", Toast.LENGTH_SHORT).show();return;}// 创建分段内容的建造器对象MultipartBody.Builder builder = new MultipartBody.Builder();String username = et_username.getText().toString();String password = et_password.getText().toString();if (!TextUtils.isEmpty(username)) {// 往建造器对象添加().string();// 回到主线程操纵界面runOnUiThread(() -> tv_result.setText("调用注册接口返回:\n"+resp));}});}
}

XML文件

创作不易 觉得有帮助请点赞关注收藏~~~

相关内容

热门资讯

上门取件我需要做什么,快递上门...   很多小伙伴想要寄快递,但是因为包裹重量和距离等原因,无法去快递驿站寄快递,想要选择上门取件,但是...
北京退休工资最低多少钱一个月 ...   我们的劳动者只要在用人单位工作直到退休,就可以领到我们相应的退休金,但是很多人对退休金并不了解,...
出行软件十大排行 实用推荐 出... 自打滴滴打车开始风靡起来,越来越多的打车软件层出不穷。它能及时让我们打到车,而不用在路边一直等出租车...
自己交社保一个月多少钱,202...   社保参保对象是我们这些享有中国国籍的公民们,虽然没有怎么强制,但是这些都是给自己的一系列保障们所...
寄大件什么物流上门取货便宜 不... 有时候,比如异地搬家,我们需要打包许多的行李。但是这些行李无法自行搬运过去,这时候就需要寄大件走物流...
社保自己交费一个月多少钱,社保...   社保是我们生活中离不开的,这是对我们医疗等一些服务有保障,减轻我们的一些压力。交了,社保的话,大...
四川退休养老金2022最新调整...   四川养老金2022年调整方案现在已经对外公布了,之前的谣言都可以结束了,随着现在白纸黑字的公布,...
医保统筹账户和个人账户的区别 ...   我们国家的基础医保分两种,一种是职工医保还有一种就是居名医保,很多人都是缴纳的职工医保,参保之后...
怎么查养老保险缴费明细 方法介... 缴纳社保是一件重要的事。缴纳过后有时我们会想要查询一下缴费明细,以此来确认是否缴费成功。那么都有哪些...
信期贷好通过吗,信期贷申请条件...   中信推出了信期贷这类的产品,也是为了哪些优质的客户,不过对信用方面要求也是比较多的。但是要是能够...