Use okhttp to download and upload pictures, file explanations and actual combat in Android App development network communication (super detailed implementation of user registration information upload with source code)

If you need the source code, please like it, follow the collection, leave a message in the comment area and send a private message~~~

1. Use okhttp to download pictures

okhttp not only simplifies the calling process of the HTTP interface, but also makes downloading files easier. For general file downloading, follow the conventional GET method to call the process, just rewrite the callback method onResponse, and pass the body method of the response object in this method You can get the data packet object of the response, call the string method of the data packet object to get the string in the form of text, the following is an example of downloading a network picture, the bitmap tool BitmapFactory just provides the decodeStream method, which allows decoding directly from the input stream The effect of obtaining a bitmap object is as follows

Click the download picture button to automatically download network pictures

2. Use okhttp to download files

Of course, network files are not only pictures, but also various files. These files do not have special decoding tools, and can only read byte data honestly from the input stream, but there is an advantage in reading byte data. It is to be able to calculate the download progress according to the length of the data that has been read and written, especially when downloading large files, it is very useful to display the current download progress in real time

The effect is as follows. The demo video has been uploaded to the personal homepage and can be watched by yourself.

It can be seen from the figure below that the download progress has been loaded to 100%.

  

 code show as below

Java class

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; // 声明一个图像视图对象

    @Override
    protected 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() {
            @Override
            public void onFailure(Call call, IOException e) { // 请求失败
                // 回到主线程操纵界面
                runOnUiThread(() -> tv_result.setText("下载网络图片报错:"+e.getMessage()));
            }

            @Override
            public 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() {
            @Override
            public void onFailure(Call call, IOException e) { // 请求失败
                // 回到主线程操纵界面
                runOnUiThread(() -> tv_result.setText("下载网络文件报错:"+e.getMessage()));
            }

            @Override
            public 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 file

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <Button
            android:id="@+id/btn_download_image"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="下载图片"
            android:textColor="@color/black"
            android:textSize="17sp" />

        <Button
            android:id="@+id/btn_download_file"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="下载文件"
            android:textColor="@color/black"
            android:textSize="17sp" />
    </LinearLayout>

    <TextView
        android:id="@+id/tv_result"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="5dp"
        android:paddingRight="5dp"
        android:textColor="@color/black"
        android:textSize="17sp" />

    <TextView
        android:id="@+id/tv_progress"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="5dp"
        android:paddingRight="5dp"
        android:textColor="@color/black"
        android:textSize="17sp" />

    <ImageView
        android:id="@+id/iv_result"
        android:layout_width="match_parent"
        android:layout_height="250dp" />

</LinearLayout>

3. Use okhttp to upload files

okhttp not only makes downloading files easier, but also makes uploading files more flexible and easy to use. For example, when modifying personal data, avatars are often accompanied by text descriptions. For this combination of uploading business scenarios, HttpURLConnection encoding is very difficult. Using okhttp It is very simple, it introduces the segmented structure MultipartBody and its builder, which are suitable for data in text format and file format

The following is an example of user registration with an avatar, which not only needs to send the user name and password to the server, but also sends the avatar picture to the server

User information can be customized

 

 code show as below

Java class

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<String> mPathList = new ArrayList<>(); // 头像文件的路径列表

    @Override
    protected 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());
    }

    @Override
    protected 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 file

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="5dp"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:orientation="horizontal">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:gravity="center"
            android:text="用户名:"
            android:textColor="@color/black"
            android:textSize="17sp" />

        <EditText
            android:id="@+id/et_username"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="@drawable/editext_selector"
            android:gravity="left|center"
            android:hint="请输入用户名"
            android:maxLength="11"
            android:textColor="@color/black"
            android:textSize="17sp" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_marginTop="10dp"
        android:orientation="horizontal">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:gravity="center"
            android:text="密 码:"
            android:textColor="@color/black"
            android:textSize="17sp" />

        <EditText
            android:id="@+id/et_password"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="@drawable/editext_selector"
            android:gravity="left|center"
            android:hint="请输入密码"
            android:inputType="numberPassword"
            android:maxLength="6"
            android:textColor="@color/black"
            android:textSize="17sp" />

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:gravity="center"
            android:text="头 像:"
            android:textColor="@color/black"
            android:textSize="17sp" />

        <ImageView
            android:id="@+id/iv_face"
            android:layout_width="120dp"
            android:layout_height="120dp"
            android:layout_marginLeft="5dp"
            android:scaleType="fitXY"
            android:src="@drawable/add_pic" />
    </LinearLayout>

    <Button
        android:id="@+id/btn_register"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="注册"
        android:textColor="@color/black"
        android:textSize="17sp" />

    <TextView
        android:id="@+id/tv_result"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textColor="@color/black"
        android:textSize="17sp" />

</LinearLayout>

It's not easy to create and find it helpful, please like, follow and collect~~~

Guess you like

Origin blog.csdn.net/jiebaoshayebuhui/article/details/128020483