1.导入依赖
//Retrofit 核心库implementation("com.squareup.retrofit2:retrofit:2.9.0")//响应数据自动序列化//JSONimplementation("com.squareup.retrofit2:converter-gson:2.9.0")//String类型implementation("com.squareup.retrofit2:converter-scalars:2.9.0")//拦截器 loggingimplementation("com.squareup.okhttp3:logging-interceptor:3.14.+")
2.需要配置清单文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"><uses-permission android:name="android.permission.INTERNET"/><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.OkHttp"android:networkSecurityConfig="@xml/network_security_config"><activityandroid:name=".MainActivity"android:exported="true"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><providerandroid:authorities="${applicationId}.provider"android:name="androidx.core.content.FileProvider"android:exported="false"android:grantUriPermissions="true"><meta-dataandroid:name="android.support.FILE_PROVIDER_PATHS"android:resource="@xml/provider_paths"/></provider></application></manifest>
3.网络权限和 provider
provider_paths.xml
<?xml version="1.0" encoding="utf-8" ?>
<paths><external-pathname="aaa"path="."/></paths>
network_security_config.xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config><base-config cleartextTrafficPermitted="true" />
</network-security-config>
4.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><Buttonandroid:id="@+id/upload"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="上传图片"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /></androidx.constraintlayout.widget.ConstraintLayout>
5.ApiService
package com.tiger.retrofel.api;import java.util.List;
import java.util.Map;import okhttp3.MultipartBody;
import retrofit2.Call;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.Multipart;
import retrofit2.http.POST;
import retrofit2.http.Part;
import retrofit2.http.Query;public interface ApiService {@POST("findList")@FormUrlEncodedCall<Map<String,Object>> test(@Field("start") Integer start,@Field("count") Integer count);@POST("uploadPic")@MultipartCall<Map<String,Object>> upload(@Part MultipartBody.Part part);}
6.权限工具类
package com.tiger.retrofel;import android.Manifest;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.os.Build;import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;public class PermissionUtil {public static final String[] PERMISSIONS_EXTERNAL_STORAGE = new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE};public static final int PERMISSIONS_EXTERNAL_STORAGE_TAG = 1;//检查多个权限。返回true表示已完全启用权限,返回false 表示 未完全启用权限public static boolean checkPermission(Activity act, String[] permissions, int requestCode) {//Android 6.0之后开始采用动态权限管理if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {int check = PackageManager.PERMISSION_GRANTED;for (String permission : permissions) {check = ContextCompat.checkSelfPermission(act, permission);if (check != PackageManager.PERMISSION_GRANTED) {break;}}//未开启该权限,则请求系统弹窗,好让用户选择 是否立即开启权限if (check != PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(act, permissions, requestCode);return false;}}return true;}public static boolean checkGrant(int[] grantResults) {if (grantResults != null) {for (int grantResult : grantResults) {if (grantResult != PackageManager.PERMISSION_GRANTED) {return false;}}return true;} else {return false;}}
}
7.Activity
package com.tiger.retrofel;import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;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 android.widget.Button;import com.tiger.retrofel.api.ApiService;
import com.tiger.retrofel.api.Subject;import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.RequestBody;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.converter.scalars.ScalarsConverterFactory;public class MainActivity extends AppCompatActivity {Retrofit retrofit;private OkHttpClient client;private ApiService apiService;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {@Overridepublic void log(String message) {Log.i("TAG", message);}}).setLevel(HttpLoggingInterceptor.Level.BASIC);client = new OkHttpClient.Builder().addInterceptor(httpLoggingInterceptor).build();retrofit = new Retrofit.Builder().baseUrl("http://192.168.202.55:8999/").client(client)
// .addConverterFactory(ScalarsConverterFactory.create()).addConverterFactory(GsonConverterFactory.create()).build();apiService = retrofit.create(ApiService.class);Button viewById = findViewById(R.id.upload);viewById.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {showPhoto();}});syncRequest();}//同步的请求private void syncRequest() {//同步new Thread(() -> {Response<Map<String,Object>> execute = null;try {execute = apiService.test(0, 2).execute();} catch (IOException e) {throw new RuntimeException(e);}Map<String,Object> body = execute.body();Log.i("ning", "run:response:" + body);}).start();}//异步的请求private void ayncRequest() {//同步try {apiService.test(0, 2).enqueue(new Callback<Map<String,Object>>() {@Overridepublic void onResponse(Call<Map<String,Object>> call, Response<Map<String,Object>> response) {}@Overridepublic void onFailure(Call<Map<String,Object>> call, Throwable t) {}});} catch (Exception e) {e.printStackTrace();}}private void showPhoto() {if (PermissionUtil.checkPermission(this, PermissionUtil.PERMISSIONS_EXTERNAL_STORAGE, PermissionUtil.PERMISSIONS_EXTERNAL_STORAGE_TAG)) {//有权限// 跳转到系统相册,选择图片,并返回Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);startActivityForResult(intent,1);}}@Overrideprotected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {super.onActivityResult(requestCode, resultCode, data);
// Log.d("ning","进来了"+resultCode+":"+resultCode);//获取图片路径if (requestCode==1 && resultCode == Activity.RESULT_OK &&data!=null){Uri selectedImage = data.getData();String[] filePathColumns ={MediaStore.Images.Media.DATA};Cursor query = getContentResolver().query(selectedImage, filePathColumns, null, null, null);query.moveToFirst();int columnIndex = query.getColumnIndex(filePathColumns[0]);String string = query.getString(columnIndex);Log.d("ning",string);uploadFile(string);query.close();}}public void uploadFile(String path){File file = new File(path);RequestBody requestBody = RequestBody.create(MediaType.parse("image/jp"),file);MultipartBody.Part part = MultipartBody.Part.createFormData("pic",file.getName(),requestBody);apiService.upload(part).enqueue(new Callback<Map<String, Object>>() {@Overridepublic void onResponse(Call<Map<String, Object>> call, Response<Map<String, Object>> response) {Log.d("ning",response.body().get("result").toString());}@Overridepublic void onFailure(Call<Map<String, Object>> call, Throwable t) {}});}}
8.实体类
public class Subject {private String episodes_info;private String rate;private Integer cover_x;private String title;private String url;private Boolean playable;private String cover;private String id;private Integer cover_y;private Boolean is_new;