上传文件至 /

This commit is contained in:
XuYuqi 2025-07-25 14:29:27 +08:00
parent 43acbcfd33
commit 4372a7fc16
4 changed files with 973 additions and 957 deletions

View File

@ -1,4 +1,3 @@
package com.example.myapplication.Service; package com.example.myapplication.Service;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
@ -18,6 +17,8 @@ import android.os.Build;
import android.os.Handler; import android.os.Handler;
import android.os.IBinder; import android.os.IBinder;
import android.os.Looper; import android.os.Looper;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.text.Editable; import android.text.Editable;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.TextWatcher; import android.text.TextWatcher;
@ -75,9 +76,11 @@ public class FloatingWindowService extends Service {
private String lastUnitName = ""; private String lastUnitName = "";
private AppDatabase database; private AppDatabase database;
private TurbineDao turbineDao; private TurbineDao turbineDao;
private AutoCompleteTextView actvUnit; // 替换原来的EditText private AutoCompleteTextView actvUnit;
private ArrayAdapter<Turbine> turbineAdapter; private ArrayAdapter<Turbine> turbineAdapter;
private String projectID; private String projectID;
public static boolean isFloatingWindowShowing = false;
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
@Override @Override
public void onCreate() { public void onCreate() {
@ -85,19 +88,17 @@ public class FloatingWindowService extends Service {
createNotificationChannel(); createNotificationChannel();
database = AppDatabase.getDatabase(this); database = AppDatabase.getDatabase(this);
turbineDao = database.turbineDao(); turbineDao = database.turbineDao();
createNotificationChannel();
showFloatingWindow(); showFloatingWindow();
} }
@Override @Override
public int onStartCommand(Intent intent, int flags, int startId) { public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null && intent.hasExtra(EXTRA_PROJECT_ID)) { if (intent != null && intent.hasExtra(EXTRA_PROJECT_ID)) {
projectID = intent.getStringExtra(EXTRA_PROJECT_ID); projectID = intent.getStringExtra(EXTRA_PROJECT_ID);
} }
return super.onStartCommand(intent, flags, startId); return super.onStartCommand(intent, flags, startId);
} }
private void createNotificationChannel() { private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel( NotificationChannel channel = new NotificationChannel(
@ -112,6 +113,7 @@ public class FloatingWindowService extends Service {
private void showFloatingWindow() { private void showFloatingWindow() {
// 创建前台服务通知 // 创建前台服务通知
isFloatingWindowShowing = true;
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID) Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("悬浮窗服务运行中") .setContentTitle("悬浮窗服务运行中")
.setContentText("正在显示悬浮提示框") .setContentText("正在显示悬浮提示框")
@ -120,11 +122,9 @@ public class FloatingWindowService extends Service {
.build(); .build();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
// Android 10+ 需要指定服务类型
startForeground(NOTIFICATION_ID, notification, startForeground(NOTIFICATION_ID, notification,
ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE); ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE);
} else { } else {
// Android 8.0-9.0
startForeground(NOTIFICATION_ID, notification); startForeground(NOTIFICATION_ID, notification);
} }
@ -154,14 +154,57 @@ public class FloatingWindowService extends Service {
setupTurbineDropdown(); setupTurbineDropdown();
radioGroup = floatingView.findViewById(R.id.radioGroup); radioGroup = floatingView.findViewById(R.id.radioGroup);
// 设置关闭按钮点击事件
View btnClose = floatingView.findViewById(R.id.btnClose);
btnClose.setOnClickListener(v -> {
// 震动反馈
Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
if (vibrator != null && vibrator.hasVibrator()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
vibrator.vibrate(VibrationEffect.createOneShot(50, VibrationEffect.DEFAULT_AMPLITUDE));
} else {
vibrator.vibrate(50);
}
}
closeFloatingWindow();
});
setupDragListener(params); setupDragListener(params);
setupValueChangeListeners(); setupValueChangeListeners();
setupAutoCompleteBehavior(); setupAutoCompleteBehavior();
}
private void closeFloatingWindow() {
if (floatingView != null && floatingView.getWindowToken() != null) {
// 添加淡出动画
floatingView.animate()
.alpha(0f)
.setDuration(200)
.withEndAction(() -> {
removeFloatingView();
stopSelf();
})
.start();
} else {
removeFloatingView();
stopSelf();
}
isFloatingWindowShowing = false;
}
private synchronized void removeFloatingView() {
try {
if (windowManager != null && floatingView != null && floatingView.getWindowToken() != null) {
windowManager.removeView(floatingView);
}
} catch (IllegalArgumentException e) {
Log.e("FloatingWindow", "View already removed", e);
} finally {
floatingView = null;
}
} }
private void setupAutoCompleteBehavior() { private void setupAutoCompleteBehavior() {
actvUnit.setFocusableInTouchMode(true); // 允许触摸获取焦点 actvUnit.setFocusableInTouchMode(true);
actvUnit.setFocusable(true); actvUnit.setFocusable(true);
actvUnit.setOnClickListener(v -> { actvUnit.setOnClickListener(v -> {
if (turbineAdapter.getCount() > 0) { if (turbineAdapter.getCount() > 0) {
@ -190,6 +233,7 @@ public class FloatingWindowService extends Service {
return false; return false;
}); });
} }
private void showSoftInputDelayed(View view) { private void showSoftInputDelayed(View view) {
view.postDelayed(() -> { view.postDelayed(() -> {
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
@ -205,52 +249,55 @@ public class FloatingWindowService extends Service {
imm.hideSoftInputFromWindow(view.getWindowToken(), 0); imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
} }
} }
// 移除 setupInputMethod() 方法因为功能已整合到上面的方法中
private void setupDragListener(WindowManager.LayoutParams params) { private void setupDragListener(WindowManager.LayoutParams params) {
floatingView.findViewById(R.id.floatingContainer).setOnTouchListener(new View.OnTouchListener() { View dragHandle = floatingView.findViewById(R.id.floatingContainer);
dragHandle.setOnTouchListener(new View.OnTouchListener() {
private int initialX, initialY; private int initialX, initialY;
private float initialTouchX, initialTouchY; private float initialTouchX, initialTouchY;
@Override @Override
public boolean onTouch(View v, MotionEvent event) { public boolean onTouch(View v, MotionEvent event) {
// 检查是否点击在关闭按钮上
if (!isViewAttached()) {
return false;
}
Rect closeButtonRect = new Rect();
floatingView.findViewById(R.id.btnClose).getGlobalVisibleRect(closeButtonRect);
if (closeButtonRect.contains((int)event.getRawX(), (int)event.getRawY())) {
return false;
}
// 检查是否点击在输入区域
Rect inputRect = new Rect();
actvUnit.getGlobalVisibleRect(inputRect);
if (inputRect.contains((int)event.getRawX(), (int)event.getRawY())) {
return false;
}
switch (event.getAction()) { switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_DOWN:
// 检查是否点击在输入区域
Rect rect = new Rect();
actvUnit.getGlobalVisibleRect(rect);
if (rect.contains((int)event.getRawX(), (int)event.getRawY())) {
// 如果是点击输入区域不处理拖动让输入框获取焦点
return false;
}
// 记录初始位置
initialX = params.x; initialX = params.x;
initialY = params.y; initialY = params.y;
initialTouchX = event.getRawX(); initialTouchX = event.getRawX();
initialTouchY = event.getRawY(); initialTouchY = event.getRawY();
// 隐藏键盘和下拉菜单
hideSoftInput(actvUnit);
actvUnit.dismissDropDown();
return true; return true;
case MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_MOVE:
// 更新悬浮窗位置
params.x = initialX + (int)(event.getRawX() - initialTouchX); params.x = initialX + (int)(event.getRawX() - initialTouchX);
params.y = initialY + (int)(event.getRawY() - initialTouchY); params.y = initialY + (int)(event.getRawY() - initialTouchY);
windowManager.updateViewLayout(floatingView, params); windowManager.updateViewLayout(floatingView, params);
return true; return true;
case MotionEvent.ACTION_UP: case MotionEvent.ACTION_UP:
// 拖动结束不处理焦点
return true; return true;
} }
return false; return false;
} }
}); });
} }
private void setupTurbineDropdown() { private void setupTurbineDropdown() {
turbineAdapter = new ArrayAdapter<Turbine>(this, turbineAdapter = new ArrayAdapter<Turbine>(this,
R.layout.dropdown_item, R.id.text1) { R.layout.dropdown_item, R.id.text1) {
@ -261,7 +308,6 @@ public class FloatingWindowService extends Service {
TextView textView = view.findViewById(R.id.text1); TextView textView = view.findViewById(R.id.text1);
Turbine turbine = getItem(position); Turbine turbine = getItem(position);
if (turbine != null) { if (turbine != null) {
// 显示更详细的信息
textView.setText(String.format(turbine.turbineName)); textView.setText(String.format(turbine.turbineName));
textView.setSingleLine(false); textView.setSingleLine(false);
textView.setMaxLines(3); textView.setMaxLines(3);
@ -277,17 +323,14 @@ public class FloatingWindowService extends Service {
FilterResults results = new FilterResults(); FilterResults results = new FilterResults();
List<Turbine> filtered; List<Turbine> filtered;
if (TextUtils.isEmpty(constraint)) { if (TextUtils.isEmpty(constraint)) {
// 无输入条件时显示全部数据
filtered = turbineDao.getTurbinesByProject(projectID); filtered = turbineDao.getTurbinesByProject(projectID);
} else { } else {
// 有输入条件时执行搜索
filtered = turbineDao.searchTurbines(projectID, "%" + constraint + "%"); filtered = turbineDao.searchTurbines(projectID, "%" + constraint + "%");
} }
results.values = filtered; results.values = filtered;
results.count = filtered.size(); results.count = filtered.size();
return results; return results;
} }
@Override @Override
@ -308,11 +351,10 @@ public class FloatingWindowService extends Service {
}; };
actvUnit.setAdapter(turbineAdapter); actvUnit.setAdapter(turbineAdapter);
actvUnit.setThreshold(0); // 输入1个字符后开始搜索 actvUnit.setThreshold(0);
actvUnit.setDropDownHeight(ViewGroup.LayoutParams.WRAP_CONTENT); actvUnit.setDropDownHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
actvUnit.setDropDownVerticalOffset(10); // 下拉框与输入框的垂直偏移 actvUnit.setDropDownVerticalOffset(10);
// 设置输入监听
actvUnit.addTextChangedListener(new TextWatcher() { actvUnit.addTextChangedListener(new TextWatcher() {
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {} @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@Override public void afterTextChanged(Editable s) {} @Override public void afterTextChanged(Editable s) {}
@ -321,9 +363,8 @@ public class FloatingWindowService extends Service {
public void onTextChanged(CharSequence s, int start, int before, int count) { public void onTextChanged(CharSequence s, int start, int before, int count) {
String input=s.toString().trim(); String input=s.toString().trim();
lastUnit = input; lastUnit = input;
lastUnitName = input; // 如果没有匹配项使用原始输入作为名称 lastUnitName = input;
if (turbineAdapter.getCount() > 0 && !TextUtils.isEmpty(input)) { if (turbineAdapter.getCount() > 0 && !TextUtils.isEmpty(input)) {
// 尝试查找完全匹配的项
for (int i = 0; i < turbineAdapter.getCount(); i++) { for (int i = 0; i < turbineAdapter.getCount(); i++) {
Turbine turbine = turbineAdapter.getItem(i); Turbine turbine = turbineAdapter.getItem(i);
if (turbine != null && turbine.turbineName.equalsIgnoreCase(input)) { if (turbine != null && turbine.turbineName.equalsIgnoreCase(input)) {
@ -333,7 +374,7 @@ public class FloatingWindowService extends Service {
} }
} }
} }
checkAndSendUpdate(); // 实时触发检查 checkAndSendUpdate();
} }
}); });
@ -344,14 +385,11 @@ public class FloatingWindowService extends Service {
ExecutorService executor = Executors.newSingleThreadExecutor(); ExecutorService executor = Executors.newSingleThreadExecutor();
executor.execute(() -> { executor.execute(() -> {
try { try {
// 先检查本地是否有数据
List<Turbine> localTurbines = turbineDao.getTurbinesByProject(projectID); List<Turbine> localTurbines = turbineDao.getTurbinesByProject(projectID);
if (localTurbines.isEmpty() || isNetworkAvailable()) { if (localTurbines.isEmpty() || isNetworkAvailable()) {
// 如果本地无数据或有网络尝试从API获取
fetchTurbinesFromApi(); fetchTurbinesFromApi();
} else { } else {
// 使用本地数据更新UI
mainHandler.post(() -> updateTurbineList(localTurbines)); mainHandler.post(() -> updateTurbineList(localTurbines));
} }
} catch (Exception e) { } catch (Exception e) {
@ -359,13 +397,13 @@ public class FloatingWindowService extends Service {
} }
}); });
} }
private void updateTurbineList(List<Turbine> turbines) { private void updateTurbineList(List<Turbine> turbines) {
turbineAdapter.clear(); turbineAdapter.clear();
if (!turbines.isEmpty()) { if (!turbines.isEmpty()) {
turbineAdapter.addAll(turbines); turbineAdapter.addAll(turbines);
} }
// 如果输入框有内容重新过滤
if (!TextUtils.isEmpty(actvUnit.getText())) { if (!TextUtils.isEmpty(actvUnit.getText())) {
turbineAdapter.getFilter().filter(actvUnit.getText()); turbineAdapter.getFilter().filter(actvUnit.getText());
} }
@ -401,16 +439,14 @@ public class FloatingWindowService extends Service {
List<Turbine> turbines = apiResponse.getData(); List<Turbine> turbines = apiResponse.getData();
Log.d("API_SUCCESS", "Fetched " + turbines.size() + " turbines"); Log.d("API_SUCCESS", "Fetched " + turbines.size() + " turbines");
// 保存到数据库子线程
new Thread(() -> { new Thread(() -> {
try { try {
turbineDao.deleteByProjectId(projectID); turbineDao.deleteByProjectId(projectID);
for (Turbine turbine : turbines) { for (Turbine turbine : turbines) {
turbine.projectId = projectID; // 确保 projectId 正确 turbine.projectId = projectID;
} }
turbineDao.insertAll(turbines); turbineDao.insertAll(turbines);
// 使用 mainHandler 更新 UI主线程
mainHandler.post(() -> { mainHandler.post(() -> {
updateTurbineList(turbines); updateTurbineList(turbines);
showToast("数据加载成功"); showToast("数据加载成功");
@ -420,19 +456,14 @@ public class FloatingWindowService extends Service {
mainHandler.post(() -> showToast("保存数据失败: " + e.getMessage())); mainHandler.post(() -> showToast("保存数据失败: " + e.getMessage()));
} }
}).start(); }).start();
} else { } else {
// API 返回错误 code != 200
String errorMsg = "服务器错误: " + apiResponse.getCode() + " - " + apiResponse.getMsg(); String errorMsg = "服务器错误: " + apiResponse.getCode() + " - " + apiResponse.getMsg();
Log.e("API_ERROR", errorMsg); Log.e("API_ERROR", errorMsg);
mainHandler.post(() -> showToast(errorMsg)); mainHandler.post(() -> showToast(errorMsg));
} }
} else { } else {
// HTTP 状态码非 200 404500
String errorMsg = "请求失败: HTTP " + response.code(); String errorMsg = "请求失败: HTTP " + response.code();
if (response.errorBody() != null) { if (response.errorBody() != null) {
try { try {
errorMsg += "\n" + response.errorBody().string(); errorMsg += "\n" + response.errorBody().string();
} catch (IOException e) { } catch (IOException e) {
@ -447,7 +478,6 @@ public class FloatingWindowService extends Service {
@Override @Override
public void onFailure(Call<ApiResponse<List<Turbine>>> call, Throwable t) { public void onFailure(Call<ApiResponse<List<Turbine>>> call, Throwable t) {
// 网络请求失败如无网络超时
String errorMsg = "网络错误: " + t.getMessage(); String errorMsg = "网络错误: " + t.getMessage();
Log.e("NETWORK_ERROR", errorMsg, t); Log.e("NETWORK_ERROR", errorMsg, t);
mainHandler.post(() -> showToast(errorMsg)); mainHandler.post(() -> showToast(errorMsg));
@ -455,12 +485,11 @@ public class FloatingWindowService extends Service {
}); });
} }
// 显示 Toast 的辅助方法
private void showToast(String message) { private void showToast(String message) {
Toast.makeText(this, message, Toast.LENGTH_LONG).show(); Toast.makeText(this, message, Toast.LENGTH_LONG).show();
} }
private void setupValueChangeListeners() { private void setupValueChangeListeners() {
// 监听机组号输入框变化
actvUnit.addTextChangedListener(new TextWatcher() { actvUnit.addTextChangedListener(new TextWatcher() {
@Override @Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {} public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@ -469,21 +498,19 @@ public class FloatingWindowService extends Service {
public void onTextChanged(CharSequence s, int start, int before, int count) {} public void onTextChanged(CharSequence s, int start, int before, int count) {}
@Override @Override
public void afterTextChanged(Editable s) { public void afterTextChanged(Editable s) {}
}
}); });
// 添加下拉框项点击监听
actvUnit.setOnItemClickListener((parent, view, position, id) -> { actvUnit.setOnItemClickListener((parent, view, position, id) -> {
Turbine selected = turbineAdapter.getItem(position); Turbine selected = turbineAdapter.getItem(position);
if (selected != null) { if (selected != null) {
lastUnit = selected.turbineId; lastUnit = selected.turbineId;
lastUnitName = selected.turbineName; lastUnitName = selected.turbineName;
actvUnit.setText(selected.turbineName); // 显示名称 actvUnit.setText(selected.turbineName);
checkAndSendUpdate(); checkAndSendUpdate();
} }
}); });
// 监听叶片号选择变化
radioGroup.setOnCheckedChangeListener((group, checkedId) -> { radioGroup.setOnCheckedChangeListener((group, checkedId) -> {
int currentBlade = 0; int currentBlade = 0;
if (checkedId != -1) { if (checkedId != -1) {
@ -499,7 +526,6 @@ public class FloatingWindowService extends Service {
} }
private void checkAndSendUpdate() { private void checkAndSendUpdate() {
// 只有当两个值都有有效变化时才发送广播
if (!lastUnit.isEmpty() && lastBlade != -1) { if (!lastUnit.isEmpty() && lastBlade != -1) {
sendUpdateBroadcast(); sendUpdateBroadcast();
highlightChanges(); highlightChanges();
@ -510,13 +536,12 @@ public class FloatingWindowService extends Service {
Intent intent = new Intent("com.example.myapplication.UPDATE_VALUES"); Intent intent = new Intent("com.example.myapplication.UPDATE_VALUES");
intent.putExtra("unit", lastUnit); intent.putExtra("unit", lastUnit);
intent.putExtra("blade", lastBlade); intent.putExtra("blade", lastBlade);
intent.putExtra("unitName", lastUnitName); // 发送机组名称 intent.putExtra("unitName", lastUnitName);
intent.setPackage(getPackageName()); intent.setPackage(getPackageName());
sendBroadcast(intent); sendBroadcast(intent);
} }
private void highlightChanges() { private void highlightChanges() {
// 高亮效果 - 改变背景色然后恢复
int originalColor = actvUnit.getSolidColor(); int originalColor = actvUnit.getSolidColor();
actvUnit.setBackgroundColor(Color.YELLOW); actvUnit.setBackgroundColor(Color.YELLOW);
radioGroup.setBackgroundColor(Color.YELLOW); radioGroup.setBackgroundColor(Color.YELLOW);
@ -524,7 +549,7 @@ public class FloatingWindowService extends Service {
new Handler().postDelayed(() -> { new Handler().postDelayed(() -> {
actvUnit.setBackgroundColor(originalColor); actvUnit.setBackgroundColor(originalColor);
radioGroup.setBackgroundColor(Color.TRANSPARENT); radioGroup.setBackgroundColor(Color.TRANSPARENT);
}, 300); // 0.3秒后恢复 }, 300);
} }
@Override @Override
@ -532,14 +557,26 @@ public class FloatingWindowService extends Service {
super.onDestroy(); super.onDestroy();
hideSoftInput(actvUnit); hideSoftInput(actvUnit);
actvUnit.dismissDropDown(); actvUnit.dismissDropDown();
if (floatingView != null && windowManager != null) { isFloatingWindowShowing = false;
windowManager.removeView(floatingView);
} // 直接调用移除方法不再重复执行stopSelf()
removeFloatingView();
mainHandler.removeCallbacksAndMessages(null); mainHandler.removeCallbacksAndMessages(null);
} }
private boolean isViewAttached() {
return floatingView != null
&& floatingView.getWindowToken() != null
&& windowManager != null;
}
@Override @Override
public IBinder onBind(Intent intent) { public IBinder onBind(Intent intent) {
return null; return null;
} }
public static void closeFloatingWindow(Context context) {
isFloatingWindowShowing = false;
Intent serviceIntent = new Intent(context, FloatingWindowService.class);
context.stopService(serviceIntent);
}
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,4 @@
package com.example.myapplication.Service; package com.example.myapplication.Service;
import android.app.Notification; import android.app.Notification;
import android.app.NotificationChannel; import android.app.NotificationChannel;
import android.app.NotificationManager; import android.app.NotificationManager;
@ -7,6 +6,7 @@ import android.app.PendingIntent;
import android.app.Service; import android.app.Service;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences;
import android.database.ContentObserver; import android.database.ContentObserver;
import android.database.Cursor; import android.database.Cursor;
import android.location.Location; import android.location.Location;
@ -23,6 +23,7 @@ import android.provider.MediaStore;
import android.util.Log; import android.util.Log;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationCompat;
import androidx.room.Room; import androidx.room.Room;
@ -33,6 +34,8 @@ import com.example.myapplication.Tool.NotificationReceiver;
import com.example.myapplication.model.ImageEntity; import com.example.myapplication.model.ImageEntity;
import com.example.myapplication.model.SharedDataManager; import com.example.myapplication.model.SharedDataManager;
import org.json.JSONObject;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
@ -40,6 +43,7 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import okhttp3.HttpUrl;
import okhttp3.MediaType; import okhttp3.MediaType;
import okhttp3.MultipartBody; import okhttp3.MultipartBody;
import okhttp3.OkHttpClient; import okhttp3.OkHttpClient;
@ -55,17 +59,19 @@ public class PhotoMonitoringService extends Service implements SharedDataManager
// 锁对象 // 锁对象
private final Object monitoringLock = new Object(); private final Object monitoringLock = new Object();
private final Object uploadLock = new Object(); private final Object uploadLock = new Object();
private long lastSuccessToastTime = 0;
private static final long TOAST_THROTTLE_INTERVAL = 1500;
// 状态标志 // 状态标志
private boolean isMonitoring = false; private boolean isMonitoring = false;
private boolean isUploading = false; private boolean isUploading = false;
private boolean isRecording = false; private boolean isRecording = false;
private int successCount = 0; private int successCount = 0;
private int failureCount = 0; private int totalUploadedCount = 0; // 新增总上传成功计数
// 组件 // 组件
private ContentObserver contentObserver; private ContentObserver contentObserver;
private final ExecutorService executor = Executors.newFixedThreadPool(6); private final ExecutorService executor = Executors.newFixedThreadPool(5);
private final OkHttpClient httpClient = new OkHttpClient.Builder() private final OkHttpClient httpClient = new OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS) // 连接超时 .connectTimeout(30, TimeUnit.SECONDS) // 连接超时
.readTimeout(60, TimeUnit.SECONDS) // 读取超时 .readTimeout(60, TimeUnit.SECONDS) // 读取超时
@ -94,85 +100,94 @@ public class PhotoMonitoringService extends Service implements SharedDataManager
// 其他状态 // 其他状态
private long lastPhotoId = 0; private long lastPhotoId = 0;
private String currentAudioPath="0"; private String currentAudioPath="-1";
private String imgpath="-1"; private String imgpath="-1";
private String partid="-1"; private String partid="-1";
private String UserId;
// 回调接口
private MonitoringCallback callback;
@Override @Override
public void onImagePathChanged(String newPath) { public void onImageIdChanged(String newId) {
} }
@Override @Override
public void onTokenChanged(String newToken) { public void onTokenChanged(String newToken) {
} }
@Override @Override
public void onUserChanged(String newUser) { public void onUserChanged(String newUser) {
user=newUser; user=newUser;
} }
@Override @Override
public void onAudioPathChanged(String newAudioPath) { public void onAudioPathChanged(String newAudioPath) {
currentAudioPath=newAudioPath; currentAudioPath=newAudioPath;
} }
@Override @Override
public void onProjectIdChanged(String newProjectId) { public void onProjectIdChanged(String newProjectId) {
projectId=newProjectId; projectId=newProjectId;
} }
@Override @Override
public void onUnitChanged(String newUnit) { public void onUnitChanged(String newUnit) {
unit=newUnit; unit=newUnit;
} }
@Override @Override
public void onBladeChanged(int newBlade) { public void onBladeChanged(int newBlade) {
blade=newBlade; blade=newBlade;
} }
@Override @Override
public void onPartidChanged(String newPartid) { public void onPartidChanged(String newPartid) {
partid=newPartid; partid=newPartid;
} }
@Override @Override
public void onChooseImageSourceChanged(String newChooseImageSource) { public void onChooseImageSourceChanged(String newChooseImageSource) {
ChooseImageSource=newChooseImageSource; ChooseImageSource=newChooseImageSource;
} }
@Override @Override
public void onUnitNameChanged(String newUnitName) { public void onUnitNameChanged(String newUnitName) {
unitName=newUnitName; unitName=newUnitName;
} }
@Override @Override
public void onIsRecordingChanged(boolean newisRecording) { public void onIsRecordingChanged(boolean newisRecording) {
isRecording=newisRecording; isRecording=newisRecording;
} }
@Override @Override
public void onUploadingStatusChanged(boolean isUploading) { public void onUploadingStatusChanged(boolean isUploading) {
this.isUploading=isUploading; this.isUploading=isUploading;
} }
public interface MonitoringCallback { @Override
void onUploadSuccess(String filePath); public void onLocationChanged(Location newLocation) {
void onUploadFailure(String filePath, String error); lastKnownLocation=newLocation;
void onStatusChanged(boolean isMonitoring);
} }
SharedDataManager dataManager ;
@Override
public void onOtherMsgChanged(String msg) {
}
SharedDataManager dataManager;
@Override @Override
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
createNotificationChannel(); createNotificationChannel();
SharedPreferences prefs = getSharedPreferences("WeatherPrefs", MODE_PRIVATE);
Weather = prefs.getString("weather", "0");
Temperator = prefs.getString("temperature", "0");
Humidity = prefs.getString("humidity", "0");
SharedPreferences sharedPreferences = getSharedPreferences("LoginPrefs", Context.MODE_PRIVATE);
// 初始化数据库 // 初始化数据库
UserId=sharedPreferences.getString("userid","-1");
db = Room.databaseBuilder(getApplicationContext(), db = Room.databaseBuilder(getApplicationContext(),
AppDatabase.class, "image-database").build(); AppDatabase.class, "image-database").build();
db2 = Room.databaseBuilder(getApplicationContext(), db2 = Room.databaseBuilder(getApplicationContext(),
@ -180,13 +195,20 @@ public class PhotoMonitoringService extends Service implements SharedDataManager
// 初始化位置管理器 // 初始化位置管理器
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
dataManager=SharedDataManager.getInstance(); dataManager=SharedDataManager.getInstance();
dataManager.addListener(this); dataManager.addListener(this);
updateFromSharedData(); updateFromSharedData();
// 初始化时从数据库获取已上传成功的数量
totalUploadedCount = 0;
updateNotification("partid"+partid);
} }
private void updateFromSharedData() { private void updateFromSharedData() {
dataManager = SharedDataManager.getInstance(); dataManager = SharedDataManager.getInstance();
this.token = dataManager.getToken(); this.token = dataManager.getToken();
this.user = dataManager.getUser(); this.user = dataManager.getUser();
this.currentAudioPath = dataManager.getAudioPath(); this.currentAudioPath = dataManager.getAudioPath();
@ -197,10 +219,11 @@ dataManager=SharedDataManager.getInstance();
this.unitName = dataManager.getUnitName(); this.unitName = dataManager.getUnitName();
this.partid=dataManager.getPartid(); this.partid=dataManager.getPartid();
this.isUploading=dataManager.getisUploading(); this.isUploading=dataManager.getisUploading();
this.lastKnownLocation=dataManager.getLocation();
} }
@Override @Override
public int onStartCommand(Intent intent, int flags, int startId) { public int onStartCommand(Intent intent, int flags, int startId) {
// 从intent中获取配置参数
if (intent != null && "start_monitoring".equals(intent.getStringExtra("command"))) { if (intent != null && "start_monitoring".equals(intent.getStringExtra("command"))) {
startMonitoring(); startMonitoring();
} }
@ -222,9 +245,7 @@ dataManager=SharedDataManager.getInstance();
super.onDestroy(); super.onDestroy();
} }
// 公共接口方法
public void startMonitoring() { public void startMonitoring() {
synchronized (monitoringLock) { synchronized (monitoringLock) {
if (isMonitoring) return; if (isMonitoring) return;
@ -247,11 +268,7 @@ dataManager=SharedDataManager.getInstance();
); );
isMonitoring = true; isMonitoring = true;
if (callback != null) {
callback.onStatusChanged(true);
}
// 检查已有照片
executor.execute(() -> { executor.execute(() -> {
List<ImageEntity> history = db2.imageDao().getAll(); List<ImageEntity> history = db2.imageDao().getAll();
if (history != null && !history.isEmpty()) { if (history != null && !history.isEmpty()) {
@ -278,25 +295,17 @@ dataManager=SharedDataManager.getInstance();
getContentResolver().unregisterContentObserver(contentObserver); getContentResolver().unregisterContentObserver(contentObserver);
contentObserver = null; contentObserver = null;
} }
if (callback != null) {
callback.onStatusChanged(false);
}
isMonitoring=false; isMonitoring=false;
} }
} }
private String getPartName(int b)
{ private String getPartName(int b) {
return "叶片" +b; return "叶片" +b;
} }
public void setCallback(MonitoringCallback callback) {
this.callback = callback;
}
public boolean isMonitoring() {
return isMonitoring;
}
// 私有方法
private void checkNewPhotos() { private void checkNewPhotos() {
String[] projection = { String[] projection = {
MediaStore.Images.Media._ID, MediaStore.Images.Media._ID,
@ -334,21 +343,12 @@ dataManager=SharedDataManager.getInstance();
long id = cursor.getLong(0); long id = cursor.getLong(0);
String path = cursor.getString(1); String path = cursor.getString(1);
imgpath = path; imgpath = path;
dataManager.setImagePath(imgpath);
long time = cursor.getLong(2) * 1000; long time = cursor.getLong(2) * 1000;
double latitude = cursor.getDouble(3); double latitude = cursor.getDouble(3);
double longitude = cursor.getDouble(4); double longitude = cursor.getDouble(4);
double altitude = 0.0; double altitude = 0.0;
try {
Location lastLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (lastLocation != null) {
lastKnownLocation = lastLocation;
}
} catch (SecurityException e) {
Log.w("PhotoMonitoringService", "Location permission not granted");
}
if (lastKnownLocation != null) { if (lastKnownLocation != null) {
latitude = lastKnownLocation.getLatitude(); latitude = lastKnownLocation.getLatitude();
longitude = lastKnownLocation.getLongitude(); longitude = lastKnownLocation.getLongitude();
@ -365,20 +365,17 @@ dataManager=SharedDataManager.getInstance();
Log.e("PhotoMonitoringService", "Error reading EXIF data", e); Log.e("PhotoMonitoringService", "Error reading EXIF data", e);
} }
String audioPath = currentAudioPath == null ? "0" : currentAudioPath; String audioPath = currentAudioPath;
lastPhotoId = Math.max(lastPhotoId, id); lastPhotoId = Math.max(lastPhotoId, id);
if (isNetworkAvailable() && !isRecording) { if (isNetworkAvailable() && !isRecording) {
uploadNewPhoto(path, time, audioPath, latitude, longitude, altitude); uploadNewPhoto(path, time, audioPath);
} else { } else {
queuePhotoForLater(path, time, audioPath, latitude, longitude, altitude); queuePhotoForLater(path, time, audioPath, latitude, longitude, altitude);
} }
currentAudioPath = null;
} }
private void uploadNewPhoto(String path, long time, String audioPath, private void uploadNewPhoto(String path, long time, String audioPath) {
double latitude, double longitude, double altitude) {
executor.execute(() -> { executor.execute(() -> {
List<ImageEntity> history = db2.imageDao().getAll(); List<ImageEntity> history = db2.imageDao().getAll();
if (history != null && !history.isEmpty()) { if (history != null && !history.isEmpty()) {
@ -396,7 +393,6 @@ dataManager=SharedDataManager.getInstance();
db2.imageDao().deleteAll(); db2.imageDao().deleteAll();
String partname = getPartName(blade); String partname = getPartName(blade);
if (partid == null) partid = partname; if (partid == null) partid = partname;
uploadPhoto(path, time, lastKnownLocation, user, uploadPhoto(path, time, lastKnownLocation, user,
@ -408,20 +404,16 @@ dataManager=SharedDataManager.getInstance();
double latitude, double longitude, double altitude) { double latitude, double longitude, double altitude) {
executor.execute(() -> { executor.execute(() -> {
String partname = getPartName(blade); String partname = getPartName(blade);
if (partid == null) partid = partname; if (partid == null) partid = partname;
db2.imageDao().insert(new ImageEntity(path, time, latitude, longitude, altitude, db2.imageDao().insert(new ImageEntity(path, time, latitude, longitude, altitude,
user, audioPath, projectId, unit, blade, false, unitName, user, audioPath, projectId, unit, blade, false, unitName,
Temperator, Humidity, Weather, ChooseImageSource,partid)); Temperator, Humidity, Weather, ChooseImageSource,partid));
}); });
} }
private void uploadPhoto(String filePath, long time, Location location, String user, private void uploadPhoto(String filePath, long time, Location location, String user,
String audioPath, String project, String unit, int blade, String audioPath, String project, String unit, int blade,
String partid, String imageSource, String unitName) { String partId, String imageSource, String unitName) {
synchronized (uploadLock) { synchronized (uploadLock) {
if (isUploading) { if (isUploading) {
queuePhotoForLater(filePath, time, audioPath, queuePhotoForLater(filePath, time, audioPath,
@ -430,16 +422,12 @@ dataManager=SharedDataManager.getInstance();
location != null ? location.getAltitude() : 0); location != null ? location.getAltitude() : 0);
return; return;
} }
} }
executor.execute(() -> { executor.execute(() -> {
try { try {
File imageFile = new File(filePath); File imageFile = new File(filePath);
if (!imageFile.exists()) { if (!imageFile.exists()) {
if (callback != null) {
callback.onUploadFailure(filePath, "File does not exist");
}
return; return;
} }
@ -447,63 +435,81 @@ dataManager=SharedDataManager.getInstance();
double longitude = location != null ? location.getLongitude() : 0; double longitude = location != null ? location.getLongitude() : 0;
double altitude = location != null ? location.getAltitude() : 0; double altitude = location != null ? location.getAltitude() : 0;
MultipartBody.Builder builder = new MultipartBody.Builder() // 构建请求URL
.setType(MultipartBody.FORM) HttpUrl.Builder urlBuilder = HttpUrl.parse("http://pms.dtyx.net:9158/image/" + imageSource + "/upload/" + partId)
.addFormDataPart("image", imageFile.getName(), .newBuilder()
RequestBody.create(imageFile, MediaType.parse("image/*"))) .addQueryParameter("collectorId",UserId)
.addFormDataPart("time", String.valueOf(time)) .addQueryParameter("collectorName", user)
.addFormDataPart("latitude", String.valueOf(latitude)) .addQueryParameter("humidness", String.valueOf(Humidity))
.addFormDataPart("longitude", String.valueOf(longitude)) .addQueryParameter("shootingDistance", String.valueOf(0)) // 根据需要设置实际值
.addFormDataPart("altitude", String.valueOf(altitude)) .addQueryParameter("temperatureMax", String.valueOf(Temperator))
.addFormDataPart("uploadUser", user) .addQueryParameter("temperatureMin", String.valueOf(Temperator))
.addFormDataPart("projectId", project) .addQueryParameter("weather", Weather)
.addFormDataPart("turbineId", unit) .addQueryParameter("windLevel", String.valueOf(0)); // 根据需要设置实际值
.addFormDataPart("partId", partid)
.addFormDataPart("imageSource", imageSource); // 创建请求体
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("file", imageFile.getName(),
RequestBody.create(imageFile, MediaType.parse("image/*")))
.build();
RequestBody requestBody = builder.build();
Request request = new Request.Builder() Request request = new Request.Builder()
.url("http://pms.dtyx.net:9158/common/upload-image/file") .url(urlBuilder.build())
.post(requestBody) .post(requestBody)
.addHeader("Authorization", token) .addHeader("Authorization", token)
.addHeader("Content-Type", "application/x-www-form-urlencoded")
.build(); .build();
try (Response response = httpClient.newCall(request).execute()) { try (Response response = httpClient.newCall(request).execute()) {
if (response.isSuccessful()) { if (response.isSuccessful()) {
// 解析响应数据
String responseData = response.body().string();
JSONObject jsonResponse = new JSONObject(responseData);
JSONObject data = jsonResponse.optJSONObject("data");
System.out.println(responseData);
String imageId = data != null ? data.optString("imageId") : "";
dataManager.setImageId(imageId);
dataManager.setOthermsg("partid:"+partid+"\n"+"imageid:"+imageId+"\n"+"response:"+responseData);
db.imageDao().insert(new ImageEntity(filePath, time, latitude, longitude, altitude, db.imageDao().insert(new ImageEntity(filePath, time, latitude, longitude, altitude,
user, audioPath, project, unit, blade, true, unitName, user, audioPath, project, unit, blade, true, unitName,
Temperator, Humidity, Weather, ChooseImageSource,partid)); Temperator, Humidity, Weather, ChooseImageSource, partId));
if (callback != null) { totalUploadedCount++;
successCount++; updateNotification(imageId);
Log.d("上传成功:","已经上传成功"+successCount+"张图片"); Intent intent = new Intent("RESPONSE_ACTION");
BackgroundToast.show(this,"已经上传成功"+successCount+"张图片"); intent.putExtra("response", response.toString());
sendBroadcast(intent);
long currentTime = System.currentTimeMillis();
if (currentTime - lastSuccessToastTime > TOAST_THROTTLE_INTERVAL) {
BackgroundToast.show(this, "图片上传成功,已上传" + totalUploadedCount + "");
lastSuccessToastTime = currentTime;
} }
} else { } else {
db2.imageDao().insert(new ImageEntity(filePath, time, latitude, longitude, altitude, db2.imageDao().insert(new ImageEntity(filePath, time, latitude, longitude, altitude,
user, audioPath, project, unit, blade, false, unitName, user, audioPath, project, unit, blade, false, unitName,
Temperator, Humidity, Weather, ChooseImageSource,partid)); Temperator, Humidity, Weather, ChooseImageSource, partId));
dataManager.setImageId("-1");
if (callback != null) {
failureCount++;
BackgroundToast.show(this,"上传失败"+response.code()+response.message());
}
} }
} }
} catch (IOException e) { } catch (Exception e) {
db2.imageDao().insert(new ImageEntity(filePath, time, 0, 0, 0, db2.imageDao().insert(new ImageEntity(filePath, time, 0, 0, 0,
user, audioPath, project, unit, blade, false, unitName, user, audioPath, project, unit, blade, false, unitName,
Temperator, Humidity, Weather, ChooseImageSource,partid)); Temperator, Humidity, Weather, ChooseImageSource, partId));
dataManager.setImageId("-1");
if (callback != null) {
BackgroundToast.show(this,"io错误"+e.getMessage());
}
} finally {
} }
}); });
} }
private void updateNotification(String msg) {
String content = "已成功上传 " + totalUploadedCount + " 张照片"+msg;
Notification notification = buildNotification("照片上传服务运行中", content);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (manager != null) {
manager.notify(NOTIFICATION_ID, notification);
}
}
private boolean isNetworkAvailable() { private boolean isNetworkAvailable() {
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
if (cm == null) return false; if (cm == null) return false;
@ -515,46 +521,44 @@ dataManager=SharedDataManager.getInstance();
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)); capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET));
} }
private void createNotificationChannel() { private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel( NotificationChannel channel = new NotificationChannel(
CHANNEL_ID, CHANNEL_ID,
"照片上传服务", "照片上传服务",
NotificationManager.IMPORTANCE_HIGH // 使用高优先级确保通知显示 NotificationManager.IMPORTANCE_HIGH
); );
channel.setDescription("显示照片上传状态和进度"); channel.setDescription("显示照片上传状态和进度");
NotificationManager manager = getSystemService(NotificationManager.class); NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(channel); manager.createNotificationChannel(channel);
} }
} }
private Notification buildNotification(String title, String content) { private Notification buildNotification(String title, String content) {
return new NotificationCompat.Builder(this, CHANNEL_ID) return new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle(title) .setContentTitle(title)
.setContentText(content) .setContentText(content)
.setSmallIcon(R.drawable.ic_upload) // 使用上传图标 .setSmallIcon(R.drawable.ic_upload)
.setPriority(NotificationCompat.PRIORITY_HIGH) .setPriority(NotificationCompat.PRIORITY_HIGH)
.setOngoing(true) // 设置为持续通知 .setOngoing(true)
.setOnlyAlertOnce(true) // 更新时不重复提醒 .setOnlyAlertOnce(true)
.addAction(createStopAction()) .addAction(createStopAction())
.build(); .build();
} }
private NotificationCompat.Action createStopAction() { private NotificationCompat.Action createStopAction() {
Intent stopIntent = new Intent(this, NotificationReceiver.class); Intent stopIntent = new Intent(this, NotificationReceiver.class);
stopIntent.setAction("ACTION_STOP_SERVICE"); stopIntent.setAction("ACTION_STOP_SERVICE");
// 修改这一行添加 FLAG_IMMUTABLE FLAG_MUTABLE
PendingIntent stopPendingIntent = PendingIntent.getBroadcast( PendingIntent stopPendingIntent = PendingIntent.getBroadcast(
this, this,
0, 0,
stopIntent, stopIntent,
PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT); // 添加 FLAG_IMMUTABLE PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
return new NotificationCompat.Action( return new NotificationCompat.Action(
R.drawable.ic_stop, "停止", stopPendingIntent); R.drawable.ic_stop, "停止", stopPendingIntent);
} }
private long getLastPhotoId() { private long getLastPhotoId() {
long id = -1; long id = -1;
Cursor cursor = getContentResolver().query( Cursor cursor = getContentResolver().query(
@ -566,10 +570,9 @@ dataManager=SharedDataManager.getInstance();
); );
if (cursor != null && cursor.moveToFirst()) { if (cursor != null && cursor.moveToFirst()) {
id = cursor.getLong(0); // MAX(_ID) 的结果在索引 0 id = cursor.getLong(0);
cursor.close(); cursor.close();
} }
return id; return id;
} }
} }

View File

@ -7,6 +7,7 @@ import android.app.Service;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo; import android.content.pm.ServiceInfo;
import android.location.Location;
import android.media.MediaRecorder; import android.media.MediaRecorder;
import android.os.Build; import android.os.Build;
import android.os.Handler; import android.os.Handler;
@ -59,7 +60,7 @@ public class RecordingService extends Service implements SharedDataManager.DataC
private AppDatabase db; private AppDatabase db;
private AppDatabase db2; private AppDatabase db2;
private final ExecutorService executor = Executors.newFixedThreadPool(4); private final ExecutorService executor = Executors.newFixedThreadPool(4);
private String currentImagePath="-1"; private String ImageId="-1";
private String currentToken="-1"; private String currentToken="-1";
private SharedDataManager dataManager; private SharedDataManager dataManager;
@ -110,16 +111,17 @@ public class RecordingService extends Service implements SharedDataManager.DataC
dataManager=SharedDataManager.getInstance(); dataManager=SharedDataManager.getInstance();
dataManager.addListener(this); dataManager.addListener(this);
currentImagePath = dataManager.getImagePath();
currentToken = dataManager.getToken(); currentToken = dataManager.getToken();
ImageId=dataManager.getImageId();
// 在onCreate()中改为使用成员变量观察 // 在onCreate()中改为使用成员变量观察
} }
@Override @Override
public void onImagePathChanged(String newPath) { public void onImageIdChanged(String newId) {
currentImagePath = newPath; ImageId=newId;
Log.d("Service", "ImagePath updated: " + newPath);
} }
@Override @Override
@ -177,6 +179,16 @@ public class RecordingService extends Service implements SharedDataManager.DataC
public void onUploadingStatusChanged(boolean isUploading) { public void onUploadingStatusChanged(boolean isUploading) {
}
@Override
public void onLocationChanged(Location newLocation) {
}
@Override
public void onOtherMsgChanged(String msg) {
} }
@ -192,9 +204,10 @@ public class RecordingService extends Service implements SharedDataManager.DataC
} }
return START_REDELIVER_INTENT; return START_REDELIVER_INTENT;
} }
private void startRecording() { private void startRecording() {
try { try {
dataManager.setIsRecording(true);
// 1. 设置录音文件路径 // 1. 设置录音文件路径
currentAudioPath = getExternalCacheDir().getAbsolutePath() currentAudioPath = getExternalCacheDir().getAbsolutePath()
+ "/" + System.currentTimeMillis() + ".3gp"; + "/" + System.currentTimeMillis() + ".3gp";
@ -283,13 +296,14 @@ public class RecordingService extends Service implements SharedDataManager.DataC
if (response.isSuccessful()) { if (response.isSuccessful()) {
// 上传成功 // 上传成功
db.AudioDao().delete(new AudioEntity(audioPath, imageId, currentTime)); executor.execute(()->{ db.AudioDao().deleteByPath(audioPath);
db2.AudioDao().insert(new AudioEntity(audioPath, imageId, currentTime));
db2.AudioDao().insert(new AudioEntity(audioPath, imageId, currentTime,true));});
BackgroundToast.show(this, "录音上传成功: " + imageId); BackgroundToast.show(this, "录音上传成功: " + imageId);
stopSelf(); stopSelf();
} else { } else {
// 上传失败HTTP 错误 // 上传失败HTTP 错误
db.AudioDao().insert(new AudioEntity(audioPath, imageId, currentTime)); executor.execute(()->{ db.AudioDao().insert(new AudioEntity(audioPath, imageId, currentTime,false));});
BackgroundToast.show(this, BackgroundToast.show(this,
"录音上传失败: " + response.code() + " " + response.message()); "录音上传失败: " + response.code() + " " + response.message());
stopSelf(); stopSelf();
@ -298,7 +312,10 @@ public class RecordingService extends Service implements SharedDataManager.DataC
// 网络异常 // 网络异常
String currentTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()) String currentTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
.format(new Date()); .format(new Date());
db.AudioDao().insert(new AudioEntity(audioPath, imageId, currentTime));
executor.execute(() -> {
db.AudioDao().insert(new AudioEntity(currentAudioPath, ImageId, currentToken, false));
});
BackgroundToast.show(this, "录音上传失败: " + e.getMessage()); BackgroundToast.show(this, "录音上传失败: " + e.getMessage());
Log.e("录音上传失败:",e.toString()); Log.e("录音上传失败:",e.toString());
stopSelf(); stopSelf();
@ -314,18 +331,23 @@ public class RecordingService extends Service implements SharedDataManager.DataC
mediaRecorder.release(); mediaRecorder.release();
mediaRecorder = null; mediaRecorder = null;
} }
dataManager.setIsRecording(false);
// 2. 停止计时器 // 2. 停止计时器
if (handler != null && updateTimerRunnable != null) { if (handler != null && updateTimerRunnable != null) {
handler.removeCallbacks(updateTimerRunnable); handler.removeCallbacks(updateTimerRunnable);
} }
// 3. 更新通知 // 3. 更新通知
updateNotification("录音已保存"); updateNotification("录音已保存");
// 4. 上传录音文件如果有需要 // 4. 上传录音文件如果有需要
if (currentAudioPath != null) { if (currentAudioPath != null && ImageId != "-1") {
uploadAudio(currentImagePath, currentAudioPath, currentToken); BackgroundToast.show(this,"开始上传录音了");
uploadAudio(ImageId, currentAudioPath, currentToken);
} else
{
BackgroundToast.show(this,"Imageid不存在上传录音失败");
executor.execute(() -> {
db.AudioDao().insert(new AudioEntity(currentAudioPath, ImageId, currentToken, false));
});
} }
// 5. 不立即停止服务等待上传完成 // 5. 不立即停止服务等待上传完成
@ -333,6 +355,7 @@ public class RecordingService extends Service implements SharedDataManager.DataC
} catch (Exception e) { } catch (Exception e) {
Toast.makeText(this, "停止录音失败: " + e.getMessage(), Toast.LENGTH_SHORT).show(); Toast.makeText(this, "停止录音失败: " + e.getMessage(), Toast.LENGTH_SHORT).show();
dataManager.setIsRecording(false);
stopSelf(); stopSelf();
} }
} }