diff --git a/app/src/main/java/com/example/kingway/ptt/AudioRecordManager.java b/app/src/main/java/com/example/kingway/ptt/AudioRecordManager.java index 577650a..10e3f2d 100644 --- a/app/src/main/java/com/example/kingway/ptt/AudioRecordManager.java +++ b/app/src/main/java/com/example/kingway/ptt/AudioRecordManager.java @@ -3,12 +3,10 @@ package com.example.kingway.ptt; import android.media.AudioFormat; import android.media.AudioRecord; import android.media.MediaRecorder; -import android.util.Log; +import timber.log.Timber; import com.stand.standapp.MyApplication; -import java.util.Arrays; - @SuppressWarnings("ResultOfMethodCallIgnored") public class AudioRecordManager { private final String TAG = "AudioRecordManager"; @@ -32,14 +30,17 @@ public class AudioRecordManager { AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize * 2); + Timber.tag(TAG).d("AudioRecord初始化: source=MIC, freq=%dHz, minBuf=%d", FREQUENCY, bufferSize * 2); } public void setRecording(){ + Timber.tag(TAG).d("setRecording -> startRecording()"); if (mRecorder == null) initAudio(); if(mRecorder.getRecordingState() != 3) mRecorder.startRecording(); } public void stopAudio(){ + Timber.tag(TAG).d("stopAudio -> stop()"); if (mRecorder != null){ mRecorder.stop(); } @@ -51,6 +52,7 @@ public class AudioRecordManager { } public void destroyAudio(){ + Timber.tag(TAG).d("destroyAudio -> 释放AudioRecord"); if (mRecorder != null){ mRecorder.stop(); mRecorder.release(); @@ -82,12 +84,13 @@ public class AudioRecordManager { try { recordThread.interrupt(); } catch (Exception e) { + Timber.tag(TAG).e(e, "录音线程interrupt失败"); recordThread = null; } } recordThread = null; } catch (Exception e) { - e.printStackTrace(); + Timber.tag(TAG).e(e, "destroyThread异常"); } finally { recordThread = null; } @@ -97,6 +100,7 @@ public class AudioRecordManager { * 启动录音线程 */ private void startThread() { + Timber.tag(TAG).d("启动录音线程"); destroyThread(); isStart = true; if (mRecorder == null) { @@ -119,10 +123,12 @@ public class AudioRecordManager { int bytesRecord; byte[] tempBuffer = new byte[bufferSize]; if (mRecorder.getState() != AudioRecord.STATE_INITIALIZED) { + Timber.tag(TAG).w("AudioRecord未初始化(state=%d),终止录音", mRecorder.getState()); stopRecord(); return; } mRecorder.startRecording(); + Timber.tag(TAG).d("录音线程: startRecording() 成功"); int count = 0; while (isStart) { if (null != mRecorder) { @@ -132,15 +138,16 @@ public class AudioRecordManager { continue; } if (bytesRecord != 0 && bytesRecord != -1) { - Log.i(TAG, "tempBuffer->" + Arrays.toString(tempBuffer)); + Timber.tag(TAG).v("录音帧: %d bytes", bytesRecord); MyApplication.getAppInstance().getpNative().pttNativeSendRecordCmd(tempBuffer); } else { + Timber.tag(TAG).w("录音循环退出: bytesRecord=%d", bytesRecord); break; } } } } catch (Exception e) { - e.printStackTrace(); + Timber.tag(TAG).e(e, "录音线程异常"); } } @@ -150,12 +157,13 @@ public class AudioRecordManager { * 启动录音 */ public void startRecord() { + Timber.tag(TAG).d("startRecord() 被调用"); try { stopRecord(); startThread(); } catch (Exception e) { - e.printStackTrace(); + Timber.tag(TAG).e(e, "startRecord异常"); } } @@ -163,6 +171,7 @@ public class AudioRecordManager { * 停止录音 */ public void stopRecord() { + Timber.tag(TAG).d("stopRecord() 被调用"); try { destroyThread(); if (mRecorder != null) { @@ -172,10 +181,10 @@ public class AudioRecordManager { } mRecorder.release(); mRecorder = null; - } catch (Exception e) { } + } catch (Exception e) { Timber.tag(TAG).e(e, "释放AudioRecord失败"); } } } catch (Exception e) { - e.printStackTrace(); + Timber.tag(TAG).e(e, "stopRecord异常"); } finally { } } diff --git a/app/src/main/java/com/example/kingway/ptt/CallBackResolution.java b/app/src/main/java/com/example/kingway/ptt/CallBackResolution.java index 7217f27..e6e010a 100644 --- a/app/src/main/java/com/example/kingway/ptt/CallBackResolution.java +++ b/app/src/main/java/com/example/kingway/ptt/CallBackResolution.java @@ -2,6 +2,8 @@ package com.example.kingway.ptt; import android.util.Log; +import timber.log.Timber; + import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executors; @@ -55,22 +57,23 @@ public class CallBackResolution { String ngx = "\\u"; try { - Log.i(TAG, "lisHex-->" + lisHex.toString()); + Timber.tag(TAG).i( "lisHex-->" + lisHex.toString()); String firstHex = lisHex.get(0); String errorNum = lisHex.get(1); - Log.d(TAG, "at_OEM_AT_cb firstHex: " + firstHex + ", errorNum: " + errorNum); + Timber.tag(TAG).d( "at_OEM_AT_cb firstHex: " + firstHex + ", errorNum: " + errorNum); switch (firstHex){ case "82"://登录状态通知指令 String loginId = lisHex.get(2) + "" + lisHex.get(3) + "" + lisHex.get(4) + "" + lisHex.get(5); pttLoginStatus = errorNum; pttLoginId = loginId; - Log.d(TAG,"PTT login status: "+pttLoginStatus+", id: "+pttLoginId); + Timber.tag(TAG).d("PTT login status: "+pttLoginStatus+", id: "+pttLoginId); // 实时推送状态到前端 com.stand.standapp.MainActivity.executeJs("updatePttLoginStatus('" + pttLoginStatus + "','" + pttLoginId + "')"); CallBackUtil.callBackLoinState(errorNum, loginId); loginState = isLoginConflict(errorNum); CallBackUtil.callBackLoginConflict(loginState); if (loginState) { + Timber.tag(TAG).w("Login conflict detected, showing conflict dialog"); com.stand.standapp.MainActivity.showPttConflictDialog(); } if ("02".equals(errorNum)) { @@ -94,17 +97,17 @@ public class CallBackResolution { break; case "0b"://发起讲话返回状态 - Log.d(TAG, "at_OEM_AT_cb ptt speak..."); + Timber.tag(TAG).d( "at_OEM_AT_cb ptt speak..."); CallBackUtil.callBackSpeakPlaySuccess(errorNum.equals("00")? true : false); break; case "0c"://结束讲话返回状态 - Log.d(TAG, "at_OEM_AT_cb speak end..."); + Timber.tag(TAG).d( "at_OEM_AT_cb speak end..."); CallBackUtil.callBackSpeakReleaseSuccess(errorNum.equals("00")? true : false); break; case "80"://返回群组信息 - Log.d(TAG, "at_OEM_AT_cb get group info: " + lisHex); + Timber.tag(TAG).d( "at_OEM_AT_cb get group info: " + lisHex); StringBuilder strGroup = new StringBuilder(); String groupId = lisHex.get(6) + "" + lisHex.get(7) + "" + lisHex.get(8) + "" + lisHex.get(9); int groupNo = Integer.valueOf((lisHex.get(4) + "" + lisHex.get(5)), 16); @@ -123,13 +126,13 @@ public class CallBackResolution { } } } catch (Exception e) { - e.printStackTrace(); + Timber.tag(TAG).e(e, "Decode hex failed"); } finally { String tempTxt = ""; tempTxt = unicodeToString(strGroup.toString()); - Log.i(TAG, " 组名称 " + tempTxt); + Timber.tag(TAG).i( " 组名称 " + tempTxt); CallBackUtil.callBackGroupInfo(groupId, tempTxt, groupNo, groupCount); - Log.d(TAG, "at_OEM_AT_cb group info groupId: " + groupId + ", groupNo: " + groupNo+", groupCount: " +groupCount); + Timber.tag(TAG).d( "at_OEM_AT_cb group info groupId: " + groupId + ", groupNo: " + groupNo+", groupCount: " +groupCount); if (1 == groupNo) groupInfos.clear(); GroupInfoDto groupInfo = new GroupInfoDto(groupId, tempTxt, groupNo, groupCount); groupInfos.add(groupInfo); @@ -156,7 +159,7 @@ public class CallBackResolution { } } } catch (Exception e) { - e.printStackTrace(); + Timber.tag(TAG).e(e, "Decode hex failed"); } finally { String tempTxt = unicodeToString(groupMemberName.toString()); GroupMemberInfoDto infoDto = new GroupMemberInfoDto(memberId, tempTxt, status, memberNo, haveVideo); @@ -192,7 +195,7 @@ public class CallBackResolution { } } catch (Exception e) { - e.printStackTrace(); + Timber.tag(TAG).e(e, "Decode hex failed"); } finally { String tempTxt = ""; for (int i = 0; i < stringsSpker.size(); i++) { @@ -232,7 +235,7 @@ public class CallBackResolution { } } catch (Exception e) { - e.printStackTrace(); + Timber.tag(TAG).e(e, "Decode hex failed"); } finally { String tempTxt = ""; for (int i = 0; i < stringsTalk.size(); i++) { @@ -251,7 +254,7 @@ public class CallBackResolution { code=-1; } - Log.i(TAG, " 临时讲话 信息通知的指令 " + tempTxt + " code=" + code); + Timber.tag(TAG).i( " 临时讲话 信息通知的指令 " + tempTxt + " code=" + code); CallBackUtil.callBackTempCallNotify(tempTxt); // 处理临时呼叫页面逻辑 @@ -274,7 +277,7 @@ public class CallBackResolution { ); com.stand.standapp.MyApplication.getAppInstance().startActivity(intent); } catch (Exception e) { - Log.e(TAG, "Failed to open TempCallActivity: " + e.getMessage()); + Timber.tag(TAG).e( "Failed to open TempCallActivity: " + e.getMessage()); } } else if (code == 0) { // 退出临时呼叫 → 关闭临时呼叫页面 @@ -318,13 +321,13 @@ public class CallBackResolution { } } catch (Exception e) { - e.printStackTrace(); + Timber.tag(TAG).e(e, "Decode hex failed"); } finally { String userGroupName = ""; for (int i = 0; i < stringsJumpGroup.size(); i++) { userGroupName += unicode(stringsJumpGroup.get(i)); } - Log.i(TAG,"进入群组 " + userGroupName); + Timber.tag(TAG).i("进入群组 " + userGroupName); indexGroupId = userGroupId; indexGroupName = userGroupName; CallBackUtil.callBackNotifyUpdateGroup(userGroupId, userGroupName); @@ -351,7 +354,7 @@ public class CallBackResolution { String time = strLis[2]; CallBackUtil.callBackNotifyLocationStatus(0, locationMemberId, latitude, longitude, time); } catch (Exception e) { - Log.e(TAG, "获取定位Exception-->" + e.getMessage()); + Timber.tag(TAG).e( "获取定位Exception-->" + e.getMessage()); } } else { CallBackUtil.callBackNotifyLocationStatus(1, "", 0.0, 0.0, ""); @@ -410,7 +413,7 @@ public class CallBackResolution { string += lisHex.get(i).toString(); } String address = hexString2String(string); - Log.i(TAG, "address-->" + address); + Timber.tag(TAG).i( "address-->" + address); String[] strLis = address.split(","); latitude = Double.parseDouble(strLis[0]); @@ -452,7 +455,7 @@ public class CallBackResolution { break; } }catch (Exception e){ - Log.e(TAG,"at_OEM_AT_cb Exception " + e.getMessage()); + Timber.tag(TAG).e("at_OEM_AT_cb Exception " + e.getMessage()); } } @@ -469,26 +472,30 @@ public class CallBackResolution { * tip:1min内会出现40次左右0-1切换 */ public static boolean isLoginConflict(String state) { - Log.d(TAG, " isLoginConflict state: " + state + ",oldLoginSate: " + oldLoginSate + ", logNum: " + logNum); + Timber.tag(TAG).d( " isLoginConflict state: " + state + ",oldLoginSate: " + oldLoginSate + ", logNum: " + logNum); if (oldLoginSate.equals("00") && state.equals("01")) { - Log.d(TAG, "isLoginConflict first login..."); + Timber.tag(TAG).d( "isLoginConflict first login..."); logNum++; oldLoginSate = state; } else if (oldLoginSate.equals("01") && state.equals("00")) { - Log.d(TAG, "isLoginConflict login state changed..."); + Timber.tag(TAG).d( "isLoginConflict login state changed..."); logNum++; oldLoginSate = state; } if (1 == logNum) { offlineTime = System.currentTimeMillis(); } - Log.d(TAG, "isLoginConflict logNum: " + logNum + ", offlineTime: " + offlineTime); - if (logNum > 4) { - Log.d(TAG, "isLoginConflict current time: " + System.currentTimeMillis() + ", diffTime: " + (System.currentTimeMillis() - offlineTime)); - if (System.currentTimeMillis() - offlineTime >= 60 * 1000) { - Log.d(TAG, "isLoginConflict login state changed: " + logNum + " in 1min"); + Timber.tag(TAG).d( "isLoginConflict logNum: " + logNum + ", offlineTime: " + offlineTime); + if (System.currentTimeMillis() - offlineTime <= 60 * 1000) { + if (logNum > 5) { + Timber.tag(TAG).d("isLoginConflict login state changed: " + logNum + " in 1min"); return true; } + } else { + Timber.tag(TAG).d("isLoginConflict maybe network change, reset..."); + logNum = 0; + offlineTime = System.currentTimeMillis(); + return false; } return false; } @@ -497,7 +504,7 @@ public class CallBackResolution { try { String[] txt = sData.split("\""); String data = txt[1]; - Log.d(TAG, "at_Play_TTS_cb sData: " + sData); + Timber.tag(TAG).d( "at_Play_TTS_cb sData: " + sData); String ngx = "\\u"; List strings = new ArrayList<>(); @@ -521,38 +528,37 @@ public class CallBackResolution { } } catch (Exception e) { - e.printStackTrace(); + Timber.tag(TAG).e(e, "Decode hex failed"); } finally { StringBuilder sb = new StringBuilder(); for (int k = 0; k < strings.size(); k++) { sb.append(unicode(strings.get(k))); } String tempTxt = sb.toString(); - Log.i(TAG,"at_Play_TTS_cb " + tempTxt); + Timber.tag(TAG).i("at_Play_TTS_cb " + tempTxt); if (tempTxt.contains("已登录")) { String showName = tempTxt.substring(3, tempTxt.length()); CallBackUtil.callBackLogin(true, showName); ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); Runnable task = () -> { - Log.d(TAG, "callBackLogin send tcp and udp"); + Timber.tag(TAG).d( "callBackLogin send tcp and udp"); SendAtUtil.sendUDP(); SendAtUtil.sendTCP(); }; executor.scheduleAtFixedRate(task, 0, 40, TimeUnit.SECONDS); } else if (tempTxt.contains("账号已更新")) { -// com.stand.standapp.MainActivity.showPttUpdateDialog("您的 PTT 账号信息已被更新,需要重新登录以应用更改。\n请点击确认重启应用。","账号更新"); - Log.d(TAG, "--------------------------1"); - Log.d(TAG, tempTxt); + Timber.tag(TAG).w("TTS reports account updated: '%s'", tempTxt); } else if (tempTxt.contains("账号或密码错误")) { CallBackUtil.callBackLogin(false, ""); + Timber.tag(TAG).e("Account/password error, showing dialog. TTS: '%s'", tempTxt); com.stand.standapp.MainActivity.showPttUpdateDialog("您的 PTT 账号信息账号或密码错误。\n请点击确认重启应用。","账号或密码错误"); }else if (tempTxt.contains("请配置账号")) { -// com.stand.standapp.MainActivity.showPttUpdateDialog("首次登录信息更新。\n请点击确认重启应用。","登录信息更新"); + Timber.tag(TAG).w("TTS reports no account configured: '%s'", tempTxt); } } } catch (Exception e) { - e.printStackTrace(); + Timber.tag(TAG).e(e, "Decode hex failed"); } } diff --git a/app/src/main/java/com/example/kingway/ptt/CallBackUtil.java b/app/src/main/java/com/example/kingway/ptt/CallBackUtil.java index 73433a2..e7b5a4a 100644 --- a/app/src/main/java/com/example/kingway/ptt/CallBackUtil.java +++ b/app/src/main/java/com/example/kingway/ptt/CallBackUtil.java @@ -1,6 +1,6 @@ package com.example.kingway.ptt; -import android.util.Log; +import timber.log.Timber; import java.util.ArrayList; import java.util.List; @@ -18,7 +18,7 @@ public class CallBackUtil { * name 用户名 */ public static void callBackLogin(boolean loginState, String name) { - Log.i(TAG, "callBackLogin loginState " + loginState + " name " + name); + Timber.tag(TAG).d("callBackLogin loginState=%s name=%s", loginState, name); } /** @@ -34,7 +34,7 @@ public class CallBackUtil { * loginId 用户ID,登录成功id有效 */ public static void callBackLoinState(String state, String loginId) { - Log.d(TAG, "callBackLoinState state: " + state + ", loginId: " + loginId); + Timber.tag(TAG).d("callBackLoinState state=%s loginId=%s", state, loginId); } /** @@ -43,13 +43,14 @@ public class CallBackUtil { * false:登录不冲突 * */ public static void callBackLoginConflict(boolean loginConflict) { - Log.d(TAG, "callBackLoginConflict: " + loginConflict); + Timber.tag(TAG).d("callBackLoginConflict: %s", loginConflict); } /** * 登录账号有视频功能通知 */ public static boolean callBackHaveVideo() { + Timber.tag(TAG).d("callBackHaveVideo invoked"); return true; } @@ -60,7 +61,7 @@ public class CallBackUtil { * state true-成功, false-失败 */ public static void callBackOnGroupSuccess(boolean state) { - + Timber.tag(TAG).d("callBackOnGroupSuccess state=%s", state); } /** @@ -80,7 +81,7 @@ public class CallBackUtil { } } com.stand.standapp.MainActivity.executeJs("if(window.onPttEvent){window.onPttEvent('MemberList', " + arr.toString() + ");}"); - } catch (Exception e) {} + } catch (Exception e) { Timber.tag(TAG).e(e, "Failed to push PTT event to JS"); } } /** @@ -88,13 +89,16 @@ public class CallBackUtil { * state true-成功, false-失败 */ public static void callBackSpeakPlaySuccess(boolean state) { - Log.d(TAG, "callBackSpeakPlaySuccess state: " + state); - if (state) AudioRecordManager.getInstance().startRecord(); + Timber.tag(TAG).d("callBackSpeakPlaySuccess state=%s", state); + if (state) { + AudioRecordManager.getInstance().startRecord(); + Timber.tag(TAG).d("AudioRecord started"); + } try { org.json.JSONObject obj = new org.json.JSONObject(); obj.put("success", state); com.stand.standapp.MainActivity.executeJs("if(window.onPttEvent){window.onPttEvent('SpeakResult', " + obj.toString() + ");}"); - } catch (Exception e) {} + } catch (Exception e) { Timber.tag(TAG).e(e, "Failed to push PTT event to JS"); } } /** @@ -106,7 +110,7 @@ public class CallBackUtil { org.json.JSONObject obj = new org.json.JSONObject(); obj.put("success", state); com.stand.standapp.MainActivity.executeJs("if(window.onPttEvent){window.onPttEvent('SpeakEnd', " + obj.toString() + ");}"); - } catch (Exception e) {} + } catch (Exception e) { Timber.tag(TAG).e(e, "Failed to push PTT event to JS"); } } /** @@ -116,7 +120,9 @@ public class CallBackUtil { * groupNo 表示此组为第几个组 * groupCount 表示此组用户成员数 */ - public static void callBackGroupInfo(String groupId, String groupName, int groupNo, int groupCount) {} + public static void callBackGroupInfo(String groupId, String groupName, int groupNo, int groupCount) { + Timber.tag(TAG).d("callBackGroupInfo groupId=%s name=%s no=%d count=%d", groupId, groupName, groupNo, groupCount); + } /** * 返回群组集合信息 @@ -133,7 +139,7 @@ public class CallBackUtil { arr.put(obj); } com.stand.standapp.MainActivity.executeJs("if(window.onPttEvent){window.onPttEvent('GroupList', " + arr.toString() + ");}"); - } catch (Exception e) {} + } catch (Exception e) { Timber.tag(TAG).e(e, "Failed to push PTT event to JS"); } } /** @@ -143,6 +149,7 @@ public class CallBackUtil { * talkName 讲话用户名字 * */ public static void callBackNotifySpker ( int speckType, String groupId, String groupName, String talkId, String talkName){ + Timber.tag(TAG).d("callBackNotifySpker speckType=%d groupId=%s talkId=%s talkName=%s", speckType, groupId, talkId, talkName); try { org.json.JSONObject obj = new org.json.JSONObject(); obj.put("speckType", speckType); @@ -151,10 +158,11 @@ public class CallBackUtil { obj.put("talkId", talkId); obj.put("talkName", talkName); com.stand.standapp.MainActivity.executeJs("if(window.onPttEvent){window.onPttEvent('SpeakerUpdate', " + obj.toString() + ");}"); - } catch (Exception e) {} + } catch (Exception e) { Timber.tag(TAG).e(e, "Failed to push PTT event to JS"); } } public static void callBackNotifyPlayStatus ( int playStatus, int speckType, String groupId, String groupName, String talkId, String talkName){ + Timber.tag(TAG).d("callBackNotifyPlayStatus playStatus=%d talkId=%s", playStatus, talkId); try { org.json.JSONObject obj = new org.json.JSONObject(); obj.put("playStatus", playStatus); @@ -164,24 +172,26 @@ public class CallBackUtil { obj.put("talkId", talkId); obj.put("talkName", talkName); com.stand.standapp.MainActivity.executeJs("if(window.onPttEvent){window.onPttEvent('PlayStatus', " + obj.toString() + ");}"); - } catch (Exception e) {} + } catch (Exception e) { Timber.tag(TAG).e(e, "Failed to push PTT event to JS"); } } public static void callBackTempCallNotify (String tempCallNotify){ + Timber.tag(TAG).d("callBackTempCallNotify msg=%s", tempCallNotify); try { org.json.JSONObject obj = new org.json.JSONObject(); obj.put("msg", tempCallNotify); com.stand.standapp.MainActivity.executeJs("if(window.onPttEvent){window.onPttEvent('TempCall', " + obj.toString() + ");}"); - } catch (Exception e) {} + } catch (Exception e) { Timber.tag(TAG).e(e, "Failed to push PTT event to JS"); } } public static void callBackNotifyUpdateGroup (String userGroupId, String userGroupName){ + Timber.tag(TAG).d("callBackNotifyUpdateGroup groupId=%s groupName=%s", userGroupId, userGroupName); try { org.json.JSONObject obj = new org.json.JSONObject(); obj.put("groupId", userGroupId); obj.put("groupName", userGroupName); com.stand.standapp.MainActivity.executeJs("if(window.onPttEvent){window.onPttEvent('UpdateGroup', " + obj.toString() + ");}"); - } catch (Exception e) {} + } catch (Exception e) { Timber.tag(TAG).e(e, "Failed to push PTT event to JS"); } } /** @@ -193,6 +203,7 @@ public class CallBackUtil { * time 时间 */ public static void callBackNotifyLocationStatus ( int status, String userId,double latitude, double longitude, String time){ + Timber.tag(TAG).d("callBackNotifyLocationStatus status=%d userId=%s lat=%f lng=%f", status, userId, latitude, longitude); try { org.json.JSONObject obj = new org.json.JSONObject(); obj.put("status", status); @@ -201,7 +212,7 @@ public class CallBackUtil { obj.put("longitude", longitude); obj.put("time", time); com.stand.standapp.MainActivity.executeJs("if(window.onPttEvent){window.onPttEvent('LocationStatus', " + obj.toString() + ");}"); - } catch (Exception e) {} + } catch (Exception e) { Timber.tag(TAG).e(e, "Failed to push PTT event to JS"); } } /** @@ -209,7 +220,7 @@ public class CallBackUtil { * status true:成功, false:失败 * */ public static void callBackNotifyUploadLocation ( boolean status){ - + Timber.tag(TAG).d("callBackNotifyUploadLocation status=%s", status); } /** @@ -221,7 +232,7 @@ public class CallBackUtil { * inv=1:1勾选单呼,0不勾选单呼 * */ public static void callBackNotifyCodeInfo (String codeInfo){ - + Timber.tag(TAG).d("callBackNotifyCodeInfo: %s", codeInfo); } /** @@ -231,7 +242,7 @@ public class CallBackUtil { * pwd=111111 账号密码:111111 * */ public static void callBackNotifyPwdInfo (String pwdInfo){ - + Timber.tag(TAG).d("callBackNotifyPwdInfo: %s", pwdInfo); } /** @@ -239,7 +250,7 @@ public class CallBackUtil { * status true:成功,false:失败 * */ public static void callBackNotifyCodeOpenStatus ( boolean status){ - + Timber.tag(TAG).d("callBackNotifyCodeOpenStatus status=%s", status); } /** @@ -247,7 +258,7 @@ public class CallBackUtil { * status true:成功,false:失败 * */ public static void callBackNotifyCodeExiteStatus ( boolean status){ - + Timber.tag(TAG).d("callBackNotifyCodeExiteStatus status=%s", status); } /** @@ -255,7 +266,7 @@ public class CallBackUtil { * status true:成功,false:失败 * */ public static void callBackNotifyUploadAgentPwd ( boolean status){ - + Timber.tag(TAG).d("callBackNotifyUploadAgentPwd status=%s", status); } /** @@ -263,7 +274,7 @@ public class CallBackUtil { * status true:成功,false:失败 * */ public static void callBackRequestReportAlarm ( boolean status){ - + Timber.tag(TAG).d("callBackRequestReportAlarm status=%s", status); } /** @@ -271,7 +282,7 @@ public class CallBackUtil { * status true:成功,false:失败 * */ public static void callBackRequestStopAlarm ( boolean status){ - + Timber.tag(TAG).d("callBackRequestStopAlarm status=%s", status); } /** @@ -281,19 +292,21 @@ public class CallBackUtil { * longitude 经度 * */ public static void callBackEnotifyAlarm (String memberName,double latitude, double longitude){ + Timber.tag(TAG).w("callBackEnotifyAlarm memberName=%s lat=%f lng=%f", memberName, latitude, longitude); try { org.json.JSONObject obj = new org.json.JSONObject(); obj.put("memberName", memberName); obj.put("latitude", latitude); obj.put("longitude", longitude); com.stand.standapp.MainActivity.executeJs("if(window.onPttEvent){window.onPttEvent('Alarm', " + obj.toString() + ");}"); - } catch (Exception e) {} + } catch (Exception e) { Timber.tag(TAG).e(e, "Failed to push PTT event to JS"); } } /** * 收到群成员停止警告通知 * */ public static void callBackEnotifyStopAlarm () { + Timber.tag(TAG).d("callBackEnotifyStopAlarm invoked"); com.stand.standapp.MainActivity.executeJs("if(window.onPttEvent){window.onPttEvent('StopAlarm', {});}"); } @@ -302,7 +315,7 @@ public class CallBackUtil { * status true:成功,false:失败 * */ public static void callBackRequestNfc ( boolean status){ - + Timber.tag(TAG).d("callBackRequestNfc status=%s", status); } } diff --git a/app/src/main/java/com/example/kingway/ptt/SendAtUtil.java b/app/src/main/java/com/example/kingway/ptt/SendAtUtil.java index 6b45ebd..3df81fc 100644 --- a/app/src/main/java/com/example/kingway/ptt/SendAtUtil.java +++ b/app/src/main/java/com/example/kingway/ptt/SendAtUtil.java @@ -48,6 +48,7 @@ public class SendAtUtil { * tempCall 是否开启单呼 1开启单呼,0关闭单呼 * */ public static void toLogin(String account, String pwd, String ip, int location, int tempCall){ + Timber.tag("PTT").i("Login: account=%s, ip=%s, gps=%d, tempCall=%d", account, ip, location, tempCall); String ipHex = str2HexStr("ip=" + ip + ";"); String accountHex = str2HexStr("id=" + account + ";"); String pwdHex = str2HexStr("pwd=" + pwd + ";"); @@ -62,22 +63,26 @@ public class SendAtUtil { * 按下PTT开始呼叫 * */ public static void speakPlay(){ + Timber.tag("PTT").i("PTT speak START (press)"); send("0B0000"); } /** 松开PTT结束呼叫*/ public static void speakRelease(){ + Timber.tag("PTT").i("PTT speak STOP (release)"); AudioRecordManager.getInstance().stopRecord(); send("0C0000"); } /** 发送TCP包 登录成功后需要定时发送TCP包*/ public static void sendTCP(){ + Timber.tag("PTT").v("TCP keepalive sent"); send("570000\r\n"); } /** 发送UDP包 登录后需要定时发送UDP包*/ public static void sendUDP(){ + Timber.tag("PTT").v("UDP keepalive sent"); send("580000\r\n"); } @@ -97,6 +102,7 @@ public class SendAtUtil { * groupId 十六进制群组Id * */ public static void jumpGroup(String groupId){ + Timber.tag("PTT").i("Jump to group: %s", groupId); send("090000" + groupId); } diff --git a/app/src/main/java/com/example/kingway/ptt/pttNative.java b/app/src/main/java/com/example/kingway/ptt/pttNative.java index 9b8428b..498ccc2 100644 --- a/app/src/main/java/com/example/kingway/ptt/pttNative.java +++ b/app/src/main/java/com/example/kingway/ptt/pttNative.java @@ -5,7 +5,7 @@ import android.media.AudioFormat; import android.media.AudioManager; import android.media.AudioRecord; import android.media.AudioTrack; -import android.util.Log; +import timber.log.Timber; import java.util.ArrayList; import java.util.List; @@ -15,8 +15,9 @@ public class pttNative { static { try { System.loadLibrary("ptt"); + Timber.tag(TAG).d("Native library 'ptt' loaded successfully"); } catch (Throwable e) { - Log.e(TAG, "Failed to load ptt library: " + e.getMessage()); + Timber.tag(TAG).e(e, "Failed to load ptt library"); } } @@ -36,7 +37,7 @@ public class pttNative { //Callback Function for Recv the message from POC Lib public void OEM_AT_cb(String sData) { - Log.e(TAG,"Poc2 AT Callback: " + sData); + Timber.tag(TAG).d("Poc2 AT Callback: %s", sData); int len, i, j=0; char[] bytes = sData.toCharArray(); @@ -50,12 +51,15 @@ public class pttNative { lisHex.add(temp.length() == 1 ? "0" + temp : temp); } } + } else { + Timber.tag(TAG).w("OEM_AT_cb: unexpected format, len=%d, data=%s", bytes.length, sData); } CallBackResolution.at_OEM_AT_cb(lisHex); } public void OEM_Play_cb(byte[] bytes){ + Timber.tag(TAG).d("OEM_Play_cb: %d bytes", bytes.length); if (mAudioTrack == null) { initAudioTrack(); } @@ -68,27 +72,27 @@ public class pttNative { public void OEM_Play_Start_cb() { - Log.e("Play Start!!!!\r\n",""); + Timber.tag(TAG).e("Play Start!!!!"); } public void OEM_Play_Stop_cb() { - Log.e("Play Stop!!!!\r\n",""); + Timber.tag(TAG).e("Play Stop!!!!"); } public void OEM_Record_Start_cb() { - Log.e("Record Start!!!!\r\n",""); + Timber.tag(TAG).e("Record Start!!!!"); } public void OEM_Record_Stop_cb() { - Log.e("Record Stop!!!!\r\n",""); + Timber.tag(TAG).e("Record Stop!!!!"); } public void OEM_Play_TTS_cb(String sData) { - Log.e(TAG , "Play TTS " + sData); + Timber.tag(TAG).e("Play TTS " + sData); CallBackResolution.at_Play_TTS_cb(sData); } @@ -112,16 +116,17 @@ public class pttNative { private native int OEM_Set_Package_Name(String name); public void pttNativeSendRecordCmd(byte[] data) { + Timber.tag(TAG).d("pttNativeSendRecordCmd: %d bytes", data.length); OEM_Push_Record_Data(data); } public void pttNativeSendAtCmd(String strAtCmd) { try { - Log.i(TAG,"strAtCmd " + strAtCmd); + Timber.tag(TAG).i("AT Send: %s", strAtCmd); OEM_AT_Send(strAtCmd); } catch (Throwable e) { - Log.e(TAG, "Native AT Send failed: " + e.getMessage()); + Timber.tag(TAG).e( "Native AT Send failed: " + e.getMessage()); } } @@ -130,7 +135,7 @@ public class pttNative { try { OEM_Poc_Task_Start(); } catch (Throwable e) { - Log.e(TAG, "Native PocTaskStart failed"); + Timber.tag(TAG).e(e, "Native PocTaskStart failed"); } } @@ -139,6 +144,7 @@ public class pttNative { try { return OEM_Set_AT_CallBack("OEM_AT_cb"); } catch (Throwable e) { + Timber.tag(TAG).e(e, "Failed to set AT callback"); return -1; } } @@ -148,6 +154,7 @@ public class pttNative { try { return OEM_Set_Play_CallBack("OEM_Play_cb"); } catch (Throwable e) { + Timber.tag(TAG).e(e, "Failed to set Play callback"); return -1; } } @@ -157,6 +164,7 @@ public class pttNative { try { return OEM_Set_Play_Start_Callback("OEM_Play_Start_cb"); } catch (Throwable e) { + Timber.tag(TAG).e(e, "Failed to set PlayStart callback"); return -1; } } @@ -166,6 +174,7 @@ public class pttNative { try { return OEM_Set_Play_Stop_Callback("OEM_Play_Stop_cb"); } catch (Throwable e) { + Timber.tag(TAG).e(e, "Failed to set PlayStop callback"); return -1; } } @@ -175,6 +184,7 @@ public class pttNative { try { return OEM_Set_Record_Start_Callback("OEM_Record_Start_cb"); } catch (Throwable e) { + Timber.tag(TAG).e(e, "Failed to set RecordStart callback"); return -1; } } @@ -184,6 +194,7 @@ public class pttNative { try { return OEM_Set_Record_Stop_Callback("OEM_Record_Stop_cb"); } catch (Throwable e) { + Timber.tag(TAG).e(e, "Failed to set RecordStop callback"); return -1; } } @@ -193,6 +204,7 @@ public class pttNative { try { return OEM_Set_TTS_Callback("OEM_Play_TTS_cb"); } catch (Throwable e) { + Timber.tag(TAG).e(e, "Failed to set TTS callback"); return -1; } } @@ -202,17 +214,20 @@ public class pttNative { try { return OEM_Set_Package_Name(name); } catch (Throwable e) { + Timber.tag(TAG).e(e, "Failed to set package callback"); return -1; } } public pttNative() { + Timber.tag(TAG).d("pttNative instance created"); initAudioTrack(); } private AudioTrack mAudioTrack; public void initAudioTrack() { int mAudioMinBufSize = AudioTrack.getMinBufferSize(8000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT); + Timber.tag(TAG).d("AudioTrack init: minBufSize=%d", mAudioMinBufSize); AudioAttributes audioAttributes = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION) // 通信场景 @@ -245,7 +260,7 @@ public class pttNative { } mAudioTrack.release(); mAudioTrack = null; - } catch (Exception e) {} + } catch (Exception e) { Timber.tag(TAG).e(e, "AudioTrack destroy failed"); } } } diff --git a/app/src/main/java/com/stand/standapp/AndroidInterface.kt b/app/src/main/java/com/stand/standapp/AndroidInterface.kt index b6b2ce6..d87c7d5 100644 --- a/app/src/main/java/com/stand/standapp/AndroidInterface.kt +++ b/app/src/main/java/com/stand/standapp/AndroidInterface.kt @@ -107,6 +107,8 @@ class AndroidInterface(private val activity: MainActivity) { SendAtUtil.speakPlay() Timber.tag("PTT").d("Speak Play") MainActivity.executeJs("updatePttTalkStatus(true)") + } else { + Timber.tag("PTT").w("Speak Play ignored: already speaking") } } @@ -125,11 +127,13 @@ class AndroidInterface(private val activity: MainActivity) { json.put("groupName", com.example.kingway.ptt.CallBackResolution.getCurrentGroupName()) json.toString() } catch (e: Exception) { + Timber.tag("PTT").e(e, "pttGetCurrentGroup failed") "{\"groupId\":\"\",\"groupName\":\"\"}" } } fun pttSpeakRelease() { + Timber.tag("PTT").d("pttSpeakRelease called, isSpeaking=%s", isSpeaking) if (isSpeaking) { val now = System.currentTimeMillis() val duration = now - lastSpeakTime @@ -152,34 +156,42 @@ class AndroidInterface(private val activity: MainActivity) { SendAtUtil.speakRelease() Timber.tag("PTT").d("Real Speak Release") MainActivity.executeJs("updatePttTalkStatus(false)") + } else { + Timber.tag("PTT").w("realRelease skipped: already released") } } fun pttForceRelease() { + val wasSpeaking = isSpeaking isSpeaking = false SendAtUtil.speakRelease() - Timber.tag("PTT").d("Force Release") + Timber.tag("PTT").d("Force Release (wasSpeaking=%s)", wasSpeaking) } fun pttGetGroupInfo() { + Timber.tag("PTT").d("pttGetGroupInfo called") SendAtUtil.getGroupInfo() } fun pttGetGroupMemberInfo(gid: String) { + Timber.tag("PTT").d("pttGetGroupMemberInfo: gid=%s", gid) SendAtUtil.getGroupMemberInfo(gid) } fun simulatePttConflict() { + Timber.tag("PTT").w("simulatePttConflict: showing conflict dialog via JS bridge") Handler(Looper.getMainLooper()).post { MainActivity.showPttConflictDialog() } } fun pttSendAtCmd(cmd: String) { + Timber.tag("PTT").d("pttSendAtCmd: %s", cmd) SendAtUtil.sendRawCmd(cmd) } fun pttJumpGroup(gid: String) { + Timber.tag("PTT").d("pttJumpGroup: gid=%s", gid) SendAtUtil.jumpGroup(gid) } @@ -358,6 +370,7 @@ class AndroidInterface(private val activity: MainActivity) { val packageInfo = activity.packageManager.getPackageInfo(activity.packageName, 0) packageInfo.versionName ?: "1.0.0" } catch (e: Exception) { + Timber.tag("AndroidInterface").e(e, "getVersionName failed") "1.0.0" } } @@ -383,6 +396,7 @@ class AndroidInterface(private val activity: MainActivity) { json.toString() } catch (e: Exception) { + Timber.tag("AndroidInterface").e(e, "getAboutInfo failed") "{ \"appName\": \"消防值守台\", \"versionName\": \"1.0.0\" }" } } @@ -405,6 +419,7 @@ class AndroidInterface(private val activity: MainActivity) { val prefs = activity.getSharedPreferences("msg_records", Context.MODE_PRIVATE) prefs.getString("history", "") ?: "" } catch (e: Exception) { + Timber.tag("Storage").e(e, "getMessages failed") "" } } @@ -442,6 +457,7 @@ class AndroidInterface(private val activity: MainActivity) { } fun showRestartDialog(message: String, title: String) { + Timber.tag("AndroidInterface").w("showRestartDialog from JS: title=%s msg=%s", title, message) Handler(Looper.getMainLooper()).post { com.stand.standapp.MainActivity.showPttUpdateDialog(message, title) } diff --git a/app/src/main/java/com/stand/standapp/LoginActivity.kt b/app/src/main/java/com/stand/standapp/LoginActivity.kt index 70359b5..8c5d750 100644 --- a/app/src/main/java/com/stand/standapp/LoginActivity.kt +++ b/app/src/main/java/com/stand/standapp/LoginActivity.kt @@ -106,6 +106,7 @@ class LoginActivity : AppCompatActivity() { } private fun performLogin(username: String, password: String, remember: Boolean, officialMode: Boolean) { + Timber.tag("Login").d("开始登录: username=%s, server=%s", username, AppConfig.getServerUrl(this)) val serverUrl = AppConfig.getServerUrl(this) val loginUrl = "$serverUrl/api/auth/login" @@ -128,6 +129,7 @@ class LoginActivity : AppCompatActivity() { client.newCall(request).enqueue(object : Callback { override fun onFailure(call: Call, e: IOException) { + Timber.tag("Login").e(e, "登录网络请求失败") runOnUiThread { loadingDialog.dismiss() Toast.makeText(applicationContext, "网络异常: ${e.message}", Toast.LENGTH_SHORT).show() @@ -160,12 +162,14 @@ class LoginActivity : AppCompatActivity() { Toast.makeText(applicationContext, "登录成功", Toast.LENGTH_SHORT).show() // 获取独立的 PTT 账号并初始化 + Timber.tag("PTT").d("开始PTT初始化流程: username=%s, hasToken=%b", username, accessToken.isNotEmpty()) initPttWithAccount(username, accessToken) // 2. 启动硬件 GPIO 监听 try { com.stand.standapp.utils.GpioManager.init(this@LoginActivity) com.stand.standapp.utils.GpioManager.startListening() + Timber.tag("GPIO").d("GPIO初始化并启动监听成功") } catch (e: Exception) { Timber.tag("GPIO").e(e, "GPIO init error") } @@ -312,6 +316,7 @@ class LoginActivity : AppCompatActivity() { private fun initPttWithAccount(username: String, accessToken: String) { if (accessToken.isEmpty()) { + Timber.tag("PTT").w("accessToken为空,使用默认PTT密码: username=%s", username) doPttInit(username, "123456") return } @@ -339,8 +344,10 @@ class LoginActivity : AppCompatActivity() { val data = json.optJSONObject("data") val pttUsername = data?.optString("cardNumber", username) ?: username val pttPassword = data?.optString("pocPassword", "123456") ?: "123456" + Timber.tag("PTT").d("获取到服务器PTT账号: cardNumber=%s", pttUsername) doPttInit(pttUsername, pttPassword) } else { + Timber.tag("PTT").w("获取PTT账号失败, code=%d", json.optInt("code")) doPttInit(username, "123456") } } catch (e: Exception) { @@ -352,21 +359,26 @@ class LoginActivity : AppCompatActivity() { } private fun doPttInit(pttUsername: String, pttPassword: String) { + Timber.tag("PTT").d("PTT初始化开始: username=%s", pttUsername) android.os.Handler(android.os.Looper.getMainLooper()).post { Toast.makeText(applicationContext, "PTT初始化中...", Toast.LENGTH_SHORT).show() } // 1. PTT 引擎强制重置后登录 (销毁旧 session,确保干净状态) try { + Timber.tag("PTT").d("发送PTT取消登录指令") com.example.kingway.ptt.SendAtUtil.toCancelLogin() + Timber.tag("PTT").d("发送PTT注销指令") com.example.kingway.ptt.SendAtUtil.toLogout() } catch (e: Exception) { Timber.tag("PTT").e(e, "PTT init error") } // 使用 Handler 替代硬编码 Thread.sleep,避免阻塞或随意开辟线程 + Timber.tag("PTT").d("等待1500ms以确保旧session完全清理") android.os.Handler(android.os.Looper.getMainLooper()).postDelayed({ try { + Timber.tag("PTT").d("发送PTT登录指令: username=%s, ip=%s", pttUsername, "220.154.131.231") com.example.kingway.ptt.SendAtUtil.toLogin(pttUsername, pttPassword, "220.154.131.231", 1, 1) } catch (e: Exception) { Timber.tag("PTT").e(e, "PTT login error") diff --git a/app/src/main/java/com/stand/standapp/MainActivity.kt b/app/src/main/java/com/stand/standapp/MainActivity.kt index b45722a..b2f27ea 100644 --- a/app/src/main/java/com/stand/standapp/MainActivity.kt +++ b/app/src/main/java/com/stand/standapp/MainActivity.kt @@ -49,6 +49,7 @@ class MainActivity : AppCompatActivity() { // 硬件按键触发 @JvmStatic fun onHardwarePttDown() { + Timber.tag("MainActivity").d("onHardwarePttDown triggered") instance?.runOnUiThread { instance?.pttInterface?.pttSpeakPlay() executeJs("onHardwarePttDown()") @@ -57,6 +58,7 @@ class MainActivity : AppCompatActivity() { @JvmStatic fun onHardwarePttUp() { + Timber.tag("MainActivity").d("onHardwarePttUp triggered") instance?.runOnUiThread { instance?.pttInterface?.pttSpeakRelease() executeJs("onHardwarePttUp()") @@ -65,6 +67,7 @@ class MainActivity : AppCompatActivity() { @JvmStatic fun showPttConflictDialog() { + Timber.tag("PTT").w("showPttConflictDialog: account conflict detected") if (isConflictDialogShowing) return isConflictDialogShowing = true instance?.runOnUiThread { @@ -83,10 +86,12 @@ class MainActivity : AppCompatActivity() { @JvmStatic fun showPttUpdateDialog(msg: String, title: String) { + Timber.tag("PTT").w("showPttUpdateDialog: title=%s msg=%s", title, msg) if (isConflictDialogShowing) return val ctx = instance if (ctx == null) { pendingDialog = title to msg + Timber.tag("PTT").d("Pending dialog stored (instance null): title=%s", title) return } isConflictDialogShowing = true @@ -106,6 +111,7 @@ class MainActivity : AppCompatActivity() { @JvmStatic fun showPendingDialogIfNeeded() { val pending = pendingDialog ?: return + Timber.tag("PTT").d("Flushing pending dialog: %s", pending.second) pendingDialog = null showPttUpdateDialog(pending.second, pending.first) } diff --git a/app/src/main/java/com/stand/standapp/utils/GpioManager.kt b/app/src/main/java/com/stand/standapp/utils/GpioManager.kt index 21bb5d0..9de8d9d 100644 --- a/app/src/main/java/com/stand/standapp/utils/GpioManager.kt +++ b/app/src/main/java/com/stand/standapp/utils/GpioManager.kt @@ -78,10 +78,14 @@ object GpioManager { MainActivity.executeJs("updatePttTalkStatus(true)") // 同步 TempCallActivity TempCallActivity.instance?.onGpioPressed() + Timber.tag("GPIO").d("Notified TempCallActivity: onGpioPressed") + } else { + Timber.tag("GPIO").w("GPIO pressed but isSpeaking already true — ignoring") } } else { // 硬件松开 PTT + Timber.tag("GPIO").d("GPIO released, isSpeaking=%s", isSpeaking) if (isSpeaking) { val now = System.currentTimeMillis() val duration = now - lastSpeakTime @@ -109,6 +113,9 @@ object GpioManager { MainActivity.executeJs("updatePttTalkStatus(false)") // 同步 TempCallActivity TempCallActivity.instance?.onGpioReleased() + Timber.tag("GPIO").d("Notified TempCallActivity: onGpioReleased") + } else { + Timber.tag("GPIO").w("GPIO realRelease skipped: already released") } } }