package com.dayu.pipirrapp.net;
|
|
import static com.dayu.pipirrapp.bean.net.UplodFileState.STATE_DONE;
|
import static com.dayu.pipirrapp.bean.net.UplodFileState.STATE_ERROR;
|
import static com.dayu.pipirrapp.bean.net.UplodFileState.STATE_UPDING;
|
import static com.luck.picture.lib.thread.PictureThreadUtils.runOnUiThread;
|
|
import android.annotation.SuppressLint;
|
import android.content.Context;
|
import android.content.Intent;
|
import android.text.TextUtils;
|
import android.util.Log;
|
|
import com.dayu.pipirrapp.MyApplication;
|
import com.dayu.pipirrapp.activity.LoginActivity;
|
import com.dayu.pipirrapp.adapter.AddPictureAdapter;
|
import com.dayu.pipirrapp.bean.net.CodeResult;
|
import com.dayu.pipirrapp.bean.net.UplodFileState;
|
import com.dayu.pipirrapp.bean.net.WeatherResponse;
|
import com.dayu.pipirrapp.net.subscribers.BaseProgressSubscriber;
|
import com.dayu.pipirrapp.net.subscribers.CodeListener;
|
import com.dayu.pipirrapp.net.subscribers.ProgressSubscriber;
|
import com.dayu.pipirrapp.net.subscribers.SubscriberListener;
|
import com.dayu.pipirrapp.net.upload.ProgressRequestBody;
|
import com.dayu.pipirrapp.net.upload.UploadFileListener;
|
import com.dayu.pipirrapp.utils.CleanDataUtils;
|
import com.dayu.pipirrapp.utils.MapJpgUtils;
|
import com.dayu.pipirrapp.utils.MyJsonParser;
|
import com.dayu.pipirrapp.utils.MyLog;
|
import com.dayu.pipirrapp.utils.NetUtils;
|
import com.google.gson.internal.LinkedTreeMap;
|
|
import java.io.File;
|
import java.util.HashMap;
|
import java.util.List;
|
import java.util.Map;
|
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
import io.reactivex.rxjava3.core.Observable;
|
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
import io.reactivex.rxjava3.functions.Function;
|
import io.reactivex.rxjava3.schedulers.Schedulers;
|
import okhttp3.MediaType;
|
import okhttp3.MultipartBody;
|
import okhttp3.RequestBody;
|
import okhttp3.ResponseBody;
|
import retrofit2.Call;
|
import retrofit2.Callback;
|
import retrofit2.Response;
|
|
|
/**
|
* Copyright (C), 2023,
|
* Author: zuot
|
* Date: 2023-04-12 9:11
|
* Description:
|
*/
|
public class ApiManager {
|
|
static String TAG = "ApiManager";
|
|
static ApiManager apiManager;
|
//文件上传失败重复次数
|
int uplodFilerepeatSize = 3;
|
|
|
ApiService apiService;
|
// 管理订阅事件
|
private final CompositeDisposable compositeDisposable = new CompositeDisposable();
|
|
/**
|
* 初始化通信框架
|
*/
|
public static void init() {
|
if (apiManager == null) {
|
apiManager = new ApiManager();
|
}
|
}
|
|
public ApiManager() {
|
apiService = RetrofitClient.getInstance().getApiService();
|
|
}
|
|
public static ApiManager getInstance() {
|
return apiManager;
|
}
|
|
|
public <T> void requestPostLoading(final Context context, final String path, final Class<T> tClass, final Map<String, Object> params, final SubscriberListener listener) {
|
request(context, false, path, false, tClass, params, listener);
|
}
|
|
public <T> void requestPostHideLoading(final Context context, final String path, final Class<T> tClass, final Map<String, Object> params, final SubscriberListener listener) {
|
request(context, true, path, false, tClass, params, listener);
|
}
|
|
public <T> void requestPost(final Context context, final String path, final Class<T> tClass, final Map<String, Object> params, final SubscriberListener listener) {
|
request(context, false, path, false, tClass, params, listener);
|
}
|
|
public <T> void requestGet(final Context context, final String path, final Class<T> tClass, final Map<String, Object> params, final SubscriberListener listener) {
|
request(context, false, path, true, tClass, params, listener);
|
}
|
|
public <T> void requestGetHideLoading(final Context context, final String path, final Class<T> tClass, final Map<String, Object> params, final SubscriberListener listener) {
|
request(context, true, path, true, tClass, params, listener);
|
}
|
|
/**
|
* 发送请求
|
*
|
* @param context
|
* @param hideLoading 是否显示加载框 false:显示 true:隐藏
|
* @param path 请求路径,在UrlConfig中定义
|
* @param isGet 是否是Get请求 true:get 请求
|
* @param tClass 对应的数据类型
|
* @param params Post请求时,对应的参数
|
* @param listener 回调请求
|
* @param <T>
|
*/
|
public <T> void request(final Context context, final boolean hideLoading, final String path, final boolean isGet, final Class<T> tClass, final Map<String, Object> params, final SubscriberListener listener) {
|
Observable observable;
|
BaseProgressSubscriber<?> mySubscriber;
|
|
|
if (isGet) {
|
if (params == null) {
|
observable = apiService.requestGet(path, MyApplication.myApplication.token);
|
} else {
|
observable = apiService.requestGet(path, params, MyApplication.myApplication.token);
|
}
|
} else {
|
observable = apiService.requestPost(path, params);
|
}
|
|
mySubscriber = new ProgressSubscriber(context, hideLoading, listener);
|
observable.subscribeOn(Schedulers.io()).
|
map(new Function<Object, BaseResponse<T>>() {
|
@Override
|
public BaseResponse<T> apply(Object o) {
|
if (o instanceof BaseResponse) {
|
BaseResponse tem = (BaseResponse) o;
|
if (tem.getCode().equals(Constants.TOKEN_INVALID)) {
|
//当code为0000是跳转到登录界面
|
tem.setMsg("登录失效请重新登录");
|
redirectToLogin();
|
return tem;
|
}
|
BaseResponse<T> response = new BaseResponse<>();
|
response.setCode(tem.getCode());
|
if (!TextUtils.isEmpty(tem.getMsg())) {
|
response.setMsg(tem.getMsg());
|
} else {
|
response.setMsg("");
|
}
|
|
|
if (tClass != null) {
|
if (tem.getContent() instanceof Map) {
|
response.setContent(parseMapContent(tem.getContent(), tClass));
|
} else if (tem.getContent() instanceof List) {
|
response.setContent(parseListContent(tem.getContent(), tClass));
|
} else if (tem.getContent() instanceof Integer || tem.getContent() instanceof String) {
|
response.setContent((T) tem.getContent());
|
}
|
}
|
return response;
|
}
|
|
return null;
|
}
|
})
|
.unsubscribeOn(Schedulers.newThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
.subscribe(mySubscriber);
|
|
}
|
|
|
// 解析 Map 类型的数据
|
private <T> T parseMapContent(Object content, Class<T> tClass) {
|
try {
|
String jsonData = MyJsonParser.getJsontoMap((Map<String, Object>) content);
|
return MyJsonParser.getBeanFromJson(jsonData, tClass);
|
} catch (Exception e) {
|
Log.e(TAG, "Error parsing map content", e);
|
return null;
|
}
|
}
|
|
// 解析 List 类型的数据
|
private <T> T parseListContent(Object content, Class<T> tClass) {
|
try {
|
String jsonData = MyJsonParser.getJsonbyList((List<?>) content);
|
return (T) MyJsonParser.getListByJson(jsonData, tClass);
|
} catch (Exception e) {
|
Log.e(TAG, "Error parsing list content", e);
|
return null;
|
}
|
}
|
|
|
/**
|
* 获取天气
|
*
|
* @param data 经纬度(格式是 纬度:经度,英文冒号分隔)
|
* @param callback
|
* @param <T>
|
*/
|
public <T> void requestWeather(String data, Callback<WeatherResponse> callback) {
|
Map<String, Object> params = new HashMap<>();
|
params.put("key", "S6Tq4pvOakMuWRrg0");
|
params.put("location", data);
|
params.put("language", "zh-Hans");
|
params.put("unit", "c");
|
params.put("days", "3");
|
Call<WeatherResponse> call = apiService.requestWeather("https://api.seniverse.com/v3/weather/daily.json", params);
|
call.enqueue(callback);
|
}
|
|
|
/**
|
* 获取验证码
|
*
|
* @param params
|
* @param listener
|
* @param <T>
|
*/
|
public <T> void getCode(Map<String, Object> params, CodeListener listener) {
|
if (NetUtils.isNetworkAvailable(MyApplication.myApplication)) {
|
Observable observable;
|
observable = apiService.getCode(params);
|
observable.subscribeOn(Schedulers.io())
|
.unsubscribeOn(Schedulers.newThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
.subscribe(responseBody -> {
|
listener.onNext((CodeResult) responseBody);
|
}, throwable -> {
|
listener.error((Throwable) throwable);
|
});
|
} else {
|
listener.onNext(null);
|
}
|
|
}
|
|
|
/**
|
* 下载地图瓦片
|
*
|
* @param urlPath
|
*/
|
@SuppressLint("CheckResult")
|
public void donwLoadTile(Context context, String urlPath) {
|
if (NetUtils.isNetworkAvailable(context)) {
|
Observable<ResponseBody> observable;
|
observable = apiService.downloadTile(urlPath);
|
observable
|
// 网络请求在 I/O 线程中进行
|
.subscribeOn(Schedulers.io())
|
// 回调处理也在 I/O 线程
|
.observeOn(Schedulers.io())
|
.subscribe(
|
responseBody -> {
|
|
boolean success = false;
|
if (!MapJpgUtils.getInsatance().isHasFiles(urlPath)) {
|
success = MapJpgUtils.getInsatance().saveTileToCache(urlPath, responseBody);
|
}
|
if (success) {
|
Log.d(TAG, "Download success for tile: " + urlPath);
|
} else {
|
Log.e(TAG, "Failed to save tile to disk: " + urlPath);
|
}
|
},
|
throwable -> Log.e(TAG, "Download failed for tile: " + urlPath)
|
);
|
} else {
|
Log.e(TAG, "没有网络不下载: " + urlPath);
|
}
|
}
|
|
// 停止线程池,释放资源
|
public void clearDisposables() {
|
if (!compositeDisposable.isDisposed()) {
|
compositeDisposable.dispose();
|
}
|
}
|
|
|
// public void uploadFile(final Context context, final UplodFileState uplodData, final UploadFileListener listener) {
|
// uploadFile(context, uplodData, listener, null);
|
// }
|
|
/**
|
* 上传图片文件
|
*
|
* @param context
|
* @param uplodData
|
* @param listener
|
*/
|
public void uploadFile(final Context context, final UplodFileState uplodData, final UploadFileListener listener, final AddPictureAdapter adapter) {
|
|
if (!TextUtils.isEmpty(uplodData.getFilePath())) {
|
MyLog.d("progressRequestBody_uploadFile>>>" + "path:" + uplodData.getFilePath() + ">>>uploadType:" + uplodData.getUploadType());
|
uplodData.setState(STATE_UPDING);
|
File file = new File(uplodData.getFilePath());
|
RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
|
ProgressRequestBody progressRequestBody = new ProgressRequestBody(requestBody, (bytesWritten, contentLength, done) -> {
|
// MyLog.d("progressRequestBody>>>" + "bytesWritten:" + bytesWritten + ">>>contentLength: " + contentLength );
|
// 更新进度条或进行其他操作
|
int progress = (int) (100 * bytesWritten / contentLength);
|
// 例如:更新 ProgressBar 或显示进度
|
runOnUiThread(() -> {
|
if (progress <5) {
|
uplodData.setProgress(0);
|
}
|
// 进度条更新代码
|
if (adapter != null && uplodData.getAdapterPosition() != -1) {
|
//优化不频繁更新进度
|
if (progress - uplodData.getProgress() > 5 || progress == 100) {
|
uplodData.setProgress(progress);
|
adapter.updateProgress(uplodData);
|
|
}
|
|
}
|
MyLog.d("progressRequestBodyHolder>>>path" + "adapterPosition:" + uplodData.getAdapterPosition() + ">>>上传进度: " + progress + "%");
|
});
|
|
});
|
MultipartBody.Part body = MultipartBody.Part.createFormData("file", file.getName(), progressRequestBody);
|
RequestBody description = RequestBody.create(MediaType.parse("text/plain"), "file description");
|
Call<BaseResponse> uploadFile = null;
|
switch (uplodData.getUploadType()) {
|
case UplodFileState.IMG_TYPE:
|
uploadFile = apiService.uploadImgFile(body, description);
|
break;
|
case UplodFileState.VIDEO_TYPE:
|
uploadFile = apiService.uploadVideoFile(body, description);
|
break;
|
default:
|
uploadFile = apiService.uploadImgFile(body, description);
|
break;
|
}
|
|
uplodData.setThisCall(uploadFile);
|
uploadFile.enqueue(new Callback<BaseResponse>() {
|
@Override
|
public void onResponse(Call<BaseResponse> call, Response<BaseResponse> response) {
|
if (response.body() != null) {
|
if (response.body().isSuccess()) {
|
uplodData.setState(STATE_DONE);
|
uplodData.setPostId(((LinkedTreeMap) response.body().getContent()).get("id").toString());
|
uplodData.setWebPath(((LinkedTreeMap) response.body().getContent()).get("webPath").toString());
|
listener.onBack(uplodData);
|
} else {
|
MyLog.d("progressRequestBody>>>" + response.body().getMsg());
|
if (uplodData.getNumber() <= uplodFilerepeatSize) {
|
uplodData.setNumber(uplodData.getNumber() + 1);
|
uplodData.setState(STATE_ERROR);
|
uploadFile(context, uplodData, listener, adapter);
|
} else {
|
uplodData.setState(STATE_ERROR);
|
uplodData.setNumber(0);
|
listener.onBack(uplodData);
|
}
|
}
|
}
|
}
|
|
@Override
|
public void onFailure(Call<BaseResponse> call, Throwable t) {
|
MyLog.d("progressRequestBody>>>" + "onFailure:" + t.getMessage());
|
if (!t.getMessage().equals("Canceled")) {
|
uplodData.setState(STATE_ERROR);
|
if (uplodData.getNumber() <= uplodFilerepeatSize) {
|
uplodData.setNumber(uplodData.getNumber() + 1);
|
uploadFile(context, uplodData, listener, adapter);
|
} else {
|
uplodData.setNumber(0);
|
listener.onBack(uplodData);
|
}
|
}
|
|
}
|
});
|
} else {
|
uplodData.setState(STATE_ERROR);
|
listener.onBack(uplodData);
|
}
|
}
|
|
|
/**
|
* 当code为“0000”时跳转到登录界面
|
*/
|
private void redirectToLogin() {
|
|
Context context = MyApplication.myApplication.getApplicationContext();
|
CleanDataUtils.cleanUserData(context);
|
Intent intent = new Intent(context, LoginActivity.class); // Assuming LoginActivity is your login screen
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); // Clear task stack
|
context.startActivity(intent);
|
}
|
}
|