From 735aa7a6fea2f5ea5639758c3ca2ffa79869fb32 Mon Sep 17 00:00:00 2001 From: TrillGates Date: Fri, 6 Aug 2021 15:41:40 +0800 Subject: [PATCH] completed web msg dialog. --- app/src/main/AndroidManifest.xml | 1 + .../com/enqualcomm/support/Constants.java | 1 + .../support/utils/ContextProxy.java | 177 +++++++++--------- .../support/utils/ProcessReceiver.java | 23 ++- .../com/enqualcomm/support/utils/Util.java | 41 ++++ .../java/com/ic/protocols/protocol_s123.java | 120 +++++++----- .../view/webmsgresponse/ShootItemAdapter.java | 64 +++++++ .../webmsgresponse/WebMessageAdapter.java | 117 ++++++++++++ .../ic/view/webmsgresponse/WebMsgView.java | 132 +++++++++++++ .../main/res/drawable/selector_item_bg.xml | 5 + .../res/drawable/shape_item_bg_normal.xml | 5 + .../main/res/drawable/shape_item_bg_press.xml | 9 + app/src/main/res/drawable/shape_text_bg.xml | 9 + app/src/main/res/layout/item_shoot.xml | 16 ++ .../main/res/layout/web_msg_item_content.xml | 85 +++++++++ app/src/main/res/layout/web_msg_item_fail.xml | 37 ++++ .../main/res/layout/web_msg_item_shoot.xml | 71 +++++++ .../main/res/layout/web_msg_item_success.xml | 36 ++++ app/src/main/res/mipmap-mdpi/icon_failed.png | Bin 0 -> 4982 bytes app/src/main/res/mipmap-mdpi/icon_success.png | Bin 0 -> 5417 bytes app/src/main/res/values-de-rCH/strings.xml | 6 + app/src/main/res/values-fr-rCH/strings.xml | 6 + app/src/main/res/values-it-rCH/strings.xml | 6 + app/src/main/res/values-ja/strings.xml | 6 + app/src/main/res/values-w820dp/strings.xml | 9 + app/src/main/res/values-zh-rCN/strings.xml | 6 + app/src/main/res/values/strings.xml | 6 + 27 files changed, 848 insertions(+), 146 deletions(-) create mode 100644 app/src/main/java/com/ic/view/webmsgresponse/ShootItemAdapter.java create mode 100644 app/src/main/java/com/ic/view/webmsgresponse/WebMessageAdapter.java create mode 100644 app/src/main/java/com/ic/view/webmsgresponse/WebMsgView.java create mode 100644 app/src/main/res/drawable/selector_item_bg.xml create mode 100644 app/src/main/res/drawable/shape_item_bg_normal.xml create mode 100644 app/src/main/res/drawable/shape_item_bg_press.xml create mode 100644 app/src/main/res/drawable/shape_text_bg.xml create mode 100644 app/src/main/res/layout/item_shoot.xml create mode 100644 app/src/main/res/layout/web_msg_item_content.xml create mode 100644 app/src/main/res/layout/web_msg_item_fail.xml create mode 100644 app/src/main/res/layout/web_msg_item_shoot.xml create mode 100644 app/src/main/res/layout/web_msg_item_success.xml create mode 100644 app/src/main/res/mipmap-mdpi/icon_failed.png create mode 100644 app/src/main/res/mipmap-mdpi/icon_success.png create mode 100644 app/src/main/res/values-w820dp/strings.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index cf4b15ee..18afbfcf 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -187,6 +187,7 @@ + diff --git a/app/src/main/java/com/enqualcomm/support/Constants.java b/app/src/main/java/com/enqualcomm/support/Constants.java index a8f01e45..925c67cb 100644 --- a/app/src/main/java/com/enqualcomm/support/Constants.java +++ b/app/src/main/java/com/enqualcomm/support/Constants.java @@ -129,6 +129,7 @@ public interface Constants { Uri CM_SERVICE_SETTING = Uri.parse("content://com.cmcm.service/cmsetting"); String DIALOG_ACTION = "com.enqualcomm.support.DIALOG"; + String DIALOG_ACTION_WITH_IC_RESPONSE = "com.ic.dialog.action.DIALOG_RESPONSE"; int ENTER_SILENT_MODE = 212; diff --git a/app/src/main/java/com/enqualcomm/support/utils/ContextProxy.java b/app/src/main/java/com/enqualcomm/support/utils/ContextProxy.java index fd1dec32..8eb1861f 100644 --- a/app/src/main/java/com/enqualcomm/support/utils/ContextProxy.java +++ b/app/src/main/java/com/enqualcomm/support/utils/ContextProxy.java @@ -32,6 +32,7 @@ import static com.enqualcomm.support.Constants.ACTION_KEEPSIT_ALARM; import static com.enqualcomm.support.Constants.ActionReceivePushTxt; import static com.enqualcomm.support.Constants.ActionSrvPushTxt; import static com.enqualcomm.support.Constants.DIALOG_ACTION; +import static com.enqualcomm.support.Constants.DIALOG_ACTION_WITH_IC_RESPONSE; public class ContextProxy { private static final long ONE_WEEK = 604800000L; @@ -381,107 +382,105 @@ public class ContextProxy { } public static void sendMsgBroadcast(Context _context, String msg, int msgType) { - + ICLogger.d("sendMsgBroadcast ==> " + msg + " msgType==> " + msgType); if (msgType == 0) { - mHandler.postDelayed(new Runnable() { - @Override - public void run() { - //本应用弹出消息框 - if (!Config.noPushTxtNotifyDialog) { - Intent intent = new Intent(); - intent.setAction(DIALOG_ACTION); - intent.putExtra("pushtxt", msg); - _context.sendBroadcast(intent); - } else { - WakeLockUtil.ScreenOnWakeLockTemperary(_context); - play_waning_notify(_context); - VibrateUtil.getInstance(_context).VibrateOnOnce(true); - Util.mSleep(2000); - } - //launcher 弹出消息 - if (!Config.noBroadCastPushTxtNotify) { - Intent intent = new Intent(ActionSrvPushTxt); - intent.putExtra("msgType", msgType); //0 代表 server下发消息,1代表 SMS消息 - intent.putExtra("txtMsg", msg); - intent.addFlags(FLAG_ACTIVITY_NEW_TASK); - _context.sendBroadcast(intent); - } + mHandler.postDelayed(() -> { + //本应用弹出消息框 + if (!Config.noPushTxtNotifyDialog) { + Intent intent = new Intent(); + intent.setAction(DIALOG_ACTION); + intent.putExtra("pushtxt", msg); + _context.sendBroadcast(intent); + } else { + WakeLockUtil.ScreenOnWakeLockTemperary(_context); + play_waning_notify(_context); + VibrateUtil.getInstance(_context).VibrateOnOnce(true); + Util.mSleep(2000); + } + //launcher 弹出消息 + if (!Config.noBroadCastPushTxtNotify) { + Intent intent = new Intent(ActionSrvPushTxt); + intent.putExtra("msgType", msgType); //0 代表 server下发消息,1代表 SMS消息 + intent.putExtra("txtMsg", msg); + intent.addFlags(FLAG_ACTIVITY_NEW_TASK); + _context.sendBroadcast(intent); } }, 50); } else if (msgType == 2) { - mHandler.postDelayed(new Runnable() { - @Override - public void run() { - //本应用弹出消息框 - if (Config.noPushTxtNotifyDialog == false) { - Intent intent = new Intent(); - intent.setAction(DIALOG_ACTION); - intent.putExtra("pushtxt", msg); - _context.sendBroadcast(intent); - } else { - WakeLockUtil.ScreenOnWakeLockTemperary(_context); - play_waning_notify(_context); - VibrateUtil.getInstance(_context).VibrateOnOnce(true); - Util.mSleep(2000); - } - //launcher 弹出消息 - if (Config.noBroadCastPushTxtNotify == false) { - Intent intent = new Intent(ActionSrvPushTxt); - intent.putExtra("msgType", msgType); //0 代表 server下发消息,1代表 SMS消息,2代表有提示音的消息 - intent.putExtra("txtMsg", msg); - intent.addFlags(FLAG_ACTIVITY_NEW_TASK); - _context.sendBroadcast(intent); - } + mHandler.postDelayed(() -> { + //本应用弹出消息框 + if (!Config.noPushTxtNotifyDialog) { + Intent intent = new Intent(); + intent.setAction(DIALOG_ACTION); + intent.putExtra("pushtxt", msg); + _context.sendBroadcast(intent); + } else { + WakeLockUtil.ScreenOnWakeLockTemperary(_context); + play_waning_notify(_context); + VibrateUtil.getInstance(_context).VibrateOnOnce(true); + Util.mSleep(2000); + } + //launcher 弹出消息 + if (!Config.noBroadCastPushTxtNotify) { + Intent intent = new Intent(ActionSrvPushTxt); + intent.putExtra("msgType", msgType); //0 代表 server下发消息,1代表 SMS消息,2代表有提示音的消息 + intent.putExtra("txtMsg", msg); + intent.addFlags(FLAG_ACTIVITY_NEW_TASK); + _context.sendBroadcast(intent); } }, 50); } else if (msgType == 3) { //专门给需要回复的消息 - - mHandler.postDelayed(new Runnable() { - @Override - public void run() { - //本应用弹出消息框 - if (Config.noPushTxtNotifyDialog == false) { - Intent intent = new Intent(); - intent.setAction(DIALOG_ACTION); - intent.putExtra("pushtxt", msg); - intent.putExtra("needreply", true); - _context.sendBroadcast(intent); - } else { - WakeLockUtil.ScreenOnWakeLockTemperary(_context); - play_waning_notify(_context); - VibrateUtil.getInstance(_context).VibrateOnOnce(true); - Util.mSleep(2000); - } - + mHandler.postDelayed(() -> { + //本应用弹出消息框 + if (!Config.noPushTxtNotifyDialog) { + Intent intent = new Intent(); + intent.setAction(DIALOG_ACTION); + intent.putExtra("pushtxt", msg); + intent.putExtra("needreply", true); + _context.sendBroadcast(intent); + } else { + WakeLockUtil.ScreenOnWakeLockTemperary(_context); + play_waning_notify(_context); + VibrateUtil.getInstance(_context).VibrateOnOnce(true); + Util.mSleep(2000); } }, 50); + } else if (msgType == 123) { + mHandler.postDelayed(() -> { + //判断是否有弹窗,如查已经弹窗了,那么亮屏即可 + Intent intent = new Intent(); + intent.setAction(DIALOG_ACTION_WITH_IC_RESPONSE); + intent.putExtra("pushTxt", msg); + intent.putExtra("needReply", true); + _context.sendBroadcast(intent); + ICLogger.d("s123 send broadcast..."); + WakeLockUtil.ScreenOnWakeLockTemperary(_context); + play_waning_notify(_context); + VibrateUtil.getInstance(_context).VibrateOnOnce(true); + }, 50); } else { - - mHandler.postDelayed(new Runnable() { - @Override - public void run() { - //本应用弹出消息框 - if (Config.noSMSNotifyDialog == false) { - Intent intent = new Intent(); - intent.setAction(DIALOG_ACTION); - intent.putExtra("sms", msg); - _context.sendBroadcast(intent); - } else { - WakeLockUtil.ScreenOnWakeLockTemperary(_context); - play_waning_notify(_context); - VibrateUtil.getInstance(_context).VibrateOnOnce(true); - Util.mSleep(2000); - } - //launcher 弹出消息 - if (Config.noBroadCastPushTxtNotify == false) { - Intent intent = new Intent(ActionSrvPushTxt); - intent.putExtra("msgType", msgType); //0 代表 server下发消息,1代表 SMS消息,2代表有提示音的消息 - intent.putExtra("txtMsg", msg); - intent.addFlags(FLAG_ACTIVITY_NEW_TASK); - _context.sendBroadcast(intent); - } + mHandler.postDelayed(() -> { + //本应用弹出消息框 + if (!Config.noSMSNotifyDialog) { + Intent intent = new Intent(); + intent.setAction(DIALOG_ACTION); + intent.putExtra("sms", msg); + _context.sendBroadcast(intent); + } else { + WakeLockUtil.ScreenOnWakeLockTemperary(_context); + play_waning_notify(_context); + VibrateUtil.getInstance(_context).VibrateOnOnce(true); + Util.mSleep(2000); + } + //launcher 弹出消息 + if (!Config.noBroadCastPushTxtNotify) { + Intent intent = new Intent(ActionSrvPushTxt); + intent.putExtra("msgType", msgType); //0 代表 server下发消息,1代表 SMS消息,2代表有提示音的消息 + intent.putExtra("txtMsg", msg); + intent.addFlags(FLAG_ACTIVITY_NEW_TASK); + _context.sendBroadcast(intent); } }, 50); } diff --git a/app/src/main/java/com/enqualcomm/support/utils/ProcessReceiver.java b/app/src/main/java/com/enqualcomm/support/utils/ProcessReceiver.java index 02bfb5d1..0a33022c 100644 --- a/app/src/main/java/com/enqualcomm/support/utils/ProcessReceiver.java +++ b/app/src/main/java/com/enqualcomm/support/utils/ProcessReceiver.java @@ -23,6 +23,7 @@ import com.enqualcomm.support.service.AudioService; import com.enqualcomm.support.service.Deliver; import com.enqualcomm.support.service.HeartRateManager; import com.ic.protocols.protocolAPIHelper; +import com.ic.view.webmsgresponse.WebMsgView; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.os.PowerManager.ACQUIRE_CAUSES_WAKEUP; @@ -33,6 +34,7 @@ import static com.enqualcomm.support.Constants.ACTION_REMOTE_CAMERA; import static com.enqualcomm.support.Constants.ACTION_SET_SIT_RANGE; import static com.enqualcomm.support.Constants.ACTION_SHUTDOWN; import static com.enqualcomm.support.Constants.DIALOG_ACTION; +import static com.enqualcomm.support.Constants.DIALOG_ACTION_WITH_IC_RESPONSE; import static com.enqualcomm.support.Constants.FROM_SERVER; import static com.enqualcomm.support.Constants.KEY_MESSAGE_FROM; import static com.enqualcomm.support.Constants.KEY_MESSAGE_TYPE; @@ -320,19 +322,19 @@ public class ProcessReceiver extends BroadcastReceiver { */ if (msgType.equals("voice")) { //创建voiceConent并添加到数据 - final VoiceContent voiceContent = VoiceContent.placeHolderOut(CONTACT_CATEGORY_GROUP, msgFrom,"0000", msgUrl, 1, 3); + final VoiceContent voiceContent = VoiceContent.placeHolderOut(CONTACT_CATEGORY_GROUP, msgFrom, "0000", msgUrl, 1, 3); // 把voiceContent拆解成1024的分包 - Util.parseToVoicePacketSent(voiceContent,1024); + Util.parseToVoicePacketSent(voiceContent, 1024); //trigger 分包发送 if (CoreService.getInstance().getConnection() != null) CoreService.getInstance().getConnection().DeliverCMDMessageToSystem("SentVoicePacket", ""); } else if (msgType.equals("pic")) { //创建voiceConent并添加到数据 - final VoiceContent voiceContent = VoiceContent.placeHolderOut(CONTACT_CATEGORY_GROUP, msgFrom,"0000", msgUrl, 2, 3); + final VoiceContent voiceContent = VoiceContent.placeHolderOut(CONTACT_CATEGORY_GROUP, msgFrom, "0000", msgUrl, 2, 3); // 把voiceContent拆解成1024的分包 - Util.parseToVoicePacketSent(voiceContent,1024); + Util.parseToVoicePacketSent(voiceContent, 1024); //trigger 分包发送 if (CoreService.getInstance().getConnection() != null) { @@ -381,11 +383,11 @@ public class ProcessReceiver extends BroadcastReceiver { String msgUrl = paramIntent.getStringExtra("filepath"); ICLogger.i("receive taken photo to send " + msgUrl); //创建voiceConent并添加到数据 - final VoiceContent voiceContent = VoiceContent.placeHolderOut(CONTACT_CATEGORY_GROUP, msgFrom,"0000", msgUrl, 2, 2); + final VoiceContent voiceContent = VoiceContent.placeHolderOut(CONTACT_CATEGORY_GROUP, msgFrom, "0000", msgUrl, 2, 2); // 把voiceContent拆解成1024的分包 - Util.parseToVoicePacketSent(voiceContent,1024); + Util.parseToVoicePacketSent(voiceContent, 1024); //trigger 分包发送 if (CoreService.getInstance().getConnection() != null) { @@ -502,12 +504,19 @@ public class ProcessReceiver extends BroadcastReceiver { Runtime.lastSitCheckStepCount = CoreService.getInstance().getRuntime().getTotalStepCount(); Runtime.lastSitCheckTiimeyyyyMMddHHmmss = TimeUtil.getSystemTime3(); } + } else if (DIALOG_ACTION_WITH_IC_RESPONSE.equals(str)) { + ICLogger.d("show response ble dialog.."); + //弹出一个需要回复的弹窗 + WebMsgView webMsgView = WebMsgView.getInstance(); + webMsgView.showMsgDialog(); + String pushTxt = paramIntent.getStringExtra("pushTxt"); + ICLogger.d("pushTxt ==> " + pushTxt); + webMsgView.setShowMsg(pushTxt); } else { //如果来电了,还有未读的消息,干脆关掉,防止影响接电话。 if (mCustomDialog != null && mCustomDialog.isShowing()) { mCustomDialog.dismiss(); } - if (this.mCustomNotification != null && this.mCustomNotification.isShowing()) { this.mCustomNotification.dismiss(); } diff --git a/app/src/main/java/com/enqualcomm/support/utils/Util.java b/app/src/main/java/com/enqualcomm/support/utils/Util.java index 0c9d4f7c..2d23b199 100644 --- a/app/src/main/java/com/enqualcomm/support/utils/Util.java +++ b/app/src/main/java/com/enqualcomm/support/utils/Util.java @@ -259,6 +259,47 @@ public class Util { return sb.toString(); } + /** + * 16进制直接转换成为字符串(无需Unicode解码) + * + * @param hex Byte字符串(Byte之间无分隔符 + * @return 对应的字符串 + * @author xxs + */ + public static String hexStr2Str(String hex, String charSet) { + String hexStr = ""; + String str = "0123456789ABCDEF"; //16进制能用到的所有字符 0-15 + for (int i = 0; i < hex.length(); i++) { + String s = hex.substring(i, i + 1); + if (s.equals("a") || s.equals("b") || s.equals("c") || s.equals("d") || s.equals("e") || s.equals("f")) { + s = s.toUpperCase().substring(0, 1); + } + hexStr += s; + } + + char[] hexs = hexStr.toCharArray();//toCharArray() 方法将字符串转换为字符数组。 + int length = (hexStr.length() / 2);//1个byte数值 -> 两个16进制字符 + byte[] bytes = new byte[length]; + int n; + for (int i = 0; i < bytes.length; i++) { + int position = i * 2;//两个16进制字符 -> 1个byte数值 + n = str.indexOf(hexs[position]) * 16; + n += str.indexOf(hexs[position + 1]); + // 保持二进制补码的一致性 因为byte类型字符是8bit的 而int为32bit 会自动补齐高位1 所以与上0xFF之后可以保持高位一致性 + //当byte要转化为int的时候,高的24位必然会补1,这样,其二进制补码其实已经不一致了,&0xff可以将高的24位置为0,低8位保持原样,这样做的目的就是为了保证二进制数据的一致性。 + bytes[i] = (byte) (n & 0xff); + } + String name = ""; + try { + name = new String(bytes, charSet); + } catch (UnsupportedEncodingException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return name; + } + /** * 此函数专门给L02 协议使用 ,解析名字用 * diff --git a/app/src/main/java/com/ic/protocols/protocol_s123.java b/app/src/main/java/com/ic/protocols/protocol_s123.java index 9b594ebb..85f7ed33 100644 --- a/app/src/main/java/com/ic/protocols/protocol_s123.java +++ b/app/src/main/java/com/ic/protocols/protocol_s123.java @@ -179,7 +179,21 @@ public class protocol_s123 { //IWAP94,123456,1,XXXXXXXXXXXXXXXX //以下这部分内容由UI给到数据库再给过来 //123456,1,XXXXXXXXXXXXXXXX - //TODO: + String[] split = value.split(CMDSPLIT); + if (split.length == 3) { + //对数据进行编码 + genStringMessage(cmdMap.get(CMD_TYPE.AP94), + new StringBuilder() + .append(CMDHEADER) + .append(cmdMap.get(CMD_TYPE.AP94)) + .append(CMDSPLIT).append(split[0]) + .append(CMDSPLIT).append(split[1]) + .append(CMDSPLIT).append(Util.utf8ToUnicode(split[2])) + .append(CMDEND) + .toString()); + } else { + ICLogger.d("parse send msg error==> " + value); + } } public enum CMD_TYPE { @@ -1549,8 +1563,6 @@ public class protocol_s123 { String[] cmdlist = cmd.split(","); if (cmdlist.length == 6) { - - log("com.ic.work mode " + cmdlist[3]); try { int mod = Integer.parseInt(cmdlist[3]); @@ -1593,55 +1605,63 @@ public class protocol_s123 { ICLogger.d("cmd == > " + cmd); //这里的切割,如查是云图的后台,会有问题,如果文本内容里有,那么就会切割出错了。所以需要后台去解决这个问题。 String[] cmdlist = cmd.split(","); - ICLogger.d("cmdlist length == > " + cmdlist); - if (cmdlist.length == 4) { - String cmdindex = cmdlist[2]; - String txtmsg = cmdlist[3]; - StringBuilder sb = new StringBuilder(); - Runtime.PushtxtMsg_srv_index = cmdindex;//给回复AP94用 - sb.append(cmdindex).append(CMDSPLIT).append(TimeUtil.getSystemTimeyyyyMMddHHmmss()).append(CMDSPLIT).append(txtmsg); - if (Config.custom_name.equals("VitracK")) { - - } else if (Util.getSystemProperties("persist.sys.pushtxt_encode", "gb2312").equals("utf-8")) { - // txtmsg = Util.decodeUnicode2Utf8(txtmsg); + ICLogger.d("cmdlist length == > " + cmdlist.length); + if (cmdlist.length == 5) { + String cmdIndex = cmdlist[2]; + //新增加的类型 + //TODO: + String type = cmdlist[3]; + ICLogger.d("web msg type ==> " + type); + String txtMsg = Util.hexStr2Str(cmdlist[4], "gb2312"); + if ("2".equals(type)) { + //文本消息 + StringBuilder sb = new StringBuilder(); + Runtime.PushtxtMsg_srv_index = cmdIndex;//给回复AP94用 + sb.append(cmdIndex).append(CMDSPLIT).append(TimeUtil.getSystemTimeyyyyMMddHHmmss()).append(CMDSPLIT).append(txtMsg); + if (Config.custom_name.equals("VitracK")) { + + } else if (Util.getSystemProperties("persist.sys.pushtxt_encode", "gb2312").equals("utf-8")) { + // txtmsg = Util.decodeUnicode2Utf8(txtmsg); // txtmsg = Util.UrlGB2312ToUTF8(txtmsg); - txtmsg = Util.UrlUTF8ToStrUTF8(txtmsg); - } else { - txtmsg = Util.UrlGB2312ToUTF8(txtmsg); - } - StringMessage msg = AP40(cmdindex, 1); - //设定当前工作模式及循环频率 - connection.send(msg); - ICLogger.i("received Txt Msg " + txtmsg); - if (!Config.noPushTxtReadReply) { - Config.setLastUnReadMessage(runtime.getContextProxy().context, sb.toString()); - runtime.getContextProxy().sendMsgBroadcast(txtmsg, 3);//msgType 3需要回复,0不需要回复 - } else { - //读取一个变量值,判断是否强制弹窗 - String forceReadMsg = Util.getSystemProperties("persist.sys.forcereadmsg"); - ICLogger.d("forceReadMsg == > " + forceReadMsg); - if (!TextUtils.isEmpty(forceReadMsg)) { - //强制阅读的话,弹窗显示 - MsgMustReadDialog instance = MsgMustReadDialog.getInstance(); - instance.showMsgDialog(); - List list = new ArrayList<>(); - list.add(txtmsg); - instance.addData(list); + txtMsg = Util.UrlUTF8ToStrUTF8(txtMsg); } else { - //msgType 3需要回复,0不需要回复 - runtime.getContextProxy().sendMsgBroadcast(txtmsg, 0); + txtMsg = Util.UrlGB2312ToUTF8(txtMsg); } + StringMessage msg = AP40(cmdIndex, 1); + //设定当前工作模式及循环频率 + connection.send(msg); + ICLogger.i("received Txt Msg " + txtMsg); + if (!Config.noPushTxtReadReply) { + Config.setLastUnReadMessage(runtime.getContextProxy().context, sb.toString()); + runtime.getContextProxy().sendMsgBroadcast(txtMsg, 3);//msgType 3需要回复,0不需要回复 + } else { + //读取一个变量值,判断是否强制弹窗 + String forceReadMsg = Util.getSystemProperties("persist.sys.forcereadmsg"); + ICLogger.d("forceReadMsg == > " + forceReadMsg); + if (!TextUtils.isEmpty(forceReadMsg)) { + //强制阅读的话,弹窗显示 + MsgMustReadDialog instance = MsgMustReadDialog.getInstance(); + instance.showMsgDialog(); + List list = new ArrayList<>(); + list.add(txtMsg); + instance.addData(list); + } else { + //msgType 3需要回复,0不需要回复 + //123表示s123的,需要回复已读,或者回复文本消息 + runtime.getContextProxy().sendMsgBroadcast(txtMsg, 123); + } + } + //保存到云短信的库里 + ContentResolver resolver = runtime.getContextProxy().getResolver(); + ContentValues contentValues = new ContentValues(); + contentValues.put(ICDatabaseHelper.web_sms_content, txtMsg); + //弹窗表示已阅读了 + contentValues.put(ICDatabaseHelper.web_sms_has_read, 1); + contentValues.put(ICDatabaseHelper.web_sms_create_time, System.currentTimeMillis()); + resolver.insert(Uri.parse(WebSmsProvider.WEB_MSG), contentValues); + //保存到数据库里,以下是原来的做法 + //runtime.getContextProxy().saveMstToSMSDB(txtmsg); } - //保存到云短信的库里 - ContentResolver resolver = runtime.getContextProxy().getResolver(); - ContentValues contentValues = new ContentValues(); - contentValues.put(ICDatabaseHelper.web_sms_content, txtmsg); - //弹窗表示已阅读了 - contentValues.put(ICDatabaseHelper.web_sms_has_read, 1); - contentValues.put(ICDatabaseHelper.web_sms_create_time, System.currentTimeMillis()); - resolver.insert(Uri.parse(WebSmsProvider.WEB_MSG), contentValues); - //保存到数据库里,以下是原来的做法 - //runtime.getContextProxy().saveMstToSMSDB(txtmsg); } else { ICLogger.i("BP40 format error!"); } @@ -3510,14 +3530,14 @@ public class protocol_s123 { break; case BP40: //服务器推送文本 - handleBP40(mConnection, mRuntime, cmd); ICLogger.i("收到服务器推送文本消息"); + handleBP40(mConnection, mRuntime, cmd); mConnection.DeliverCMDMessageToSystem("showTxt", cmd);//通知下面线程状态变化 break; case BPXL: - handleBPXL(cmd, mConnection); ICLogger.i("收到服务器心率检测命令"); + handleBPXL(cmd, mConnection); if (mRuntime.check_stat_do_ppg_test()) { HeartRateManager.getInstance().triggerPPGTest(FROM_SERVER); } diff --git a/app/src/main/java/com/ic/view/webmsgresponse/ShootItemAdapter.java b/app/src/main/java/com/ic/view/webmsgresponse/ShootItemAdapter.java new file mode 100644 index 00000000..a81b41ae --- /dev/null +++ b/app/src/main/java/com/ic/view/webmsgresponse/ShootItemAdapter.java @@ -0,0 +1,64 @@ +package com.ic.view.webmsgresponse; + +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.enqualcomm.support.R; + +import java.util.ArrayList; +import java.util.List; + +public class ShootItemAdapter extends RecyclerView.Adapter { + + private final List dataList = new ArrayList<>(); + private OnItemClickListener mItemClickListener; + + @Override + public InnerHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_shoot, parent, false); + return new InnerHolder(itemView); + } + + @Override + public void onBindViewHolder(InnerHolder holder, int position) { + TextView itemTextView = (TextView) holder.itemView.findViewById(R.id.shoot_item_tv); + String itemText = dataList.get(position); + itemTextView.setText(itemText); + //设置点击事件 + holder.itemView.setOnClickListener(v -> { + if (mItemClickListener != null) { + mItemClickListener.onItemClick(itemText); + } + }); + } + + @Override + public int getItemCount() { + return dataList.size(); + } + + public void updateData(List dataList) { + this.dataList.clear(); + this.dataList.addAll(dataList); + notifyDataSetChanged(); + } + + + public void setOnItemClickListener(OnItemClickListener listener) { + this.mItemClickListener = listener; + } + + public interface OnItemClickListener { + void onItemClick(String text); + } + + + public class InnerHolder extends RecyclerView.ViewHolder { + public InnerHolder(View itemView) { + super(itemView); + } + } +} diff --git a/app/src/main/java/com/ic/view/webmsgresponse/WebMessageAdapter.java b/app/src/main/java/com/ic/view/webmsgresponse/WebMessageAdapter.java new file mode 100644 index 00000000..94336fd6 --- /dev/null +++ b/app/src/main/java/com/ic/view/webmsgresponse/WebMessageAdapter.java @@ -0,0 +1,117 @@ +package com.ic.view.webmsgresponse; + +import android.graphics.Rect; +import android.support.v4.view.PagerAdapter; +import android.support.v4.view.ViewPager; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.enqualcomm.support.R; + +import java.util.List; + +public class WebMessageAdapter extends PagerAdapter { + + private final ViewPager mViewPager; + private TextView webMsgView; + private RecyclerView shootListView; + private String mCurrentText; + private ShootItemAdapter shootItemAdapter; + private List mResponseTextList; + private View replyBtn; + + public WebMessageAdapter(ViewPager msgPage) { + this.mViewPager = msgPage; + } + + @Override + public Object instantiateItem(ViewGroup container, int position) { + //根据位置来加载内容 + View item; + if (position == 0) { + item = View.inflate(container.getContext(), R.layout.web_msg_item_content, null); + webMsgView = (TextView) item.findViewById(R.id.web_msg_tv); + if (TextUtils.isEmpty(mCurrentText)) { + webMsgView.setText(mCurrentText); + } + replyBtn = item.findViewById(R.id.reply_btn); + //设置点击事件 + replyBtn.setOnClickListener(v -> { + //跳转到列表页面 + if (mViewPager != null) { + //第二个页面是数据选择的页面 + mViewPager.setCurrentItem(1); + } + }); + } else if (position == 1) { + item = View.inflate(container.getContext(), R.layout.web_msg_item_shoot, null); + shootListView = (RecyclerView) item.findViewById(R.id.shoot_list_view); + if (shootItemAdapter == null) { + shootItemAdapter = new ShootItemAdapter(); + } + shootListView.setLayoutManager(new LinearLayoutManager(container.getContext())); + shootListView.addItemDecoration(new RecyclerView.ItemDecoration() { + @Override + public void getItemOffsets(Rect outRect, View view, + RecyclerView parent, + RecyclerView.State state) { + outRect.top = 1; + outRect.bottom = 1; + } + }); + //设置适配器 + shootListView.setAdapter(shootItemAdapter); + if (mResponseTextList != null) { + shootItemAdapter.updateData(mResponseTextList); + } + } else if (position == 2) { + item = View.inflate(container.getContext(), R.layout.web_msg_item_success, null); + } else { + item = View.inflate(container.getContext(), R.layout.web_msg_item_fail, null); + } + container.addView(item); + return item; + } + + @Override + public void destroyItem(ViewGroup container, int position, Object object) { + container.removeView((View) object); + } + + @Override + public int getCount() { + return 4;//4个页面, + //一个是消息页面, + //一个是快捷回复页面 + //一个是成功页面 + //一个是失败页面 + } + + @Override + public boolean isViewFromObject(View view, Object object) { + return view == object; + } + + @Override + public int getItemPosition(Object object) { + return POSITION_NONE; + } + + public void updateShootList(List responseText) { + this.mResponseTextList = responseText; + if (shootItemAdapter != null) { + shootItemAdapter.updateData(responseText); + } + } + + public void updateMsgText(String text) { + this.mCurrentText = text; + if (webMsgView != null) { + webMsgView.setText(text); + } + } +} diff --git a/app/src/main/java/com/ic/view/webmsgresponse/WebMsgView.java b/app/src/main/java/com/ic/view/webmsgresponse/WebMsgView.java new file mode 100644 index 00000000..8aeb8e2c --- /dev/null +++ b/app/src/main/java/com/ic/view/webmsgresponse/WebMsgView.java @@ -0,0 +1,132 @@ +package com.ic.view.webmsgresponse; + +import android.content.ContentResolver; +import android.content.Context; +import android.database.Cursor; +import android.net.Uri; +import android.support.v4.view.ViewPager; +import android.text.TextUtils; +import android.view.Gravity; +import android.view.View; +import android.view.WindowManager; + +import com.enqualcomm.support.ICApplication; +import com.enqualcomm.support.R; +import com.enqualcomm.support.provider.ShootTextProvider; +import com.enqualcomm.support.utils.ICLogger; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * 云消息&短信弹窗 + * 直接塞到Window里 + * 要求:不阅读完,不可以关闭 + * 交互:阅读完,有下一页的按钮,最后一页才有关闭按钮。 + */ +public class WebMsgView { + + private WindowManager windowManager; + private WebMessageAdapter messageAdapter; + private ViewPager msgPage; + private ExecutorService executorService; + private ContentResolver contentResolver; + private View view; + private String currentText; + + private WebMsgView() { + //获取到数据库里的数据,显示快捷回复列表 + executorService = Executors.newSingleThreadExecutor(); + } + + private final List responseText = new ArrayList<>(); + + private void initShootData() { + executorService.execute(() -> { + responseText.clear(); + contentResolver = ICApplication.sContext.getContentResolver(); + Cursor query = contentResolver.query(Uri.parse(ShootTextProvider.SHOOT_TEXT), + new String[]{"_id", "value"}, + "type=?", new String[]{"3"}, null); + if (query != null) { + while (query.moveToNext()) { + String text = query.getString(1); + ICLogger.d("text ==> " + text); + responseText.add(text); + } + query.close(); + } + if (view != null && messageAdapter != null) { + view.post(() -> { + messageAdapter.updateShootList(responseText); + }); + } + }); + } + + private static WebMsgView sInstance; + + public static WebMsgView getInstance() { + if (sInstance == null) { + sInstance = new WebMsgView(); + } + return sInstance; + } + + private boolean isShow = false; + + public void showMsgDialog() { + ICLogger.d("showMsgDialog..." + isShow); + if (isShow) { + return; + } + isShow = true; + Context context = ICApplication.sContext; + windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + //设置属性 + WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(); + layoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; + //这个是针对S123的屏幕,如果要适配其他,可以动态获取屏幕宽度,高度,再以百分比的形式计算即可。 + layoutParams.height = WindowManager.LayoutParams.MATCH_PARENT; + layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT; + layoutParams.packageName = context.getPackageName(); + layoutParams.gravity = Gravity.CENTER; + //加载布局 + view = View.inflate(context, R.layout.msg_dialog_layout, null); + //设置适配器 + initView(view); + //准备数据 + //添加到Window里 + initShootData(); + windowManager.addView(view, layoutParams); + } + + public void setShowMsg(String text) { + this.currentText = text; + //设置要显示的消息 + if (messageAdapter != null) { + messageAdapter.updateMsgText(text); + } + } + + public void dismiss() { + executorService.shutdown(); + executorService = null; + sInstance = null; + contentResolver = null; + } + + + private void initView(final View view) { + msgPage = (ViewPager) view.findViewById(R.id.msg_pager); + msgPage.setOffscreenPageLimit(2); + //设置适配器 + messageAdapter = new WebMessageAdapter(msgPage); + if (!TextUtils.isEmpty(currentText)) { + messageAdapter.updateMsgText(currentText); + } + msgPage.setAdapter(messageAdapter); + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_item_bg.xml b/app/src/main/res/drawable/selector_item_bg.xml new file mode 100644 index 00000000..c8cbe35d --- /dev/null +++ b/app/src/main/res/drawable/selector_item_bg.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_item_bg_normal.xml b/app/src/main/res/drawable/shape_item_bg_normal.xml new file mode 100644 index 00000000..6b610f6c --- /dev/null +++ b/app/src/main/res/drawable/shape_item_bg_normal.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_item_bg_press.xml b/app/src/main/res/drawable/shape_item_bg_press.xml new file mode 100644 index 00000000..f0862021 --- /dev/null +++ b/app/src/main/res/drawable/shape_item_bg_press.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_text_bg.xml b/app/src/main/res/drawable/shape_text_bg.xml new file mode 100644 index 00000000..c8e3c78c --- /dev/null +++ b/app/src/main/res/drawable/shape_text_bg.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_shoot.xml b/app/src/main/res/layout/item_shoot.xml new file mode 100644 index 00000000..0f772996 --- /dev/null +++ b/app/src/main/res/layout/item_shoot.xml @@ -0,0 +1,16 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/web_msg_item_content.xml b/app/src/main/res/layout/web_msg_item_content.xml new file mode 100644 index 00000000..f97e8c57 --- /dev/null +++ b/app/src/main/res/layout/web_msg_item_content.xml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/web_msg_item_fail.xml b/app/src/main/res/layout/web_msg_item_fail.xml new file mode 100644 index 00000000..54bee0f0 --- /dev/null +++ b/app/src/main/res/layout/web_msg_item_fail.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/web_msg_item_shoot.xml b/app/src/main/res/layout/web_msg_item_shoot.xml new file mode 100644 index 00000000..e92f1d7e --- /dev/null +++ b/app/src/main/res/layout/web_msg_item_shoot.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/web_msg_item_success.xml b/app/src/main/res/layout/web_msg_item_success.xml new file mode 100644 index 00000000..f3cf520f --- /dev/null +++ b/app/src/main/res/layout/web_msg_item_success.xml @@ -0,0 +1,36 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-mdpi/icon_failed.png b/app/src/main/res/mipmap-mdpi/icon_failed.png new file mode 100644 index 0000000000000000000000000000000000000000..68ef972c2f950c0131b3ff64c2d8234e89661db4 GIT binary patch literal 4982 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 TnrS{a00000NkvXXu0mjfKk`f` literal 0 HcmV?d00001 diff --git a/app/src/main/res/values-de-rCH/strings.xml b/app/src/main/res/values-de-rCH/strings.xml index d8d91115..993d27d8 100644 --- a/app/src/main/res/values-de-rCH/strings.xml +++ b/app/src/main/res/values-de-rCH/strings.xml @@ -159,4 +159,10 @@ 低电量报警 SOS紧急报警 %s发出了SOS信号。%s + 已阅读 + 回复 + 发送失败请重试 + 发送成功 + 返回 + 发送 diff --git a/app/src/main/res/values-fr-rCH/strings.xml b/app/src/main/res/values-fr-rCH/strings.xml index d8d91115..993d27d8 100644 --- a/app/src/main/res/values-fr-rCH/strings.xml +++ b/app/src/main/res/values-fr-rCH/strings.xml @@ -159,4 +159,10 @@ 低电量报警 SOS紧急报警 %s发出了SOS信号。%s + 已阅读 + 回复 + 发送失败请重试 + 发送成功 + 返回 + 发送 diff --git a/app/src/main/res/values-it-rCH/strings.xml b/app/src/main/res/values-it-rCH/strings.xml index b619edec..358fc5fa 100644 --- a/app/src/main/res/values-it-rCH/strings.xml +++ b/app/src/main/res/values-it-rCH/strings.xml @@ -157,4 +157,10 @@ 低电量报警 SOS紧急报警 %s发出了SOS信号。%s + 已阅读 + 回复 + 发送失败请重试 + 发送成功 + 返回 + 发送 diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index b61ca7c8..022080f6 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -160,5 +160,11 @@ 低電力アラート 緊急SOS %sからSOSが発信されました。%s + 已阅读 + 回复 + 发送失败请重试 + 发送成功 + 返回 + 发送 diff --git a/app/src/main/res/values-w820dp/strings.xml b/app/src/main/res/values-w820dp/strings.xml new file mode 100644 index 00000000..49acd3b8 --- /dev/null +++ b/app/src/main/res/values-w820dp/strings.xml @@ -0,0 +1,9 @@ + + + 已阅读 + 回复 + 发送失败请重试 + 发送成功 + 返回 + 发送 + \ No newline at end of file diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index b43a9b64..089d5ff6 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -187,4 +187,10 @@ 低电量报警 SOS紧急报警 %s发出了SOS信号。%s + 已阅读 + 回复 + 发送失败请重试 + 发送成功 + 返回 + 发送 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b93e7b8f..cf9b7f85 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -190,5 +190,11 @@ SOS紧急报警 SOS was sent from "%s". %s + 已阅读 + 回复 + 发送失败请重试 + 发送成功 + 返回 + 发送 -- 2.17.1