Merge branch 'develop_liyi' of http://code.star-lock.cn/StarlockTeam/app-starlock into develop_liyi
This commit is contained in:
commit
cc8babf730
@ -91,6 +91,8 @@ generate_git_tag:
|
||||
stage: generate_tag_or_version
|
||||
extends: .generate_tag_rule
|
||||
before_script:
|
||||
- bash pre_build.sh xhj
|
||||
- bash pre_build.sh sky
|
||||
- project_url=$(echo $CI_PROJECT_URL | sed 's/http:\/\///')
|
||||
- echo "project_url:$project_url"
|
||||
- git remote set-url origin http://gitlab-ci-token:${GITLAB_ACCESS_TOKEN}@$project_url.git
|
||||
|
||||
@ -7,7 +7,9 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
04C1FC572D13F1A2000C959E /* InfoPlist.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 04C1FC562D13F1A2000C959E /* InfoPlist.xcstrings */; };
|
||||
04717D692D1B97E100089BD3 /* InfoPlist_sky.strings in Resources */ = {isa = PBXBuildFile; fileRef = 04717D672D1B97E100089BD3 /* InfoPlist_sky.strings */; };
|
||||
04717D6D2D1B983300089BD3 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 04717D6B2D1B983200089BD3 /* InfoPlist.strings */; };
|
||||
04717D712D1B9B5A00089BD3 /* InfoPlist_xhj.strings in Resources */ = {isa = PBXBuildFile; fileRef = 04717D6F2D1B9B5A00089BD3 /* InfoPlist_xhj.strings */; };
|
||||
04D0CC262D06CE570042EF10 /* launchImage_xhj.png in Resources */ = {isa = PBXBuildFile; fileRef = 82B657662C919BDF0079121C /* launchImage_xhj.png */; };
|
||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||
25B2A1422F9A2CCCBBCBBB97 /* skyRelease.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 35F02D170492750B437D6AB6 /* skyRelease.xcconfig */; };
|
||||
@ -98,8 +100,13 @@
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
0420903B2C0EEAA50073E654 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Main.strings"; sourceTree = "<group>"; };
|
||||
04717D682D1B97E100089BD3 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/InfoPlist_sky.strings"; sourceTree = "<group>"; };
|
||||
04717D6A2D1B97E800089BD3 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist_sky.strings; sourceTree = "<group>"; };
|
||||
04717D6C2D1B983200089BD3 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
04717D6E2D1B983900089BD3 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
|
||||
04717D702D1B9B5A00089BD3 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/InfoPlist_xhj.strings"; sourceTree = "<group>"; };
|
||||
04717D722D1B9B5D00089BD3 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist_xhj.strings; sourceTree = "<group>"; };
|
||||
04BFC4482BCFE05100688FCA /* RunnerRelease-xhj.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "RunnerRelease-xhj.entitlements"; sourceTree = "<group>"; };
|
||||
04C1FC562D13F1A2000C959E /* InfoPlist.xcstrings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json.xcstrings; path = InfoPlist.xcstrings; sourceTree = "<group>"; };
|
||||
0BEB3ADCCEC961E2916B9004 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
0D02C18E16914A687A4A1AC2 /* devDebug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = devDebug.xcconfig; path = Flutter/devDebug.xcconfig; sourceTree = "<group>"; };
|
||||
126D1370182AB44291C67A10 /* Pods-Runner.dev-release-sky.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.dev-release-sky.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.dev-release-sky.xcconfig"; sourceTree = "<group>"; };
|
||||
@ -343,7 +350,7 @@
|
||||
97C146F01CF9000F007C117D /* Runner */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
04C1FC562D13F1A2000C959E /* InfoPlist.xcstrings */,
|
||||
04717D6B2D1B983200089BD3 /* InfoPlist.strings */,
|
||||
E0B3E9EC2D04B36C00907A95 /* info_dev.plist */,
|
||||
E0B3E9EB2D04B36C00907A95 /* info_pre.plist */,
|
||||
E0B3E9EA2D04B36C00907A95 /* info_sky.plist */,
|
||||
@ -366,6 +373,8 @@
|
||||
82BD91212ADA72360018E523 /* CommonDefine.h */,
|
||||
76C3321F45DA6AE46ED83204 /* RunnerDebug-dev.entitlements */,
|
||||
16D90D130794DF74DA656999 /* RunnerRelease-sky.entitlements */,
|
||||
04717D672D1B97E100089BD3 /* InfoPlist_sky.strings */,
|
||||
04717D6F2D1B9B5A00089BD3 /* InfoPlist_xhj.strings */,
|
||||
);
|
||||
path = Runner;
|
||||
sourceTree = "<group>";
|
||||
@ -431,6 +440,7 @@
|
||||
9740EEB61CF901F6004384FC /* Run Script */,
|
||||
97C146EA1CF9000F007C117D /* Sources */,
|
||||
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||
04717D732D1B9CCA00089BD3 /* ShellScript */,
|
||||
97C146EC1CF9000F007C117D /* Resources */,
|
||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||
@ -487,12 +497,14 @@
|
||||
04D0CC262D06CE570042EF10 /* launchImage_xhj.png in Resources */,
|
||||
82F1ED1C2BE8BA8F00265D59 /* BioAuthEngine.bundle in Resources */,
|
||||
82B657692C919DA70079121C /* launchImage_sky.png in Resources */,
|
||||
04717D712D1B9B5A00089BD3 /* InfoPlist_xhj.strings in Resources */,
|
||||
82F1ED1A2BE8BA7D00265D59 /* OCRXMedia.bundle in Resources */,
|
||||
82F1ED182BE8BA6900265D59 /* APBToygerFacadeSuitable.bundle in Resources */,
|
||||
82F1ED162BE8BA2000265D59 /* APBToygerFacade.bundle in Resources */,
|
||||
E0B3E9ED2D04B36C00907A95 /* info_xhj.plist in Resources */,
|
||||
82F1ED142BE8B9F400265D59 /* ToygerService.bundle in Resources */,
|
||||
82C026542AE8AC6D0011FE6A /* AliyunEmasServices-Info.plist in Resources */,
|
||||
04717D6D2D1B983300089BD3 /* InfoPlist.strings in Resources */,
|
||||
E0A496C92CA30C2C00E376BB /* xhjDevRelease.xcconfig in Resources */,
|
||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
|
||||
E0A496CD2CA30CA900E376BB /* skyDevRelease.xcconfig in Resources */,
|
||||
@ -510,9 +522,9 @@
|
||||
9C453CBFAB0703DFA762337C /* preProfile.xcconfig in Resources */,
|
||||
44827AC367F1EAB110A97660 /* preRelease.xcconfig in Resources */,
|
||||
D7EF77645AB1C3CEEA536468 /* skyDebug.xcconfig in Resources */,
|
||||
04C1FC572D13F1A2000C959E /* InfoPlist.xcstrings in Resources */,
|
||||
7B54002BF45E5D8B295B6447 /* skyProfile.xcconfig in Resources */,
|
||||
25B2A1422F9A2CCCBBCBBB97 /* skyRelease.xcconfig in Resources */,
|
||||
04717D692D1B97E100089BD3 /* InfoPlist_sky.strings in Resources */,
|
||||
ADF948FD9EE8BD1AE71F0984 /* xhjDebug.xcconfig in Resources */,
|
||||
E0B3E9F02D04B36D00907A95 /* info_dev.plist in Resources */,
|
||||
EE0A7A61CF36BC83ACA6EE3E /* xhjProfile.xcconfig in Resources */,
|
||||
@ -527,6 +539,24 @@
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
04717D732D1B9CCA00089BD3 /* ShellScript */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "# Type a script or drag a script file from your workspace to insert its path.\n# env\nCONFIGURATION_NAME=\"${CONFIGURATION}\"\necho \"-----===${CONFIGURATION_NAME}===------\"\nSTRINGS_FILE=\"\"\nif [[ \"$CONFIGURATION_NAME\" == *\"sky\"* ]]; then\n STRINGS_FILE=\"InfoPlist_sky.strings\"\nelif [[ \"$CONFIGURATION_NAME\" == *\"xhj\"* ]]; then\n STRINGS_FILE=\"InfoPlist_xhj.strings\"\nelse\n STRINGS_FILE=\"InfoPlist.strings\"\nfi\necho \"-----===${STRINGS_FILE}===------\"\necho \"=====${SRCROOT}====\"\nif [[ \"$STRINGS_FILE\" == \"InfoPlist.strings\" ]]; then\n echo \"=====use Default InfoPlist.strings====\"\n exit 0;\nfi\n# 替换目标目录中的 InfoPlist.strings\nfor lang in $(ls \"${SRCROOT}/Runner\" | grep .lproj); do\n echo \"-----===${lang}===------\"\n cp \"${SRCROOT}/Runner/${lang}/${STRINGS_FILE}\" \"${SRCROOT}/Runner/${lang}/InfoPlist.strings\"\ndone\n";
|
||||
};
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
@ -614,6 +644,33 @@
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
04717D672D1B97E100089BD3 /* InfoPlist_sky.strings */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
04717D682D1B97E100089BD3 /* zh-Hans */,
|
||||
04717D6A2D1B97E800089BD3 /* en */,
|
||||
);
|
||||
name = InfoPlist_sky.strings;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
04717D6B2D1B983200089BD3 /* InfoPlist.strings */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
04717D6C2D1B983200089BD3 /* en */,
|
||||
04717D6E2D1B983900089BD3 /* zh-Hans */,
|
||||
);
|
||||
name = InfoPlist.strings;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
04717D6F2D1B9B5A00089BD3 /* InfoPlist_xhj.strings */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
04717D702D1B9B5A00089BD3 /* zh-Hans */,
|
||||
04717D722D1B9B5D00089BD3 /* en */,
|
||||
);
|
||||
name = InfoPlist_xhj.strings;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
@ -703,8 +760,10 @@
|
||||
buildSettings = {
|
||||
CODE_SIGN_ENTITLEMENTS = "Runner/RunnerRelease-sky.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = SF86QP26TZ;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = NAQ5PL2DYC;
|
||||
INFOPLIST_FILE = Runner/info_sky.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
@ -714,6 +773,7 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.starlock.lock.local;
|
||||
PRODUCT_NAME = Runner;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = Debug_com.starlock.lock.local.mobileprovision;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
@ -798,8 +858,10 @@
|
||||
buildSettings = {
|
||||
CODE_SIGN_ENTITLEMENTS = "Runner/RunnerRelease-xhj.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = SF86QP26TZ;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = NAQ5PL2DYC;
|
||||
INFOPLIST_FILE = Runner/info_xhj.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
@ -809,6 +871,7 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.starlock.lock.local;
|
||||
PRODUCT_NAME = Runner;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = Debug_com.starlock.lock.local.mobileprovision;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
@ -822,8 +885,10 @@
|
||||
buildSettings = {
|
||||
CODE_SIGN_ENTITLEMENTS = "Runner/RunnerRelease-sky.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = NAQ5PL2DYC;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = NAQ5PL2DYC;
|
||||
INFOPLIST_FILE = Runner/info_sky.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
@ -832,6 +897,7 @@
|
||||
);
|
||||
PRODUCT_NAME = Runner;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = Appstore_com.skychip.lock.mobileprovision;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
@ -845,8 +911,10 @@
|
||||
buildSettings = {
|
||||
CODE_SIGN_ENTITLEMENTS = "Runner/RunnerRelease-xhj.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = P8997RW3V8;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = P8997RW3V8;
|
||||
INFOPLIST_FILE = Runner/info_xhj.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
@ -856,6 +924,7 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.xhjcn.lock;
|
||||
PRODUCT_NAME = Runner;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = Appstore_com.xhjcn.lock.mobileprovision;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
@ -1088,8 +1157,10 @@
|
||||
buildSettings = {
|
||||
CODE_SIGN_ENTITLEMENTS = "Runner/RunnerDebug-dev.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = SF86QP26TZ;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = NAQ5PL2DYC;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
@ -1099,6 +1170,7 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.starlock.lock.local;
|
||||
PRODUCT_NAME = Runner;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = Debug_com.starlock.lock.local.mobileprovision;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
@ -1183,8 +1255,10 @@
|
||||
buildSettings = {
|
||||
CODE_SIGN_ENTITLEMENTS = "Runner/RunnerRelease-sky.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = NAQ5PL2DYC;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = NAQ5PL2DYC;
|
||||
INFOPLIST_FILE = Runner/info_sky.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
@ -1194,6 +1268,7 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.skychip.lock.pre;
|
||||
PRODUCT_NAME = Runner;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = Adhoc_com.skychip.lock.pre.mobileprovision;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
@ -1278,8 +1353,10 @@
|
||||
buildSettings = {
|
||||
CODE_SIGN_ENTITLEMENTS = "Runner/RunnerRelease-sky.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = NAQ5PL2DYC;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = NAQ5PL2DYC;
|
||||
INFOPLIST_FILE = Runner/info_sky.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
@ -1289,6 +1366,7 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.skychip.lock.dev;
|
||||
PRODUCT_NAME = Runner;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = Adhoc_com.skychip.lock.dev.mobileprovision;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
@ -1373,8 +1451,10 @@
|
||||
buildSettings = {
|
||||
CODE_SIGN_ENTITLEMENTS = "Runner/RunnerRelease-xhj.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = P8997RW3V8;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = P8997RW3V8;
|
||||
INFOPLIST_FILE = Runner/info_xhj.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
@ -1384,6 +1464,7 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.xhjcn.lock.pre;
|
||||
PRODUCT_NAME = Runner;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = Adhoc_com.xhjcn.lock.pre.mobileprovision;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
@ -1468,8 +1549,10 @@
|
||||
buildSettings = {
|
||||
CODE_SIGN_ENTITLEMENTS = "Runner/RunnerRelease-xhj.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = P8997RW3V8;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = P8997RW3V8;
|
||||
INFOPLIST_FILE = Runner/info_xhj.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
@ -1479,6 +1562,7 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.xhjcn.lock.dev;
|
||||
PRODUCT_NAME = Runner;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = Adhoc_com.xhjcn.lock.dev.mobileprovision;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug-pre-xhj"
|
||||
buildConfiguration = "Debug-sky"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug-pre-xhj"
|
||||
buildConfiguration = "Debug-xhj"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
|
||||
@ -1,8 +1,18 @@
|
||||
/*
|
||||
InfoPlist.strings
|
||||
InfoPlist_xhj.strings
|
||||
Runner
|
||||
|
||||
Created by mac on 2024/11/21.
|
||||
Created by Mac on 2024/12/25.
|
||||
|
||||
*/
|
||||
"AppName"="Star Lock";
|
||||
CFBundleName="StarLock";
|
||||
CFBundleDisplayName="StarLock";
|
||||
NSBluetoothAlwaysUsageDescription="The app uses bluetooth to find, connect and transfer data between different devices";
|
||||
NSBluetoothPeripheralUsageDescription="The app uses bluetooth to find, connect and transfer data between different devices";
|
||||
NSCameraUsageDescription="The application requests the camera to take photos for avatar upload and face authentication";
|
||||
NSContactsUsageDescription="Access the address book to send electronic keys to contacts in the address book";
|
||||
NSLocationAlwaysAndWhenInUseUsageDescription="updated location information when applying in the front and backend";
|
||||
NSLocationAlwaysUsageDescription="updated location information when the app is in the background";
|
||||
NSLocationWhenInUseUsageDescription="updated location information when the app is in the foreground";
|
||||
NSMicrophoneUsageDescription="request microphone for calls";
|
||||
NSPhotoLibraryUsageDescription="request photo album for avatar upload";
|
||||
|
||||
18
ios/Runner/en.lproj/InfoPlist_sky.strings
Normal file
18
ios/Runner/en.lproj/InfoPlist_sky.strings
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
InfoPlist_sky.strings
|
||||
Runner
|
||||
|
||||
Created by Mac on 2024/12/25.
|
||||
|
||||
*/
|
||||
CFBundleName="TTLock Pro";
|
||||
CFBundleDisplayName="TTLock Pro";
|
||||
NSBluetoothAlwaysUsageDescription="The app uses bluetooth to find, connect and transfer data between different devices";
|
||||
NSBluetoothPeripheralUsageDescription="The app uses bluetooth to find, connect and transfer data between different devices";
|
||||
NSCameraUsageDescription="The application requests the camera to take photos for avatar upload and face authentication";
|
||||
NSContactsUsageDescription="Access the address book to send electronic keys to contacts in the address book";
|
||||
NSLocationAlwaysAndWhenInUseUsageDescription="updated location information when applying in the front and backend";
|
||||
NSLocationAlwaysUsageDescription="updated location information when the app is in the background";
|
||||
NSLocationWhenInUseUsageDescription="updated location information when the app is in the foreground";
|
||||
NSMicrophoneUsageDescription="request microphone for calls";
|
||||
NSPhotoLibraryUsageDescription="request photo album for avatar upload";
|
||||
18
ios/Runner/en.lproj/InfoPlist_xhj.strings
Normal file
18
ios/Runner/en.lproj/InfoPlist_xhj.strings
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
InfoPlist_xhj.strings
|
||||
Runner
|
||||
|
||||
Created by Mac on 2024/12/25.
|
||||
|
||||
*/
|
||||
CFBundleName="StarLock Pro";
|
||||
CFBundleDisplayName="StarLock Pro";
|
||||
NSBluetoothAlwaysUsageDescription="The app uses bluetooth to find, connect and transfer data between different devices";
|
||||
NSBluetoothPeripheralUsageDescription="The app uses bluetooth to find, connect and transfer data between different devices";
|
||||
NSCameraUsageDescription="The application requests the camera to take photos for avatar upload and face authentication";
|
||||
NSContactsUsageDescription="Access the address book to send electronic keys to contacts in the address book";
|
||||
NSLocationAlwaysAndWhenInUseUsageDescription="updated location information when applying in the front and backend";
|
||||
NSLocationAlwaysUsageDescription="updated location information when the app is in the background";
|
||||
NSLocationWhenInUseUsageDescription="updated location information when the app is in the foreground";
|
||||
NSMicrophoneUsageDescription="request microphone for calls";
|
||||
NSPhotoLibraryUsageDescription="request photo album for avatar upload";
|
||||
@ -7,7 +7,7 @@
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>$(BUNDLE_DISPLAY_NAME)</string>
|
||||
<string>$(BUNDLE_NAME)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
|
||||
23
ios/Runner/info_sky.xcstrings
Normal file
23
ios/Runner/info_sky.xcstrings
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"sourceLanguage" : "zh-Hans",
|
||||
"strings" : {
|
||||
"CFBundleDisplayName" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "TTLock Pro"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "锁通通"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"version" : "1.0"
|
||||
}
|
||||
@ -7,7 +7,7 @@
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>$(BUNDLE_DISPLAY_NAME)</string>
|
||||
<string>$(BUNDLE_NAME)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
|
||||
@ -1,8 +1,18 @@
|
||||
/*
|
||||
InfoPlist.strings
|
||||
InfoPlist_xhj.strings
|
||||
Runner
|
||||
|
||||
Created by mac on 2024/11/21.
|
||||
Created by Mac on 2024/12/25.
|
||||
|
||||
*/
|
||||
"AppName"="星锁";
|
||||
CFBundleName="星锁";
|
||||
CFBundleDisplayName="星锁";
|
||||
NSBluetoothAlwaysUsageDescription="该应用程序使用蓝牙在不同设备之间查找、连接和传输数据";
|
||||
NSBluetoothPeripheralUsageDescription="该应用程序使用蓝牙在不同设备之间查找、连接和传输数据";
|
||||
NSCameraUsageDescription="应用请求相机,以便于拍摄照片,用于头像上传及人脸认证";
|
||||
NSContactsUsageDescription="应用访问通讯录,用于给通讯录中的联系人发送电子钥匙";
|
||||
NSLocationAlwaysAndWhenInUseUsageDescription="应用在前台和后台的时候可以搜到更新的位置信息";
|
||||
NSLocationAlwaysUsageDescription="应用在后台的时候可以搜到更新的位置信息";
|
||||
NSLocationWhenInUseUsageDescription="应用在前台的时候可以搜到更新的位置信息";
|
||||
NSMicrophoneUsageDescription="应用请求麦克风用来通话";
|
||||
NSPhotoLibraryUsageDescription="应用请求相册用于头像上传";
|
||||
|
||||
18
ios/Runner/zh-Hans.lproj/InfoPlist_sky.strings
Normal file
18
ios/Runner/zh-Hans.lproj/InfoPlist_sky.strings
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
InfoPlist_sky.strings
|
||||
Runner
|
||||
|
||||
Created by Mac on 2024/12/25.
|
||||
|
||||
*/
|
||||
CFBundleName="锁通通";
|
||||
CFBundleDisplayName="锁通通";
|
||||
NSBluetoothAlwaysUsageDescription="该应用程序使用蓝牙在不同设备之间查找、连接和传输数据";
|
||||
NSBluetoothPeripheralUsageDescription="该应用程序使用蓝牙在不同设备之间查找、连接和传输数据";
|
||||
NSCameraUsageDescription="应用请求相机,以便于拍摄照片,用于头像上传及人脸认证";
|
||||
NSContactsUsageDescription="应用访问通讯录,用于给通讯录中的联系人发送电子钥匙";
|
||||
NSLocationAlwaysAndWhenInUseUsageDescription="应用在前台和后台的时候可以搜到更新的位置信息";
|
||||
NSLocationAlwaysUsageDescription="应用在后台的时候可以搜到更新的位置信息";
|
||||
NSLocationWhenInUseUsageDescription="应用在前台的时候可以搜到更新的位置信息";
|
||||
NSMicrophoneUsageDescription="应用请求麦克风用来通话";
|
||||
NSPhotoLibraryUsageDescription="应用请求相册用于头像上传";
|
||||
18
ios/Runner/zh-Hans.lproj/InfoPlist_xhj.strings
Normal file
18
ios/Runner/zh-Hans.lproj/InfoPlist_xhj.strings
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
InfoPlist_xhj.strings
|
||||
Runner
|
||||
|
||||
Created by Mac on 2024/12/25.
|
||||
|
||||
*/
|
||||
CFBundleName="星星锁";
|
||||
CFBundleDisplayName="星星锁";
|
||||
NSBluetoothAlwaysUsageDescription="该应用程序使用蓝牙在不同设备之间查找、连接和传输数据";
|
||||
NSBluetoothPeripheralUsageDescription="该应用程序使用蓝牙在不同设备之间查找、连接和传输数据";
|
||||
NSCameraUsageDescription="应用请求相机,以便于拍摄照片,用于头像上传及人脸认证";
|
||||
NSContactsUsageDescription="应用访问通讯录,用于给通讯录中的联系人发送电子钥匙";
|
||||
NSLocationAlwaysAndWhenInUseUsageDescription="应用在前台和后台的时候可以搜到更新的位置信息";
|
||||
NSLocationAlwaysUsageDescription="应用在后台的时候可以搜到更新的位置信息";
|
||||
NSLocationWhenInUseUsageDescription="应用在前台的时候可以搜到更新的位置信息";
|
||||
NSMicrophoneUsageDescription="应用请求麦克风用来通话";
|
||||
NSPhotoLibraryUsageDescription="应用请求相册用于头像上传";
|
||||
@ -1118,5 +1118,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
"分简称": "M",
|
||||
"跟随系统": "اتبع النظام"
|
||||
}
|
||||
@ -1118,5 +1118,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
"分简称": "M",
|
||||
"跟随系统": "Следете система"
|
||||
}
|
||||
@ -1118,5 +1118,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
"分简称": "M",
|
||||
"跟随系统": "এক্ফক্লোসিস্টেম"
|
||||
}
|
||||
@ -1118,5 +1118,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
"分简称": "M",
|
||||
"跟随系统": "Sledovat systém"
|
||||
}
|
||||
@ -1118,5 +1118,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
"分简称": "M",
|
||||
"跟随系统": "Følg systemet"
|
||||
}
|
||||
@ -1118,5 +1118,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
"分简称": "M",
|
||||
"跟随系统": "System folgen"
|
||||
}
|
||||
@ -1118,5 +1118,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
"分简称": "M",
|
||||
"跟随系统": "Ακολουθήστε το σύστημα"
|
||||
}
|
||||
@ -1011,6 +1011,7 @@
|
||||
"请在锁设置中开启远程开锁": "Please enable remote unlocking in the lock settings",
|
||||
"接听": "Answer",
|
||||
"截图已保存到相册": "Screenshot saved to album",
|
||||
"录屏已保存到相册": "Screen recording file saved to album",
|
||||
"添加遥控": "Add remote control",
|
||||
"已连接到锁,请按遥控": "Connected to the lock, please press the remote control",
|
||||
"遥控号": "Remote control number",
|
||||
@ -1121,5 +1122,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
"分简称": "M",
|
||||
"跟随系统": "Follow system"
|
||||
}
|
||||
|
||||
@ -1118,5 +1118,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
"分简称": "M",
|
||||
"跟随系统": "Seguir sistema"
|
||||
}
|
||||
@ -1118,5 +1118,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
"分简称": "M",
|
||||
"跟随系统": "Süsteemi jälgimine"
|
||||
}
|
||||
@ -1118,5 +1118,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
"分简称": "M",
|
||||
"跟随系统": "Seuraa järjestelmää"
|
||||
}
|
||||
@ -1118,5 +1118,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
"分简称": "M",
|
||||
"跟随系统": "Suivre le système"
|
||||
}
|
||||
@ -1118,5 +1118,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
"分简称": "M",
|
||||
"跟随系统": "מערכת מעקב"
|
||||
}
|
||||
@ -1046,39 +1046,39 @@
|
||||
"英文": "英语",
|
||||
"简体中文": "简体中文",
|
||||
"繁体中文": "繁體中文",
|
||||
"法语": "法语",
|
||||
"法语": "Français",
|
||||
"俄语": "Русский",
|
||||
"德语": "多伊奇",
|
||||
"德语": "Deutsch",
|
||||
"日语": "日本語",
|
||||
"韩语": "嘻嘻哈哈",
|
||||
"意大利语": "意大利语",
|
||||
"韩语": "한국어",
|
||||
"意大利语": "Italiano",
|
||||
"乌克兰语": "Українська",
|
||||
"葡萄牙语": "葡萄牙商业银行",
|
||||
"西班牙语": "西班牙语",
|
||||
"葡萄牙语": "Português",
|
||||
"西班牙语": "Español",
|
||||
"阿拉伯语": "العربية",
|
||||
"越南语": "Tiếng Việt",
|
||||
"马来语": "马来语",
|
||||
"荷兰语": "荷兰语",
|
||||
"罗马尼亚语": "罗马ă",
|
||||
"马来语": "Bahasa Melayu",
|
||||
"荷兰语": "Nederlands",
|
||||
"罗马尼亚语": "Română",
|
||||
"立陶宛语": "Lietuvių",
|
||||
"瑞典语": "瑞典语",
|
||||
"瑞典语": "Svenska",
|
||||
"爱沙尼亚语": "Eesti",
|
||||
"波兰语": "波兰语",
|
||||
"斯洛伐克语": "懒散的人č艾娜",
|
||||
"捷克语": "Češ蒂娜",
|
||||
"波兰语": "Polski",
|
||||
"斯洛伐克语": "Slovenčina",
|
||||
"捷克语": "Čeština",
|
||||
"希腊语": "Ελληνικά",
|
||||
"希伯来语": "עברית",
|
||||
"塞尔维亚语": "Српски",
|
||||
"土耳其语": "Turkce",
|
||||
"匈牙利语": "马札尔人的",
|
||||
"匈牙利语": "Magyar",
|
||||
"保加利亚语": "Български",
|
||||
"哈萨克斯坦语": "Қазақ",
|
||||
"孟加拉语": "বাংলা",
|
||||
"克罗地亚语": "Hrvatski",
|
||||
"泰语": "ไทย",
|
||||
"印度尼西亚语": "印度尼西亚语",
|
||||
"芬兰语": "芬兰语",
|
||||
"丹麦语": "丹麦语",
|
||||
"印度尼西亚语": "Bahasa Indonesia",
|
||||
"芬兰语": "Suomi",
|
||||
"丹麦语": "Dansk",
|
||||
"重置后,该锁的掌静脉都将被删除哦,确认要重置吗?": "重置后,锁上的掌骨静脉会被删除。你确定要重置吗?",
|
||||
"在线": "在线",
|
||||
"离线": "离线",
|
||||
@ -1118,5 +1118,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
"分简称": "M",
|
||||
"跟随系统": "跟踪系统"
|
||||
}
|
||||
@ -1118,5 +1118,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
"分简称": "M",
|
||||
"跟随系统": "Prati sistem:"
|
||||
}
|
||||
@ -1118,5 +1118,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
"分简称": "M",
|
||||
"跟随系统": "Follow system"
|
||||
}
|
||||
@ -1118,5 +1118,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
"分简称": "M",
|
||||
"跟随系统": "Sistem mengikuti"
|
||||
}
|
||||
@ -1118,5 +1118,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
"分简称": "M",
|
||||
"跟随系统": "Seguire il sistema"
|
||||
}
|
||||
@ -1118,5 +1118,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
"分简称": "M",
|
||||
"跟随系统": "システムに従う"
|
||||
}
|
||||
@ -1014,6 +1014,7 @@
|
||||
"请在锁设置中开启远程开锁": "请在锁设置中开启远程开锁",
|
||||
"接听": "接听",
|
||||
"截图已保存到相册": "截图已保存到相册",
|
||||
"录屏已保存到相册": "录屏已保存到相册",
|
||||
"添加遥控": "添加遥控",
|
||||
"已连接到锁,请按遥控": "已连接到锁,请按遥控",
|
||||
"遥控号": "遥控号",
|
||||
@ -1121,5 +1122,6 @@
|
||||
"月简称": "月简称",
|
||||
"日简称": "日简称",
|
||||
"时简称": "时简称",
|
||||
"分简称": "分简称"
|
||||
"分简称": "分简称",
|
||||
"跟随系统": "跟随系统"
|
||||
}
|
||||
|
||||
@ -1118,5 +1118,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
"分简称": "M",
|
||||
"跟随系统": "Жүйені қолдану"
|
||||
}
|
||||
@ -1118,5 +1118,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
"分简称": "M",
|
||||
"跟随系统": "시스템을 따르십시오"
|
||||
}
|
||||
@ -1118,5 +1118,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
"分简称": "M",
|
||||
"跟随系统": "Sekti sistema"
|
||||
}
|
||||
@ -1118,5 +1118,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
"分简称": "M",
|
||||
"跟随系统": "Ikut system"
|
||||
}
|
||||
@ -1118,5 +1118,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
"分简称": "M",
|
||||
"跟随系统": "Systeem volgen"
|
||||
}
|
||||
@ -1118,5 +1118,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
"分简称": "M",
|
||||
"跟随系统": "Śledź system"
|
||||
}
|
||||
@ -1118,5 +1118,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
"分简称": "M",
|
||||
"跟随系统": "Siga o sistema"
|
||||
}
|
||||
@ -1118,5 +1118,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
"分简称": "M",
|
||||
"跟随系统": "Urmează sistemul:"
|
||||
}
|
||||
@ -1118,5 +1118,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
"分简称": "M",
|
||||
"跟随系统": "Следуйте системе"
|
||||
}
|
||||
@ -1118,5 +1118,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
"分简称": "M",
|
||||
"跟随系统": "Sledovať systém"
|
||||
}
|
||||
@ -1118,5 +1118,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
"分简称": "M",
|
||||
"跟随系统": "Пратите систем"
|
||||
}
|
||||
@ -1118,5 +1118,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
"分简称": "M",
|
||||
"跟随系统": "Följ system"
|
||||
}
|
||||
@ -1118,5 +1118,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
"分简称": "M",
|
||||
"跟随系统": "ระบบติดตามผล"
|
||||
}
|
||||
@ -1118,5 +1118,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
"分简称": "M",
|
||||
"跟随系统": "Sistemi takip et"
|
||||
}
|
||||
@ -1118,6 +1118,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
|
||||
"分简称": "M",
|
||||
"跟随系统": "跟蹤系統"
|
||||
}
|
||||
@ -1118,5 +1118,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
"分简称": "M",
|
||||
"跟随系统": "Система стеження за"
|
||||
}
|
||||
@ -1118,5 +1118,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
"分简称": "M",
|
||||
"跟随系统": "Hệ thống theo dõi"
|
||||
}
|
||||
@ -1013,6 +1013,7 @@
|
||||
"请在锁设置中开启远程开锁": "请在锁设置中开启远程开锁",
|
||||
"接听": "接听",
|
||||
"截图已保存到相册": "截图已保存到相册",
|
||||
"录屏已保存到相册": "录屏已保存到相册",
|
||||
"添加遥控": "添加遥控",
|
||||
"已连接到锁,请按遥控": "已连接到锁,请按遥控",
|
||||
"遥控号": "遥控号",
|
||||
@ -1122,5 +1123,6 @@
|
||||
"月简称": "M",
|
||||
"日简称": "D",
|
||||
"时简称": "H",
|
||||
"分简称": "M"
|
||||
"分简称": "M",
|
||||
"跟随系统": "跟随系统"
|
||||
}
|
||||
|
||||
45
lib/app.dart
45
lib/app.dart
@ -33,9 +33,14 @@ class MyApp extends StatefulWidget {
|
||||
class _MyAppState extends State<MyApp> with WidgetsBindingObserver, BaseWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ScreenUtilInit(
|
||||
designSize: const Size(585, 1265),
|
||||
builder: (BuildContext w, Widget? a) => _initMaterialApp());
|
||||
return FutureBuilder(
|
||||
future: Get.updateLocale(CurrentLocaleTool.getCurrentLocale()),
|
||||
builder: (BuildContext context, AsyncSnapshot snapshot) {
|
||||
return ScreenUtilInit(
|
||||
designSize: const Size(585, 1265),
|
||||
builder: (BuildContext w, Widget? a) => _initMaterialApp());
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
GetMaterialApp _initMaterialApp() {
|
||||
@ -60,23 +65,23 @@ class _MyAppState extends State<MyApp> with WidgetsBindingObserver, BaseWidget {
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
],
|
||||
// localeResolutionCallback用于在启动时动态确定应该使用哪种语言和地区。
|
||||
localeResolutionCallback:
|
||||
(Locale? locale, Iterable<Locale> supportedLocales) {
|
||||
AppLog.log(
|
||||
'System device locale: ${Get.deviceLocale} locale:$locale');
|
||||
// if (widget.isLogin) {
|
||||
// 登录之后调用存储的语言
|
||||
locale = CurrentLocaleTool.getCurrentLocale();
|
||||
// } else {
|
||||
// // 没登录之前调用系统的语言
|
||||
// locale = Get.deviceLocale;
|
||||
// }
|
||||
locale = CurrentLocaleTool.convertLocale(locale);
|
||||
AppLog.log('localeResolutionCallback locale: $locale');
|
||||
AppManager()
|
||||
.setLanCode(code: '${locale.languageCode}_${locale.countryCode}');
|
||||
return Locale(locale.languageCode, locale.countryCode);
|
||||
},
|
||||
// localeResolutionCallback:
|
||||
// (Locale? locale, Iterable<Locale> supportedLocales) {
|
||||
// AppLog.log(
|
||||
// 'System device locale: ${Get.deviceLocale} locale:$locale');
|
||||
// // if (widget.isLogin) {
|
||||
// // 登录之后调用存储的语言
|
||||
// locale = CurrentLocaleTool.getCurrentLocale();
|
||||
// // } else {
|
||||
// // // 没登录之前调用系统的语言
|
||||
// // locale = Get.deviceLocale;
|
||||
// // }
|
||||
// locale = CurrentLocaleTool.convertLocale(locale);
|
||||
// AppLog.log('localeResolutionCallback locale: $locale');
|
||||
// AppManager()
|
||||
// .setLanCode(code: '${locale.languageCode}_${locale.countryCode}');
|
||||
// return Locale(locale.languageCode, locale.countryCode);
|
||||
// },
|
||||
// 用来指定应用当前使用的语言和地区。它定义了应用在启动时加载的默认语言环境。
|
||||
locale: CurrentLocaleTool.getCurrentLocale(),
|
||||
// locale: Get.deviceLocale,
|
||||
|
||||
@ -36,7 +36,6 @@ import 'package:star_lock/main/lockDetail/messageWarn/msgNotification/msgNotific
|
||||
import 'package:star_lock/main/lockDetail/messageWarn/msgNotification/nDaysUnopened/nDaysUnopened_page.dart';
|
||||
import 'package:star_lock/main/lockDetail/messageWarn/msgNotification/openDoorNotify/openDoorNotify_page.dart';
|
||||
import 'package:star_lock/main/lockDetail/messageWarn/notificationMode/notificationMode_page.dart';
|
||||
import 'package:star_lock/main/lockDetail/monitoring/star_chart_h264/star_chart_page.dart';
|
||||
import 'package:star_lock/main/lockDetail/palm/addPalm/addPalm_page.dart';
|
||||
import 'package:star_lock/main/lockDetail/palm/palmList/palmList_page.dart';
|
||||
import 'package:star_lock/main/lockDetail/passwordKey/passwordKeyDetailChangeDate/passwordKeyDetailChangeDate_page.dart';
|
||||
@ -61,6 +60,7 @@ import 'package:star_lock/mine/mineSet/transferSmartLock/transferSmartLockList/t
|
||||
import 'package:star_lock/mine/valueAddedServices/advancedFeaturesWeb/advancedFeaturesWeb_page.dart';
|
||||
import 'package:star_lock/mine/valueAddedServices/advancedFunctionRecord/advancedFunctionRecord_page.dart';
|
||||
import 'package:star_lock/mine/valueAddedServices/valueAddedServicesRecord/value_added_services_record_page.dart';
|
||||
import 'package:star_lock/talk/startChart/views/talkView/talk_view_page.dart';
|
||||
|
||||
import 'common/safetyVerification/safetyVerification_page.dart';
|
||||
import 'login/forgetPassword/starLock_forgetPassword_page.dart';
|
||||
@ -514,6 +514,7 @@ abstract class Routers {
|
||||
static const String googleHomePage = '/googleHomePage'; //GoogleHome
|
||||
static const String doubleLockLinkPage = '/doubleLockLinkPage'; //双锁联动
|
||||
static const String starChartPage = '/starChartPage'; //星图
|
||||
static const String starChartTalkView = '/starChartTalkView'; //星图对讲页面
|
||||
}
|
||||
|
||||
abstract class AppRouters {
|
||||
@ -747,7 +748,8 @@ abstract class AppRouters {
|
||||
GetPage<dynamic>(
|
||||
name: Routers.lockTimePage,
|
||||
page: () => const LockTimePage(),
|
||||
), // 诊断
|
||||
),
|
||||
// 诊断
|
||||
GetPage<dynamic>(
|
||||
name: Routers.diagnosePage,
|
||||
page: () => const DiagnosePage(),
|
||||
@ -1192,6 +1194,6 @@ abstract class AppRouters {
|
||||
name: Routers.doubleLockLinkPage,
|
||||
page: () => const DoubleLockLinkPage()),
|
||||
GetPage<dynamic>(
|
||||
name: Routers.starChartPage, page: () => const StarChartPage()),
|
||||
name: Routers.starChartTalkView, page: () => const TalkViewPage()),
|
||||
];
|
||||
}
|
||||
|
||||
@ -213,9 +213,7 @@ class BlueManage {
|
||||
message: '指定设备名称的扫描蓝牙设备 监听扫描结果失败',
|
||||
detail: '打印失败问题 e:${e.toString()}',
|
||||
upload: false);
|
||||
AppLog.log(
|
||||
'扫描失败:$e',
|
||||
);
|
||||
AppLog.log('扫描失败:$e');
|
||||
});
|
||||
FlutterBluePlus.cancelWhenScanComplete(subscription);
|
||||
await completer.future;
|
||||
|
||||
@ -21,4 +21,12 @@ class EventBusManager {
|
||||
eventBusFir(dynamic event) {
|
||||
eventBus?.fire(event);
|
||||
}
|
||||
|
||||
// 发送事件
|
||||
void fireEvent(dynamic event) {
|
||||
eventBus?.fire(event);
|
||||
}
|
||||
|
||||
// 获取 EventBus 实例
|
||||
EventBus? get bus => eventBus;
|
||||
}
|
||||
|
||||
@ -1,210 +0,0 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_voice_processor/flutter_voice_processor.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:star_lock/app_settings/app_settings.dart';
|
||||
import 'package:star_lock/blue/io_tool/manager_event_bus.dart';
|
||||
import 'package:star_lock/main/lockDetail/monitoring/star_chart_h264/star_chart_state.dart';
|
||||
import 'package:star_lock/talk/startChart/events/talk_status_change_event.dart';
|
||||
import 'package:star_lock/talk/startChart/start_chart_manage.dart';
|
||||
import 'package:star_lock/talk/startChart/start_chart_talk_status.dart';
|
||||
import 'package:star_lock/tools/baseGetXController.dart';
|
||||
import 'package:star_lock/tools/eventBusEventManage.dart';
|
||||
|
||||
class StarChartLogic extends BaseGetXController {
|
||||
final StarChartState state = StarChartState();
|
||||
|
||||
/// 收到Talk发送的状态
|
||||
StreamSubscription? _getTalkStatusRefreshUIEvent;
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
_getTalkStatusRefreshUIAction();
|
||||
}
|
||||
|
||||
void _getTalkStatusRefreshUIAction() {
|
||||
_getTalkStatusRefreshUIEvent = EventBusManager()
|
||||
.eventBus!
|
||||
.on<TalkStatusChangeEvent>()
|
||||
.listen((TalkStatusChangeEvent event) async {
|
||||
state.talkStatus.value = event.newStatus.index;
|
||||
state.oneMinuteTime.value = 0;
|
||||
if (state.talkStatus.value == TalkStatus.rejected.index ||
|
||||
state.talkStatus.value == TalkStatus.notTalkData.index ||
|
||||
state.talkStatus.value == TalkStatus.notTalkPing.index ||
|
||||
state.talkStatus.value == TalkStatus.end.index) {
|
||||
_cancelTimers();
|
||||
// 状态错误,返回页面
|
||||
Get.back();
|
||||
return;
|
||||
}
|
||||
|
||||
if (state.talkStatus.value == TalkStatus.duringCall.index) {
|
||||
_startCallTimer();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void _startCallTimer() {
|
||||
state.oneMinuteTimeTimer.cancel();
|
||||
state.oneMinuteTimeTimer =
|
||||
Timer.periodic(const Duration(seconds: 1), (Timer t) {
|
||||
state.oneMinuteTime.value++;
|
||||
if (state.oneMinuteTime.value >= 60) {
|
||||
t.cancel();
|
||||
initiateHangUpCommand();
|
||||
AppLog.log('通话时间超过60秒,自动挂断');
|
||||
state.oneMinuteTime.value = 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void _cancelTimers() {
|
||||
state.oneMinuteTimeTimer.cancel();
|
||||
}
|
||||
|
||||
// 发起接听命令
|
||||
void initiateAnswerCommand() {
|
||||
StartChartManage().sendTalkAcceptMessage();
|
||||
}
|
||||
|
||||
// 发起挂断命令
|
||||
void initiateHangUpCommand() {
|
||||
_cancelTimers();
|
||||
if (state.talkStatus.value == TalkStatus.duringCall.index) {
|
||||
// 如果是通话中就挂断
|
||||
StartChartManage().sendTalkHangupMessage();
|
||||
} else {
|
||||
// 拒绝
|
||||
StartChartManage().sendTalkRejectMessage();
|
||||
}
|
||||
Get.back();
|
||||
}
|
||||
|
||||
Future<void> _onFrame(List<int> frame) async {
|
||||
state.allFrames.add(frame);
|
||||
final List<int> concatenatedFrames = concatenateFrames(state.allFrames);
|
||||
AppLog.log('pcm数据:$concatenatedFrames');
|
||||
|
||||
final List<int> pcmBytes = listLinearToULaw(frame);
|
||||
//发起发送录音命令
|
||||
// StartChartManage().sendTalkAudioMessage(pcmBytes);
|
||||
}
|
||||
|
||||
List<int> listLinearToULaw(List<int> pcmList) {
|
||||
return pcmList.map(linearToULaw).toList();
|
||||
}
|
||||
|
||||
List<int> concatenateFrames(List<List<int>> frames) {
|
||||
return frames.expand((frame) => frame).toList();
|
||||
}
|
||||
|
||||
Future<void> startProcessing() async {
|
||||
// state.isButtonDisabled.value = true;
|
||||
//
|
||||
// state.voiceProcessor?.addFrameListener(_onFrame);
|
||||
// state.voiceProcessor?.addErrorListener(_onError);
|
||||
// try {
|
||||
// if (await state.voiceProcessor?.hasRecordAudioPermission() ?? false) {
|
||||
// await state.voiceProcessor?.start(state.frameLength, state.sampleRate);
|
||||
// state.isProcessing.value =
|
||||
// await state.voiceProcessor?.isRecording() ?? false;
|
||||
// } else {
|
||||
// state.errorMessage.value = 'Recording permission not granted';
|
||||
// }
|
||||
// } on PlatformException catch (ex) {
|
||||
// state.errorMessage.value = 'Failed to start recorder: $ex';
|
||||
// } finally {
|
||||
// state.isButtonDisabled.value = false;
|
||||
// }
|
||||
}
|
||||
|
||||
void _onError(VoiceProcessorException error) {
|
||||
state.errorMessage.value = error.message!;
|
||||
}
|
||||
|
||||
Future<void> stopProcessing() async {
|
||||
// 检查 voiceProcessor 是否已经初始化
|
||||
// if (state.voiceProcessor == null) {
|
||||
// state.errorMessage.value = 'Voice processor is not initialized.';
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// state.isButtonDisabled.value = true;
|
||||
// try {
|
||||
// await state.voiceProcessor?.stop();
|
||||
// state.voiceProcessor?.removeFrameListener(_onFrame);
|
||||
// state.udpSendDataFrameNumber = 0;
|
||||
// } on PlatformException catch (ex) {
|
||||
// state.errorMessage.value = 'Failed to stop recorder: $ex';
|
||||
// } finally {
|
||||
// state.isProcessing.value =
|
||||
// await state.voiceProcessor?.isRecording() ?? false;
|
||||
// state.isButtonDisabled.value = false;
|
||||
// }
|
||||
}
|
||||
|
||||
int linearToULaw(int pcmVal) {
|
||||
int mask;
|
||||
int seg;
|
||||
int uval;
|
||||
|
||||
if (pcmVal < 0) {
|
||||
pcmVal = 0x84 - pcmVal;
|
||||
mask = 0x7F;
|
||||
} else {
|
||||
pcmVal += 0x84;
|
||||
mask = 0xFF;
|
||||
}
|
||||
|
||||
seg = search(pcmVal);
|
||||
if (seg >= 8) {
|
||||
return 0x7F ^ mask;
|
||||
} else {
|
||||
uval = seg << 4;
|
||||
uval |= (pcmVal >> (seg + 3)) & 0xF;
|
||||
return uval ^ mask;
|
||||
}
|
||||
}
|
||||
|
||||
int search(int val) {
|
||||
final List<int> table = [
|
||||
0xFF,
|
||||
0x1FF,
|
||||
0x3FF,
|
||||
0x7FF,
|
||||
0xFFF,
|
||||
0x1FFF,
|
||||
0x3FFF,
|
||||
0x7FFF
|
||||
];
|
||||
for (int i = 0; i < table.length; i++) {
|
||||
if (val <= table[i]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return table.length;
|
||||
}
|
||||
|
||||
Future<bool> getPermissionStatus() async {
|
||||
const Permission permission = Permission.microphone;
|
||||
final PermissionStatus status = await permission.status;
|
||||
if (status.isGranted) {
|
||||
return true;
|
||||
} else if (status.isDenied || status.isRestricted) {
|
||||
await requestPermission(permission);
|
||||
} else if (status.isPermanentlyDenied) {
|
||||
openAppSettings();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Future<void> requestPermission(Permission permission) async {
|
||||
final PermissionStatus status = await permission.request();
|
||||
if (status.isPermanentlyDenied) {
|
||||
openAppSettings();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,396 +0,0 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:ui' as ui;
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:image_gallery_saver/image_gallery_saver.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:star_lock/app_settings/app_colors.dart';
|
||||
import 'package:star_lock/app_settings/app_settings.dart';
|
||||
import 'package:star_lock/main/lockDetail/monitoring/star_chart_h264/star_chart_logic.dart';
|
||||
import 'package:star_lock/main/lockDetail/monitoring/star_chart_h264/star_chart_state.dart';
|
||||
import 'package:star_lock/talk/startChart/start_chart_talk_status.dart';
|
||||
import 'package:star_lock/talk/startChart/webView/h264_web_view.dart';
|
||||
import 'package:star_lock/talk/udp/udp_manage.dart';
|
||||
import 'package:star_lock/tools/eventBusEventManage.dart';
|
||||
import 'package:star_lock/tools/showTFView.dart';
|
||||
|
||||
class StarChartPage extends StatefulWidget {
|
||||
const StarChartPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StarChartPage> createState() => _StarChartPageState();
|
||||
}
|
||||
|
||||
class _StarChartPageState extends State<StarChartPage> {
|
||||
final StarChartLogic logic = Get.put(StarChartLogic());
|
||||
final StarChartState state = Get.find<StarChartLogic>().state;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
initAsync();
|
||||
_getTVDataRefreshUIAction();
|
||||
}
|
||||
|
||||
Future<void> initAsync() async {
|
||||
await requestMicrophonePermission();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return PopScope(
|
||||
canPop: false,
|
||||
child: RepaintBoundary(
|
||||
key: state.globalKey,
|
||||
child: Container(
|
||||
width: 1.sw,
|
||||
height: 1.sh,
|
||||
color: Colors.transparent,
|
||||
child: _buildTalkView(isMpeg4: true),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildTopButtons() {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
buildIconButton(
|
||||
icon: state.isOpenVoice.value
|
||||
? 'images/main/icon_lockDetail_monitoringCloseVoice.png'
|
||||
: 'images/main/icon_lockDetail_monitoringOpenVoice.png',
|
||||
onTap: () {
|
||||
state.isOpenVoice.value = !state.isOpenVoice.value;
|
||||
},
|
||||
),
|
||||
SizedBox(width: 60.w),
|
||||
buildIconButton(
|
||||
icon: 'images/main/icon_lockDetail_monitoringScreenshot.png',
|
||||
onTap: captureAndSavePng,
|
||||
),
|
||||
SizedBox(width: 60.w),
|
||||
buildIconButton(
|
||||
icon: 'images/main/icon_lockDetail_monitoringScreenRecording.png',
|
||||
onTap: () {
|
||||
// Get.toNamed(Routers.monitoringRealTimeScreenPage);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildBottomButtons() {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: <Widget>[
|
||||
buildAnswerButton(),
|
||||
buildIconButton(
|
||||
icon: 'images/main/icon_lockDetail_hangUp.png',
|
||||
label: '挂断'.tr,
|
||||
color: Colors.red,
|
||||
onTap: () async {
|
||||
logic.initiateHangUpCommand();
|
||||
},
|
||||
),
|
||||
buildIconButton(
|
||||
icon: 'images/main/icon_lockDetail_monitoringUnlock.png',
|
||||
label: '开锁'.tr,
|
||||
color: AppColors.mainColor,
|
||||
onTap: () {
|
||||
if (UDPManage().remoteUnlock == 1) {
|
||||
showDeletPasswordAlertDialog(context);
|
||||
} else {
|
||||
logic.showToast('请在锁设置中开启远程开锁'.tr);
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildAnswerButton() {
|
||||
return Obx(() {
|
||||
// final bool isDuringCall =
|
||||
// state.talkStatus.value == TalkStatus.duringCall.index;
|
||||
return buildIconButton(
|
||||
icon: state.talkStatus.value == TalkStatus.duringCall.index
|
||||
? 'images/main/icon_lockDetail_monitoringUnTalkback.png'
|
||||
: 'images/main/icon_lockDetail_monitoringAnswerCalls.png',
|
||||
label: state.talkStatus.value == TalkStatus.duringCall.index
|
||||
? '长按说话'.tr
|
||||
: '接听'.tr,
|
||||
onTap: () async {
|
||||
if (state.talkStatus.value == TalkStatus.waitingAnswer.index) {
|
||||
logic.initiateAnswerCommand();
|
||||
setState(() {});
|
||||
}
|
||||
},
|
||||
onLongPress: () {
|
||||
state.listAudioData.value = <int>[];
|
||||
logic.startProcessing();
|
||||
},
|
||||
onLongPressUp: () {
|
||||
logic.stopProcessing();
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Widget buildIconButton({
|
||||
required String icon,
|
||||
String? label,
|
||||
Color color = Colors.white,
|
||||
required Function() onTap,
|
||||
Function()? onLongPress,
|
||||
Function()? onLongPressUp,
|
||||
}) {
|
||||
final double wh = 80.w;
|
||||
return GestureDetector(
|
||||
onTap: onTap,
|
||||
onLongPress: onLongPress,
|
||||
onLongPressUp: onLongPressUp,
|
||||
child: SizedBox(
|
||||
height: 140.h,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Container(
|
||||
width: wh,
|
||||
height: wh,
|
||||
decoration: BoxDecoration(
|
||||
color: color,
|
||||
borderRadius: BorderRadius.circular((wh + 10.w * 2) / 2),
|
||||
),
|
||||
padding: EdgeInsets.all(20.w),
|
||||
child: Image.asset(icon, fit: BoxFit.fitWidth),
|
||||
),
|
||||
if (label != null) ...[
|
||||
SizedBox(height: 20.w),
|
||||
Expanded(
|
||||
child: Text(
|
||||
label,
|
||||
style: TextStyle(fontSize: 20.sp, color: Colors.white),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void showDeletPasswordAlertDialog(BuildContext context) {
|
||||
showDialog(
|
||||
barrierDismissible: false,
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return ShowTFView(
|
||||
title: '请输入6位数字开锁密码'.tr,
|
||||
tipTitle: '',
|
||||
controller: state.passwordTF,
|
||||
inputFormatters: <TextInputFormatter>[
|
||||
LengthLimitingTextInputFormatter(6), //限制长度
|
||||
FilteringTextInputFormatter.allow(RegExp('[0-9]')),
|
||||
],
|
||||
sureClick: () async {
|
||||
if (state.passwordTF.text.isEmpty) {
|
||||
logic.showToast('请输入开锁密码'.tr);
|
||||
return;
|
||||
}
|
||||
final List<int> numbers = <int>[];
|
||||
final List<int> lockIDData = utf8.encode(state.passwordTF.text);
|
||||
numbers.addAll(lockIDData);
|
||||
for (int i = 0; i < 6 - lockIDData.length; i++) {
|
||||
numbers.add(0);
|
||||
}
|
||||
//todo: 开门暂未实现
|
||||
// logic.udpOpenDoorAction(numbers);
|
||||
},
|
||||
cancelClick: () {
|
||||
Get.back();
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> requestMicrophonePermission() async {
|
||||
await logic.getPermissionStatus().then((bool value) async {
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> captureAndSavePng() async {
|
||||
try {
|
||||
if (state.globalKey.currentContext == null) {
|
||||
AppLog.log('截图失败: 未找到当前上下文');
|
||||
return;
|
||||
}
|
||||
final RenderRepaintBoundary boundary = state.globalKey.currentContext!
|
||||
.findRenderObject()! as RenderRepaintBoundary;
|
||||
final ui.Image image = await boundary.toImage();
|
||||
final ByteData? byteData =
|
||||
await image.toByteData(format: ui.ImageByteFormat.png);
|
||||
if (byteData == null) {
|
||||
AppLog.log('截图失败: 图像数据为空');
|
||||
return;
|
||||
}
|
||||
final Uint8List pngBytes = byteData.buffer.asUint8List();
|
||||
|
||||
final Directory directory = await getApplicationDocumentsDirectory();
|
||||
final String imagePath = '${directory.path}/screenshot.png';
|
||||
|
||||
final File imgFile = File(imagePath);
|
||||
await imgFile.writeAsBytes(pngBytes);
|
||||
|
||||
await ImageGallerySaver.saveFile(imagePath);
|
||||
|
||||
AppLog.log('截图保存路径: $imagePath');
|
||||
logic.showToast('截图已保存到相册'.tr);
|
||||
} catch (e) {
|
||||
AppLog.log('截图失败: $e');
|
||||
}
|
||||
}
|
||||
|
||||
void _getTVDataRefreshUIAction() {
|
||||
state.getTVDataRefreshUIEvent = eventBus
|
||||
.on<GetTVDataRefreshUI>()
|
||||
.listen((GetTVDataRefreshUI event) async {
|
||||
if (event.tvList.isNotEmpty && event.tvList.length > 100) {
|
||||
final Uint8List imageData = Uint8List.fromList(event.tvList);
|
||||
if (!listEquals(state.listPhotoData.value, imageData)) {
|
||||
state.listPhotoData.value = imageData;
|
||||
state.shouldUpdateUI.value = true;
|
||||
if (state.shouldUpdateUI.value) {
|
||||
setState(() {});
|
||||
state.shouldUpdateUI.value = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
logic.stopProcessing();
|
||||
state.getTVDataRefreshUIEvent!.cancel();
|
||||
}
|
||||
|
||||
Widget _buildTalkView({required bool isMpeg4}) {
|
||||
return isMpeg4 ? _buildMpeg4TalkView() : _buildH264TalkView();
|
||||
}
|
||||
|
||||
Widget _buildMpeg4TalkView() {
|
||||
return Stack(
|
||||
children: <Widget>[
|
||||
Image.memory(
|
||||
state.listPhotoData.value,
|
||||
gaplessPlayback: true,
|
||||
width: 1.sw,
|
||||
height: 1.sh,
|
||||
fit: BoxFit.cover,
|
||||
filterQuality: FilterQuality.high,
|
||||
errorBuilder:
|
||||
(BuildContext context, Object error, StackTrace? stackTrace) {
|
||||
return Container(color: Colors.transparent);
|
||||
},
|
||||
),
|
||||
Positioned(
|
||||
top: ScreenUtil().statusBarHeight + 30.h,
|
||||
width: 1.sw,
|
||||
child: Obx(() {
|
||||
final String sec =
|
||||
(state.oneMinuteTime.value % 60).toString().padLeft(2, '0');
|
||||
final String min =
|
||||
(state.oneMinuteTime.value ~/ 60).toString().padLeft(2, '0');
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Text('$min:$sec',
|
||||
style: TextStyle(fontSize: 26.sp, color: Colors.white)),
|
||||
],
|
||||
);
|
||||
}),
|
||||
),
|
||||
Positioned(
|
||||
bottom: 10.w,
|
||||
child: Container(
|
||||
width: 1.sw - 30.w * 2,
|
||||
margin: EdgeInsets.all(30.w),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xC83C3F41),
|
||||
borderRadius: BorderRadius.circular(20.h),
|
||||
),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
SizedBox(height: 20.h),
|
||||
buildTopButtons(),
|
||||
SizedBox(height: 20.h),
|
||||
buildBottomButtons(),
|
||||
SizedBox(height: 20.h),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildH264TalkView() {
|
||||
return Stack(
|
||||
children: <Widget>[
|
||||
H264WebView(),
|
||||
Positioned(
|
||||
top: ScreenUtil().statusBarHeight + 30.h,
|
||||
width: 1.sw,
|
||||
child: Obx(() {
|
||||
final String sec =
|
||||
(state.oneMinuteTime.value % 60).toString().padLeft(2, '0');
|
||||
final String min =
|
||||
(state.oneMinuteTime.value ~/ 60).toString().padLeft(2, '0');
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Text('$min:$sec',
|
||||
style: TextStyle(fontSize: 26.sp, color: Colors.white)),
|
||||
],
|
||||
);
|
||||
}),
|
||||
),
|
||||
Positioned(
|
||||
bottom: 10.w,
|
||||
child: Container(
|
||||
width: 1.sw - 30.w * 2,
|
||||
margin: EdgeInsets.all(30.w),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xC83C3F41),
|
||||
borderRadius: BorderRadius.circular(20.h),
|
||||
),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
SizedBox(height: 20.h),
|
||||
buildTopButtons(),
|
||||
SizedBox(height: 20.h),
|
||||
buildBottomButtons(),
|
||||
SizedBox(height: 20.h),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,57 +0,0 @@
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_voice_processor/flutter_voice_processor.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:network_info_plus/network_info_plus.dart';
|
||||
import 'package:star_lock/talk/startChart/start_chart_talk_status.dart';
|
||||
|
||||
import '../../../../tools/storage.dart';
|
||||
|
||||
class StarChartState {
|
||||
RxBool isOpenVoice = false.obs;
|
||||
int udpSendDataFrameNumber = 0; // 帧序号
|
||||
// var isSenderAudioData = false.obs;// 是否要发送音频数据
|
||||
StreamSubscription? getTVDataRefreshUIEvent; //收到视频流数据
|
||||
RxBool shouldUpdateUI = false.obs; //是否需要更新UI
|
||||
|
||||
Future<String?> userMobileIP = NetworkInfo().getWifiIP();
|
||||
Future<String?> userUid = Storage.getUid();
|
||||
|
||||
// RxInt udpStatus =
|
||||
// 0.obs; //0:初始状态 1:等待监视 2: 3:监视中 4:呼叫成功 5:主角通话中 6:被叫通话 8:被叫通话中 9:长按说话
|
||||
TextEditingController passwordTF = TextEditingController();
|
||||
|
||||
Rx<Uint8List> listPhotoData = Uint8List(0).obs; //得到的视频流字节数据
|
||||
RxList<int> listAudioData = <int>[].obs; //得到的音频流字节数据
|
||||
|
||||
//录音相关
|
||||
late VoiceProcessor? voiceProcessor;
|
||||
RxBool isProcessing = false.obs; //是否正在处理音频数据
|
||||
RxBool isButtonDisabled = false.obs; //是否禁用按钮
|
||||
final int frameLength = 320; //音视频帧长度为320
|
||||
final int sampleRate = 8000; //音频采样率为8000
|
||||
RxString errorMessage = ''.obs;
|
||||
List<List<int>> allFrames = <List<int>>[];
|
||||
|
||||
GlobalKey globalKey = GlobalKey();
|
||||
|
||||
late Timer oneMinuteTimeTimer =
|
||||
Timer(const Duration(seconds: 1), () {}); // 定时器超过60秒关闭当前界面
|
||||
RxInt oneMinuteTime = 0.obs; // 定时器秒数
|
||||
|
||||
// 定时器如果发送了接听的命令 而没收到回复就每秒重复发送10次
|
||||
late Timer answerTimer = Timer(const Duration(seconds: 1), () {}); //接听命令定时器
|
||||
RxInt answerSeconds = 0.obs;
|
||||
RxBool isClickAnswer = false.obs; //是否点击了接听按钮
|
||||
|
||||
late Timer hangUpTimer = Timer(const Duration(seconds: 1), () {}); //挂断命令定时器
|
||||
RxInt hangUpSeconds = 0.obs;
|
||||
RxBool isClickHangUp = false.obs; //是否点击了挂断按钮
|
||||
|
||||
late Timer openDoorTimer = Timer(const Duration(seconds: 1), () {}); //开门命令定时器
|
||||
RxInt openDoorSeconds = 0.obs;
|
||||
|
||||
RxInt talkStatus = 0.obs; //星图对讲状态
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@ -32,6 +32,7 @@ class LockMainXHJLogic extends BaseGetXController {
|
||||
final String languageCodeAndCountryCode = entity.data!.lang!;
|
||||
if (languageCodeAndCountryCode.isEmpty) {
|
||||
await StoreService.to.saveLanguageCode('');
|
||||
await Get.updateLocale(Get.deviceLocale!);
|
||||
} else if (languageCodeAndCountryCode.contains('-')) {
|
||||
final List<String> parts = languageCodeAndCountryCode.split('-');
|
||||
final Locale locale = Locale(parts[0], parts[1]);
|
||||
|
||||
@ -4,7 +4,7 @@ import 'flavors.dart';
|
||||
import 'main.dart' as runner;
|
||||
|
||||
Future<void> main() async {
|
||||
F.appFlavor = Flavor.local;
|
||||
F.appFlavor = Flavor.sky;
|
||||
// AppLog.log('local调用了main函数');
|
||||
await runner.main();
|
||||
}
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
class GatewayConnectionLockListEntity {
|
||||
|
||||
GatewayConnectionLockListEntity(
|
||||
{this.errorCode, this.description, this.errorMsg, this.data});
|
||||
|
||||
@ -27,7 +26,6 @@ class GatewayConnectionLockListEntity {
|
||||
}
|
||||
|
||||
class Data {
|
||||
|
||||
Data({this.list, this.total, this.pageNo, this.pageSize});
|
||||
|
||||
Data.fromJson(Map<String, dynamic> json) {
|
||||
@ -59,23 +57,23 @@ class Data {
|
||||
}
|
||||
|
||||
class GatewayConnectionLockItemEntity {
|
||||
|
||||
GatewayConnectionLockItemEntity({this.lockId, this.lockAlias, this.rssi});
|
||||
GatewayConnectionLockItemEntity(
|
||||
{this.lockId, this.lockAlias, this.gatewayRssi});
|
||||
|
||||
GatewayConnectionLockItemEntity.fromJson(Map<String, dynamic> json) {
|
||||
lockId = json['lockId'];
|
||||
lockAlias = json['lockAlias'];
|
||||
rssi = json['rssi'];
|
||||
gatewayRssi = json['gatewayRssi'];
|
||||
}
|
||||
int? lockId;
|
||||
String? lockAlias;
|
||||
int? rssi;
|
||||
int? gatewayRssi;
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['lockId'] = lockId;
|
||||
data['lockAlias'] = lockAlias;
|
||||
data['rssi'] = rssi;
|
||||
data['gatewayRssi'] = gatewayRssi;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,7 +56,7 @@ class _GatewayConnectionLockListPageState
|
||||
return _gatewayConnectionLockListItem(
|
||||
'images/mine/icon_mine_gatewaySignal_prompt.png',
|
||||
entity.lockAlias ?? '',
|
||||
'信号强'.tr, () {
|
||||
entity.gatewayRssi.toString(), () {
|
||||
// Navigator.pushNamed(context, Routers.gatewayDetailPage);
|
||||
});
|
||||
})
|
||||
|
||||
@ -15,22 +15,27 @@ class MineMultiLanguageLogic extends GetxController {
|
||||
|
||||
//更新个人信息
|
||||
Future<void> updateUserLangInfo(Locale l) async {
|
||||
// AppLog.log('lanTypeTitle: $lanTypeTitle');
|
||||
AppLog.log('selet: ${l.toString()}}');
|
||||
String lang = l.toString();
|
||||
if (state.currentLanguageType.value == LanguageType.system) {
|
||||
lang = '';
|
||||
}
|
||||
String currentLanguage = StoreService.to.getLanguageCode()!;
|
||||
await StoreService.to.saveLanguageCode(lang);
|
||||
final PasswordKeyListEntity entity =
|
||||
await ApiRepository.to.updateUserLangInfo(lang: lang);
|
||||
if (entity.errorCode!.codeIsSuccessful) {
|
||||
await changeLanguage(l);
|
||||
await Get.updateLocale(l);
|
||||
AppLog.log('saveLocale: ${l.toString()}}');
|
||||
eventBus.fire(ChangeLanguageBlockLastLanguageEvent());
|
||||
} else {
|
||||
await StoreService.to.saveLanguageCode(currentLanguage);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> changeLanguage(Locale l) async {
|
||||
await Get.updateLocale(l);
|
||||
await StoreService.to.saveLanguageCode(
|
||||
CurrentLocaleTool.convertLocale(Get.locale!).toString());
|
||||
}
|
||||
// Future<void> changeLanguage(Locale l) async {
|
||||
// await StoreService.to.saveLanguageCode(l.toString());
|
||||
// await Get.updateLocale(l);
|
||||
// AppLog.log('saveLocale: ${l.toString()}}');
|
||||
// }
|
||||
}
|
||||
|
||||
@ -36,7 +36,8 @@ class _MineMultiLanguagePageState extends State<MineMultiLanguagePage> {
|
||||
final String lanTypeTitle =
|
||||
ExtensionLanguageType.fromLocale(state.seletLocale)
|
||||
.lanTitle;
|
||||
Get.back(result: {'currentLanguage': lanTypeTitle});
|
||||
Get.back(
|
||||
result: {'currentLanguage': state.seletLocale.toString()});
|
||||
},
|
||||
child: Text(
|
||||
'保存'.tr,
|
||||
@ -59,7 +60,7 @@ class _MineMultiLanguagePageState extends State<MineMultiLanguagePage> {
|
||||
final List<Widget> l = <Widget>[];
|
||||
l.add(
|
||||
CommonItem(
|
||||
leftTitel: '跟随系统',
|
||||
leftTitel: '跟随系统'.tr,
|
||||
rightTitle: '',
|
||||
isHaveLine: true,
|
||||
isHaveDirection: false,
|
||||
|
||||
@ -15,7 +15,9 @@ class MineMultiLanguageState {
|
||||
}
|
||||
|
||||
Rx<LanguageType> currentLanguageType =
|
||||
ExtensionLanguageType.fromLocale(Get.locale!).obs;
|
||||
StoreService.to.getLanguageCode()!.isEmpty
|
||||
? LanguageType.system.obs
|
||||
: ExtensionLanguageType.fromLocale(Get.locale!).obs;
|
||||
|
||||
late Locale seletLocale;
|
||||
}
|
||||
|
||||
@ -2,17 +2,14 @@ import 'dart:io';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:get/get_state_manager/get_state_manager.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:star_lock/app_settings/app_settings.dart';
|
||||
import 'package:star_lock/flavors.dart';
|
||||
import 'package:star_lock/mine/mineSet/mineSet/mineSet_logic.dart';
|
||||
import 'package:star_lock/mine/mineSet/mineSet/mineSet_state.dart';
|
||||
import 'package:star_lock/tools/langue/langue_tool.dart';
|
||||
import 'package:star_lock/tools/wechat/customer_tool.dart';
|
||||
import '../../../appRouters.dart';
|
||||
import '../../../app_settings/app_colors.dart';
|
||||
@ -22,7 +19,8 @@ import '../../../tools/submitBtn.dart';
|
||||
import '../../../tools/titleAppBar.dart';
|
||||
import '../../../tools/wechat/wechatManageTool.dart';
|
||||
import '../../../tools/wechat/wx_push_miniProgram/wx_push_miniProgram.dart';
|
||||
import '../../../translations/trans_lib.dart';
|
||||
import '../../../translations/app_dept.dart';
|
||||
import '../../../translations/current_locale_tool.dart';
|
||||
|
||||
class MineSetPage extends StatefulWidget {
|
||||
MineSetPage({Key? key, this.showAppBar = true, this.showAbout = false})
|
||||
@ -303,10 +301,10 @@ class _MineSetPageState extends State<MineSetPage>
|
||||
isHaveDirection: true,
|
||||
action: () async {
|
||||
// Get.toNamed(Routers.mineMultiLanguagePage);
|
||||
await Get.toNamed(Routers.mineMultiLanguagePage)!.then(
|
||||
(value) => {
|
||||
state.currentLanguage.value = value['currentLanguage']
|
||||
});
|
||||
await Get.toNamed(Routers.mineMultiLanguagePage)!.then((value) {
|
||||
state.currentLanguage.value = value['currentLanguage'];
|
||||
setState(() {});
|
||||
});
|
||||
});
|
||||
}),
|
||||
/* 2024-01-12 会议确定去掉“锁屏” by DaisyWu
|
||||
@ -516,11 +514,23 @@ class _MineSetPageState extends State<MineSetPage>
|
||||
Expanded(
|
||||
child: Text(leftTitle!, style: TextStyle(fontSize: 22.sp))),
|
||||
SizedBox(width: 10.w),
|
||||
Image.asset(
|
||||
'images/icon_right_grey.png',
|
||||
width: 12.w,
|
||||
height: 21.w,
|
||||
),
|
||||
if (CurrentLocaleTool.getCurrentLocaleString() ==
|
||||
ExtensionLanguageType.fromLanguageType(LanguageType.hebrew)
|
||||
.toString() ||
|
||||
CurrentLocaleTool.getCurrentLocaleString() ==
|
||||
ExtensionLanguageType.fromLanguageType(LanguageType.arabic)
|
||||
.toString())
|
||||
Image.asset(
|
||||
'images/icon_left_grey.png',
|
||||
width: 21.w,
|
||||
height: 21.w,
|
||||
)
|
||||
else
|
||||
Image.asset(
|
||||
'images/icon_right_grey.png',
|
||||
width: 12.w,
|
||||
height: 21.w,
|
||||
),
|
||||
SizedBox(width: 5.w),
|
||||
],
|
||||
),
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:star_lock/app_settings/app_settings.dart';
|
||||
import 'package:star_lock/mine/minePersonInfo/minePersonInfoPage/minePersonInfo_entity.dart';
|
||||
import 'package:star_lock/mine/mineSet/mineSet/userSettingInfoEntity.dart';
|
||||
|
||||
import '../../../tools/store_service.dart';
|
||||
import '../../../translations/app_dept.dart';
|
||||
import '../../../translations/current_locale_tool.dart';
|
||||
|
||||
@ -24,10 +26,14 @@ class MineSetState {
|
||||
|
||||
/// 获取翻译后的国家名称
|
||||
String get currentLanguageName {
|
||||
return ExtensionLanguageType.fromLocale(
|
||||
CurrentLocaleTool.getCurrentLocaleWithLanguageCode(
|
||||
currentLanguage.value))
|
||||
.lanTitle;
|
||||
AppLog.log(
|
||||
'currentLanguage.value:${currentLanguage.value} fsgdsgddfg:${CurrentLocaleTool.getCurrentLocaleWithLanguageCode(currentLanguage.value)}');
|
||||
return StoreService.to.getLanguageCode()!.isEmpty
|
||||
? '跟随系统'.tr
|
||||
: ExtensionLanguageType.fromLocale(CurrentLocaleTool.convertLocale(
|
||||
CurrentLocaleTool.getCurrentLocaleWithLanguageCode(
|
||||
currentLanguage.value)))
|
||||
.lanTitle;
|
||||
}
|
||||
|
||||
RxBool isAmazonAlexa = false.obs; //亚马逊Alexa
|
||||
|
||||
@ -4,6 +4,7 @@ import 'dart:typed_data';
|
||||
import 'package:star_lock/talk/startChart/constant/message_type_constant.dart';
|
||||
import 'package:star_lock/talk/startChart/constant/payload_type_constant.dart';
|
||||
import 'package:star_lock/talk/startChart/constant/protocol_flag_constant.dart';
|
||||
import 'package:star_lock/talk/startChart/constant/udp_constant.dart';
|
||||
import 'package:star_lock/talk/startChart/entity/scp_message.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/gateway_reset.pb.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/generic.pb.dart';
|
||||
@ -17,12 +18,12 @@ import 'package:star_lock/talk/startChart/proto/talk_request.pb.dart';
|
||||
|
||||
class MessageCommand {
|
||||
// 全局字典,用于存储每个 ToPeerId 对应的当前 messageId
|
||||
// 单个会话的messageId需要递增
|
||||
static Map<String, int> _messageIdMap = {};
|
||||
static int _maxIntValue = 9223372036854775807; // Dart 中 int 的最大值
|
||||
|
||||
// 获取并递增消息ID
|
||||
static int getNextMessageId(String toPeerId, {bool increment = true}) {
|
||||
|
||||
static int getNextMessageId(String toPeerId, {bool increment = true}) {
|
||||
if (_messageIdMap.containsKey(toPeerId)) {
|
||||
if (increment) {
|
||||
_messageIdMap[toPeerId] = _messageIdMap[toPeerId]! + 1;
|
||||
@ -51,7 +52,6 @@ class MessageCommand {
|
||||
SpIndex: 1,
|
||||
FromPeerId: FromPeerId,
|
||||
ToPeerId: ToPeerId,
|
||||
Payload: [0],
|
||||
PayloadCRC: 0,
|
||||
PayloadLength: 0,
|
||||
PayloadType: PayloadTypeConstant.goOnline,
|
||||
@ -295,7 +295,7 @@ class MessageCommand {
|
||||
static List<int> talkExpectMessage({
|
||||
required String FromPeerId,
|
||||
required String ToPeerId,
|
||||
required TalkExpect talkExpect,
|
||||
required TalkExpectReq talkExpect,
|
||||
int? MessageId,
|
||||
}) {
|
||||
final payload = talkExpect.writeToBuffer();
|
||||
@ -324,8 +324,8 @@ class MessageCommand {
|
||||
int? MessageId,
|
||||
}) {
|
||||
final genericResp = GenericResp();
|
||||
genericResp.message = 'ok';
|
||||
genericResp.code = 0;
|
||||
genericResp.message = UdpConstant.genericRespSuccessMsg;
|
||||
genericResp.code = UdpConstant.genericRespSuccessCode;
|
||||
final payload = genericResp.writeToBuffer();
|
||||
ScpMessage message = ScpMessage(
|
||||
ProtocolFlag: ProtocolFlagConstant.scp01,
|
||||
@ -350,10 +350,11 @@ class MessageCommand {
|
||||
required String ToPeerId,
|
||||
required int PayloadType,
|
||||
int? MessageId,
|
||||
String? errorMessageText,
|
||||
}) {
|
||||
final genericResp = GenericResp();
|
||||
genericResp.message = 'error';
|
||||
genericResp.code = -1;
|
||||
genericResp.message = errorMessageText ?? UdpConstant.genericRespErrorMsg;
|
||||
genericResp.code = UdpConstant.genericRespErrorCode;
|
||||
final payload = genericResp.writeToBuffer();
|
||||
ScpMessage message = ScpMessage(
|
||||
ProtocolFlag: ProtocolFlagConstant.scp01,
|
||||
|
||||
3
lib/talk/startChart/constant/exception_constant.dart
Normal file
3
lib/talk/startChart/constant/exception_constant.dart
Normal file
@ -0,0 +1,3 @@
|
||||
class ExceptionConstant{
|
||||
static const String relay = 'relay';
|
||||
}
|
||||
18
lib/talk/startChart/constant/talk_status.dart
Normal file
18
lib/talk/startChart/constant/talk_status.dart
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
|
||||
enum TalkStatus {
|
||||
none, // 无状态
|
||||
waitingAnswer, // 等待接听
|
||||
answeredSuccessfully, // 接听成功
|
||||
waitingData, // 等待数据
|
||||
duringCall, // 通话中
|
||||
hangingUpDuring, // 通话中挂断
|
||||
rejected, // 被拒绝
|
||||
uninitialized, // 未初始化
|
||||
initializationCompleted, // 初始化完成
|
||||
notTalkData, // 暂无通话数据
|
||||
notTalkPing, // 暂无通话保持
|
||||
error, // 错误状态
|
||||
end, // 结束
|
||||
}
|
||||
|
||||
@ -2,4 +2,7 @@ class UdpConstant{
|
||||
// generic成功响应
|
||||
static const int genericRespSuccessCode = 0;
|
||||
static const String genericRespSuccessMsg = 'ok';
|
||||
// generic失败响应
|
||||
static const int genericRespErrorCode = -1;
|
||||
static const String genericRespErrorMsg = 'error';
|
||||
}
|
||||
@ -1,37 +1,55 @@
|
||||
class HeartbeatResponse {
|
||||
int? statusCode;
|
||||
int? nextPingTime;
|
||||
String? clientAddr;
|
||||
|
||||
HeartbeatResponse({
|
||||
this.statusCode,
|
||||
this.nextPingTime,
|
||||
this.clientAddr,
|
||||
});
|
||||
|
||||
factory HeartbeatResponse.fromBytes(List<int> bytes) {
|
||||
final message = HeartbeatResponse();
|
||||
int offset = 0;
|
||||
|
||||
// Set default value for statusCode
|
||||
message.statusCode = 0; // 或者其他默认值
|
||||
|
||||
// Check if the entire array has at least 2 bytes for nextPingTime
|
||||
if (bytes.length < 2) {
|
||||
// 检查是否有足够的数据来解析状态码
|
||||
if (bytes.length < 1) {
|
||||
throw FormatException("Insufficient data for HeartbeatResponse");
|
||||
}
|
||||
|
||||
// nextPingTime (2 bytes, little-endian)
|
||||
if (bytes.length - offset >= 2) {
|
||||
message.nextPingTime = (bytes[offset + 1] << 8) | bytes[offset];
|
||||
offset += 2;
|
||||
} else {
|
||||
throw FormatException("Invalid nextPingTime length");
|
||||
// 解析状态码 (1 byte)
|
||||
message.statusCode = bytes[offset];
|
||||
offset += 1;
|
||||
|
||||
// 检查是否有足够的数据来解析 nextPingTime
|
||||
if (bytes.length < offset + 2) {
|
||||
throw FormatException("Insufficient data for nextPingTime");
|
||||
}
|
||||
|
||||
// 解析 nextPingTime (2 bytes, little-endian)
|
||||
message.nextPingTime = (bytes[offset + 1] << 8) | bytes[offset];
|
||||
offset += 2;
|
||||
|
||||
// 解析 clientAddr (null-terminated string)
|
||||
final clientAddrBytes = <int>[];
|
||||
while (offset < bytes.length && bytes[offset] != 0) {
|
||||
clientAddrBytes.add(bytes[offset]);
|
||||
offset++;
|
||||
}
|
||||
|
||||
// 跳过 null terminator
|
||||
if (offset < bytes.length && bytes[offset] == 0) {
|
||||
offset++;
|
||||
}
|
||||
|
||||
message.clientAddr = String.fromCharCodes(clientAddrBytes);
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'HeartbeatResponse{statusCode: $statusCode, nextPingTime: $nextPingTime}';
|
||||
return 'HeartbeatResponse{statusCode: $statusCode, nextPingTime: $nextPingTime, clientAddr: $clientAddr}';
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,32 +1,11 @@
|
||||
import 'dart:convert';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:protobuf/protobuf.dart';
|
||||
import 'dart:typed_data';
|
||||
import 'package:star_lock/app_settings/app_settings.dart';
|
||||
import 'package:star_lock/talk/startChart/constant/message_type_constant.dart';
|
||||
import 'package:star_lock/talk/startChart/constant/payload_type_constant.dart';
|
||||
import 'package:star_lock/talk/startChart/entity/heartbeat_response.dart';
|
||||
import 'package:star_lock/talk/startChart/entity/login_response.dart';
|
||||
import 'package:star_lock/talk/startChart/handle/other/talk_data_repository.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/ble_message.pb.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/gateway_reset.pb.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/gateway_transfer.pb.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/generic.pb.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/remote_unlock.pb.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/talk_accept.pbserver.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/talk_data.pb.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/talk_expect.pb.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/talk_hangup.pb.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/talk_ping.pb.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/talk_push.pbserver.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/talk_receiver_transfer.pb.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/talk_reject.pb.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/talk_request.pb.dart';
|
||||
import 'package:star_lock/talk/startChart/exception/start_chart_message_exception.dart';
|
||||
import 'package:star_lock/talk/startChart/handle/scp_message_handle.dart';
|
||||
import 'package:star_lock/talk/startChart/handle/scp_message_handler_factory.dart';
|
||||
|
||||
class ScpMessage {
|
||||
/// 分包缓冲区
|
||||
// 存储每个 messageId 对应的分包数据
|
||||
static Map<int, List<List<int>>> _packetBuffer = {};
|
||||
|
||||
ScpMessage({
|
||||
this.ProtocolFlag,
|
||||
this.MessageType,
|
||||
@ -167,15 +146,17 @@ class ScpMessage {
|
||||
return bytesToHexString;
|
||||
}
|
||||
|
||||
static ScpMessage deserialize(List<int> bytes) {
|
||||
static ScpMessage deserialize(Uint8List bytes) {
|
||||
final message = ScpMessage();
|
||||
int offset = 0;
|
||||
// Convert byte array to hex string with zero padding and without spaces
|
||||
String hexString =
|
||||
bytes.map((b) => b.toRadixString(16).padLeft(2, '0')).join();
|
||||
|
||||
// Log the hex string
|
||||
_log(text: '原始字节数组: $hexString');
|
||||
// String hexString =
|
||||
// bytes.map((b) => b.toRadixString(16).padLeft(2, '0')).join();
|
||||
// // _log(text: 'result bytes hex: ${hexString}');
|
||||
// _log(
|
||||
// text:
|
||||
// '\n result bytes hex: ${hexString} \n payload hex: ${hexString.substring(210)}');
|
||||
|
||||
// ProtocolFlag (4 bytes)
|
||||
if (bytes.length - offset >= 4) {
|
||||
message.ProtocolFlag = utf8.decode(bytes.sublist(offset, offset + 4));
|
||||
@ -276,9 +257,6 @@ class ScpMessage {
|
||||
spTotal: message.SpTotal,
|
||||
messageId: message.MessageId,
|
||||
);
|
||||
// if (message.Payload != null && message.Payload is List<int>) {
|
||||
// message.PayloadLength = message.Payload.length;
|
||||
// }
|
||||
} else {
|
||||
throw FormatException("Invalid Payload or PayloadLength");
|
||||
}
|
||||
@ -298,203 +276,23 @@ class ScpMessage {
|
||||
int? messageId,
|
||||
}) {
|
||||
try {
|
||||
switch (payloadType) {
|
||||
case PayloadTypeConstant.goOnline:
|
||||
// 上线
|
||||
LoginResponse loginResp = LoginResponse.fromBytes(byte);
|
||||
return loginResp;
|
||||
case PayloadTypeConstant.heartbeat:
|
||||
// 心跳
|
||||
HeartbeatResponse heartbeatResponse =
|
||||
HeartbeatResponse.fromBytes(byte);
|
||||
return heartbeatResponse;
|
||||
case PayloadTypeConstant.echoTest:
|
||||
// 回声测试
|
||||
if (spTotal != null &&
|
||||
spTotal > 1 &&
|
||||
messageId != null &&
|
||||
spIndex != null) {
|
||||
// 分包处理
|
||||
return _handleFragmentedPayload(
|
||||
messageId: messageId,
|
||||
spTotal: spTotal,
|
||||
spIndex: spIndex,
|
||||
byte: byte,
|
||||
payloadType: payloadType,
|
||||
);
|
||||
} else {
|
||||
// 如果 spTotal 为 1 或者没有分包信息,直接处理 byte 数据
|
||||
String payload = utf8.decode(byte);
|
||||
return payload;
|
||||
}
|
||||
case PayloadTypeConstant.gatewayReset:
|
||||
// 初始化网关
|
||||
if (messageType == MessageTypeConstant.Resp) {
|
||||
final GatewayResetResp gatewayResetResp =
|
||||
GatewayResetResp.fromBuffer(byte);
|
||||
return gatewayResetResp;
|
||||
} else if (messageType == MessageTypeConstant.Req) {
|
||||
final GatewayResetReq gatewayResetReq =
|
||||
GatewayResetReq.fromBuffer(byte);
|
||||
return gatewayResetReq;
|
||||
} else {
|
||||
String payload = utf8.decode(byte);
|
||||
return payload;
|
||||
}
|
||||
case PayloadTypeConstant.callRequest:
|
||||
if (messageType == MessageTypeConstant.Resp) {
|
||||
final GenericResp genericResp = GenericResp.fromBuffer(byte);
|
||||
return genericResp;
|
||||
} else if (messageType == MessageTypeConstant.Req) {
|
||||
final TalkReq talkReq = TalkReq.fromBuffer(byte);
|
||||
return talkReq;
|
||||
} else {
|
||||
String payload = utf8.decode(byte);
|
||||
return payload;
|
||||
}
|
||||
case PayloadTypeConstant.talkAccept:
|
||||
if (messageType == MessageTypeConstant.Resp) {
|
||||
final GenericResp genericResp = GenericResp.fromBuffer(byte);
|
||||
return genericResp;
|
||||
} else if (messageType == MessageTypeConstant.Req) {
|
||||
final TalkAcceptReq talkAccept = TalkAcceptReq.fromBuffer(byte);
|
||||
return talkAccept;
|
||||
} else {
|
||||
String payload = utf8.decode(byte);
|
||||
return payload;
|
||||
}
|
||||
case PayloadTypeConstant.gatewayTransfer:
|
||||
if (messageType == MessageTypeConstant.Resp) {
|
||||
final GenericResp genericResp = GenericResp.fromBuffer(byte);
|
||||
return genericResp;
|
||||
} else if (messageType == MessageTypeConstant.Req) {
|
||||
final GatewayTransferReq gatewayTransferReq =
|
||||
GatewayTransferReq.fromBuffer(byte);
|
||||
return gatewayTransferReq;
|
||||
} else {
|
||||
String payload = utf8.decode(byte);
|
||||
return payload;
|
||||
}
|
||||
case PayloadTypeConstant.blePassthrough:
|
||||
final BleResp bleResp = BleResp.fromBuffer(byte);
|
||||
return bleResp;
|
||||
case PayloadTypeConstant.remoteUnlock:
|
||||
if (messageType == MessageTypeConstant.Resp) {
|
||||
final GenericResp genericResp = GenericResp.fromBuffer(byte);
|
||||
return genericResp;
|
||||
} else if (messageType == MessageTypeConstant.Req) {
|
||||
final RemoteUnlockResp remoteUnlockResp =
|
||||
RemoteUnlockResp.fromBuffer(byte);
|
||||
return remoteUnlockResp;
|
||||
} else {
|
||||
String payload = utf8.decode(byte);
|
||||
return payload;
|
||||
}
|
||||
case PayloadTypeConstant.talkReceiverTransfer:
|
||||
if (messageType == MessageTypeConstant.Resp) {
|
||||
final GenericResp genericResp = GenericResp.fromBuffer(byte);
|
||||
return genericResp;
|
||||
} else if (messageType == MessageTypeConstant.Req) {
|
||||
final TalkReceiverTransfer talkReceiverTransfer =
|
||||
TalkReceiverTransfer.fromBuffer(byte);
|
||||
return talkReceiverTransfer;
|
||||
} else {
|
||||
String payload = utf8.decode(byte);
|
||||
return payload;
|
||||
}
|
||||
case PayloadTypeConstant.talkPush:
|
||||
if (messageType == MessageTypeConstant.Resp) {
|
||||
final GenericResp genericResp = GenericResp.fromBuffer(byte);
|
||||
return genericResp;
|
||||
} else if (messageType == MessageTypeConstant.Req) {
|
||||
final TalkPush talkPush = TalkPush.fromBuffer(byte);
|
||||
return talkPush;
|
||||
} else {
|
||||
String payload = utf8.decode(byte);
|
||||
return payload;
|
||||
}
|
||||
case PayloadTypeConstant.talkReject:
|
||||
if (messageType == MessageTypeConstant.Resp) {
|
||||
final GenericResp genericResp = GenericResp.fromBuffer(byte);
|
||||
return genericResp;
|
||||
} else if (messageType == MessageTypeConstant.Req) {
|
||||
final TalkReject talkReject = TalkReject.fromBuffer(byte);
|
||||
return talkReject;
|
||||
} else {
|
||||
String payload = utf8.decode(byte);
|
||||
return payload;
|
||||
}
|
||||
case PayloadTypeConstant.talkPing:
|
||||
if (messageType == MessageTypeConstant.Resp) {
|
||||
final GenericResp genericResp = GenericResp.fromBuffer(byte);
|
||||
return genericResp;
|
||||
} else if (messageType == MessageTypeConstant.Req) {
|
||||
final TalkPing talkPing = TalkPing.fromBuffer(byte);
|
||||
return talkPing;
|
||||
} else {
|
||||
String payload = utf8.decode(byte);
|
||||
return payload;
|
||||
}
|
||||
case PayloadTypeConstant.talkExpect:
|
||||
if (messageType == MessageTypeConstant.Resp) {
|
||||
final GenericResp genericResp = GenericResp.fromBuffer(byte);
|
||||
return genericResp;
|
||||
} else if (messageType == MessageTypeConstant.Req) {
|
||||
final TalkExpect talkExpect = TalkExpect.fromBuffer(byte);
|
||||
return talkExpect;
|
||||
} else {
|
||||
String payload = utf8.decode(byte);
|
||||
return payload;
|
||||
}
|
||||
case PayloadTypeConstant.talkData:
|
||||
if (messageType == MessageTypeConstant.Resp) {
|
||||
final GenericResp genericResp = GenericResp.fromBuffer(byte);
|
||||
return genericResp;
|
||||
} else if (messageType == MessageTypeConstant.RealTimeData) {
|
||||
// 回声测试
|
||||
if (spTotal != null &&
|
||||
spTotal > 1 &&
|
||||
messageId != null &&
|
||||
spIndex != null) {
|
||||
// 分包处理
|
||||
return _handleFragmentedPayload(
|
||||
messageId: messageId,
|
||||
spTotal: spTotal,
|
||||
spIndex: spIndex,
|
||||
byte: byte,
|
||||
payloadType: payloadType,
|
||||
);
|
||||
} else {
|
||||
// 没有分包直接解析
|
||||
final TalkData talkData = TalkData.fromBuffer(byte);
|
||||
return talkData;
|
||||
}
|
||||
} else {
|
||||
String payload = utf8.decode(byte);
|
||||
return payload;
|
||||
}
|
||||
case PayloadTypeConstant.talkHangup:
|
||||
if (messageType == MessageTypeConstant.Resp) {
|
||||
final GenericResp genericResp = GenericResp.fromBuffer(byte);
|
||||
return genericResp;
|
||||
} else if (messageType == MessageTypeConstant.RealTimeData) {
|
||||
final TalkHangup talkHangup = TalkHangup.fromBuffer(byte);
|
||||
return talkHangup;
|
||||
} else {
|
||||
String payload = utf8.decode(byte);
|
||||
return payload;
|
||||
}
|
||||
default:
|
||||
print('❌未知的payloadType类型,按照字符串解析');
|
||||
String payload = utf8.decode(byte);
|
||||
return payload;
|
||||
}
|
||||
// 构造工厂
|
||||
final ScpMessageHandler handler =
|
||||
ScpMessageHandlerFactory.createHandler(payloadType);
|
||||
// 处理荷载信息并返回
|
||||
final payload = handler.deserializePayload(
|
||||
payloadType: payloadType,
|
||||
messageType: messageType,
|
||||
byte: byte,
|
||||
offset: offset,
|
||||
PayloadLength: PayloadLength,
|
||||
spTotal: spTotal,
|
||||
spIndex: spIndex,
|
||||
messageId: messageId,
|
||||
);
|
||||
return payload;
|
||||
} catch (e, stackTrace) {
|
||||
// 打印异常信息
|
||||
_log(text: '❌反序列化udp数据时遇到错误----》$e');
|
||||
// 打印堆栈跟踪信息
|
||||
_log(text: '堆栈跟踪:\n$stackTrace');
|
||||
return '';
|
||||
throw StartChartMessageException('❌反序列化udp数据时遇到错误----》$e \n$stackTrace');
|
||||
}
|
||||
}
|
||||
|
||||
@ -515,49 +313,4 @@ class ScpMessage {
|
||||
static void _log({required String text}) {
|
||||
AppLog.log('=====${text}');
|
||||
}
|
||||
|
||||
/// 处理分包逻辑
|
||||
/// 如果没有收到所有包则返回null
|
||||
static dynamic _handleFragmentedPayload({
|
||||
required int messageId,
|
||||
required int spTotal,
|
||||
required int spIndex,
|
||||
required List<int> byte,
|
||||
required int payloadType,
|
||||
}) {
|
||||
// 初始化分包列表
|
||||
if (!_packetBuffer.containsKey(messageId)) {
|
||||
_packetBuffer[messageId] = List.filled(spTotal, []);
|
||||
}
|
||||
|
||||
// 检查分包索引是否在合法范围内
|
||||
if (spIndex < 1 || spIndex > spTotal) {
|
||||
print('Invalid spIndex: $spIndex for messageId: $messageId');
|
||||
return null;
|
||||
}
|
||||
|
||||
// 存储当前分包
|
||||
_packetBuffer[messageId]![spIndex - 1] = byte;
|
||||
|
||||
// 检查是否接收到所有分包
|
||||
if (_packetBuffer[messageId]!.every((packet) => packet.isNotEmpty)) {
|
||||
// 重组所有分包
|
||||
List<int> completePayload = _packetBuffer[messageId]!.expand((packet) => packet).toList();
|
||||
|
||||
// 清除已重组的分包数据
|
||||
_packetBuffer.remove(messageId);
|
||||
|
||||
// 解析完整的 payload
|
||||
if (payloadType == PayloadTypeConstant.talkData) {
|
||||
final TalkData talkData = TalkData.fromBuffer(completePayload);
|
||||
return talkData;
|
||||
} else {
|
||||
String payload = utf8.decode(completePayload);
|
||||
return payload;
|
||||
}
|
||||
} else {
|
||||
// 如果分包尚未接收完全,返回 null 或其他指示符
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,13 +0,0 @@
|
||||
import 'package:star_lock/talk/startChart/start_chart_talk_status.dart';
|
||||
|
||||
class TalkStatusChangeEvent {
|
||||
final TalkStatus oldStatus;
|
||||
final TalkStatus newStatus;
|
||||
|
||||
TalkStatusChangeEvent(this.oldStatus, this.newStatus);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return "TalkStatusChangeEvent: ${oldStatus.name} -> ${newStatus.name}";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
class StartChartMessageException implements Exception {
|
||||
final String message;
|
||||
|
||||
StartChartMessageException(this.message);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'StartChartMessageException{message: $message}';
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
class StartChartTalkStatusException implements Exception {
|
||||
final String message;
|
||||
|
||||
StartChartTalkStatusException(this.message);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'StartChartTalkStatusException{message: $message}';
|
||||
}
|
||||
}
|
||||
@ -1,3 +1,5 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:star_lock/appRouters.dart';
|
||||
@ -28,4 +30,19 @@ class UdpBlePassThroughHandler extends ScpMessageBaseHandle
|
||||
|
||||
@override
|
||||
void handleRealTimeData(ScpMessage scpMessage) {}
|
||||
|
||||
@override
|
||||
deserializePayload(
|
||||
{required int payloadType,
|
||||
required int messageType,
|
||||
required List<int> byte,
|
||||
int? offset,
|
||||
int? PayloadLength,
|
||||
int? spTotal,
|
||||
int? spIndex,
|
||||
int? messageId}) {
|
||||
final BleResp bleResp = BleResp();
|
||||
bleResp.mergeFromBuffer(byte);
|
||||
return bleResp;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:star_lock/talk/startChart/entity/scp_message.dart';
|
||||
@ -10,15 +13,11 @@ import '../../start_chart_manage.dart';
|
||||
class UdpEchoTestHandler extends ScpMessageBaseHandle
|
||||
implements ScpMessageHandler {
|
||||
@override
|
||||
void handleReq(ScpMessage scpMessage) {
|
||||
// TODO: 收到回声测试请求
|
||||
}
|
||||
void handleReq(ScpMessage scpMessage) {}
|
||||
|
||||
@override
|
||||
void handleResp(ScpMessage scpMessage) {
|
||||
// TODO: 收到回声测试回复
|
||||
final List<int> payload = scpMessage.Payload;
|
||||
|
||||
if (payload is String) {
|
||||
EasyLoading.showToast(scpMessage.Payload, duration: 2000.milliseconds);
|
||||
} else {
|
||||
@ -32,4 +31,34 @@ class UdpEchoTestHandler extends ScpMessageBaseHandle
|
||||
|
||||
@override
|
||||
void handleRealTimeData(ScpMessage scpMessage) {}
|
||||
|
||||
@override
|
||||
deserializePayload(
|
||||
{required int payloadType,
|
||||
required int messageType,
|
||||
required List<int> byte,
|
||||
int? offset,
|
||||
int? PayloadLength,
|
||||
int? spTotal,
|
||||
int? spIndex,
|
||||
int? messageId}) {
|
||||
// 回声测试
|
||||
if (spTotal != null &&
|
||||
spTotal > 1 &&
|
||||
messageId != null &&
|
||||
spIndex != null) {
|
||||
// 分包处理
|
||||
return handleFragmentedPayload(
|
||||
messageId: messageId,
|
||||
spTotal: spTotal,
|
||||
spIndex: spIndex,
|
||||
byte: byte,
|
||||
payloadType: payloadType,
|
||||
);
|
||||
} else {
|
||||
// 如果 spTotal 为 1 或者没有分包信息,直接处理 byte 数据
|
||||
String payload = utf8.decode(byte);
|
||||
return payload;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:star_lock/talk/startChart/constant/message_type_constant.dart';
|
||||
import 'package:star_lock/talk/startChart/entity/scp_message.dart';
|
||||
import 'package:star_lock/talk/startChart/handle/scp_message_base_handle.dart';
|
||||
import 'package:star_lock/talk/startChart/handle/scp_message_handle.dart';
|
||||
@ -7,17 +11,14 @@ import 'package:star_lock/talk/startChart/proto/gateway_reset.pb.dart';
|
||||
|
||||
import '../../start_chart_manage.dart';
|
||||
|
||||
class UdpGateWayResetHandler extends ScpMessageBaseHandle implements ScpMessageHandler {
|
||||
|
||||
|
||||
class UdpGateWayResetHandler extends ScpMessageBaseHandle
|
||||
implements ScpMessageHandler {
|
||||
@override
|
||||
void handleReq(ScpMessage scpMessage) {
|
||||
// TODO: 收到网关初始化请求
|
||||
final GatewayResetResp gatewayResetResp = scpMessage.Payload;
|
||||
final status = gatewayResetResp.status;
|
||||
if (status != null && status == GatewayResetResp_StatusE.OK) {
|
||||
|
||||
}
|
||||
if (status != null && status == GatewayResetResp_StatusE.OK) {}
|
||||
}
|
||||
|
||||
@override
|
||||
@ -26,12 +27,33 @@ class UdpGateWayResetHandler extends ScpMessageBaseHandle implements ScpMessageH
|
||||
}
|
||||
|
||||
@override
|
||||
void handleInvalidReq(ScpMessage scpMessage) {
|
||||
|
||||
}
|
||||
void handleInvalidReq(ScpMessage scpMessage) {}
|
||||
|
||||
@override
|
||||
void handleRealTimeData(ScpMessage scpMessage) {
|
||||
void handleRealTimeData(ScpMessage scpMessage) {}
|
||||
|
||||
@override
|
||||
deserializePayload(
|
||||
{required int payloadType,
|
||||
required int messageType,
|
||||
required List<int> byte,
|
||||
int? offset,
|
||||
int? PayloadLength,
|
||||
int? spTotal,
|
||||
int? spIndex,
|
||||
int? messageId}) {
|
||||
// 初始化网关
|
||||
if (messageType == MessageTypeConstant.Resp) {
|
||||
final GatewayResetResp gatewayResetResp =
|
||||
GatewayResetResp.fromBuffer(byte);
|
||||
return gatewayResetResp;
|
||||
} else if (messageType == MessageTypeConstant.Req) {
|
||||
final GatewayResetReq gatewayResetReq = GatewayResetReq();
|
||||
gatewayResetReq.mergeFromBuffer(byte);
|
||||
return gatewayResetReq;
|
||||
} else {
|
||||
String payload = utf8.decode(byte);
|
||||
return payload;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,9 +1,14 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:star_lock/talk/startChart/constant/message_type_constant.dart';
|
||||
import 'package:star_lock/talk/startChart/entity/scp_message.dart';
|
||||
import 'package:star_lock/talk/startChart/handle/scp_message_base_handle.dart';
|
||||
import 'package:star_lock/talk/startChart/handle/scp_message_handle.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/gateway_reset.pb.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/gateway_transfer.pb.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/generic.pb.dart';
|
||||
|
||||
import '../../start_chart_manage.dart';
|
||||
@ -29,4 +34,28 @@ class UdpGateWayTransferHandler extends ScpMessageBaseHandle
|
||||
|
||||
@override
|
||||
void handleRealTimeData(ScpMessage scpMessage) {}
|
||||
|
||||
@override
|
||||
deserializePayload(
|
||||
{required int payloadType,
|
||||
required int messageType,
|
||||
required List<int> byte,
|
||||
int? offset,
|
||||
int? PayloadLength,
|
||||
int? spTotal,
|
||||
int? spIndex,
|
||||
int? messageId}) {
|
||||
if (messageType == MessageTypeConstant.Resp) {
|
||||
final GenericResp genericResp = GenericResp();
|
||||
genericResp.mergeFromBuffer(byte);
|
||||
return genericResp;
|
||||
} else if (messageType == MessageTypeConstant.Req) {
|
||||
final GatewayTransferReq gatewayTransferReq = GatewayTransferReq();
|
||||
gatewayTransferReq.mergeFromBuffer(byte);
|
||||
return gatewayTransferReq;
|
||||
} else {
|
||||
String payload = utf8.decode(byte);
|
||||
return payload;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:star_lock/talk/startChart/constant/payload_type_constant.dart';
|
||||
import 'package:star_lock/talk/startChart/entity/login_response.dart';
|
||||
import 'package:star_lock/talk/startChart/entity/scp_message.dart';
|
||||
@ -35,4 +37,19 @@ class UdpGoOnlineHandler extends ScpMessageBaseHandle
|
||||
|
||||
@override
|
||||
void handleRealTimeData(ScpMessage scpMessage) {}
|
||||
|
||||
@override
|
||||
deserializePayload(
|
||||
{required int payloadType,
|
||||
required int messageType,
|
||||
required List<int> byte,
|
||||
int? offset,
|
||||
int? PayloadLength,
|
||||
int? spTotal,
|
||||
int? spIndex,
|
||||
int? messageId}) {
|
||||
// 上线
|
||||
LoginResponse loginResp = LoginResponse.fromBytes(byte);
|
||||
return loginResp;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:star_lock/talk/startChart/constant/payload_type_constant.dart';
|
||||
import 'package:star_lock/talk/startChart/entity/heartbeat_response.dart';
|
||||
import 'package:star_lock/talk/startChart/entity/login_response.dart';
|
||||
@ -39,4 +41,19 @@ class UdpHeartBeatHandler extends ScpMessageBaseHandle
|
||||
|
||||
@override
|
||||
void handleRealTimeData(ScpMessage scpMessage) {}
|
||||
|
||||
@override
|
||||
deserializePayload(
|
||||
{required int payloadType,
|
||||
required int messageType,
|
||||
required List<int> byte,
|
||||
int? offset,
|
||||
int? PayloadLength,
|
||||
int? spTotal,
|
||||
int? spIndex,
|
||||
int? messageId}) {
|
||||
// 心跳
|
||||
HeartbeatResponse heartbeatResponse = HeartbeatResponse.fromBytes(byte);
|
||||
return heartbeatResponse;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,10 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:star_lock/appRouters.dart';
|
||||
import 'package:star_lock/talk/startChart/constant/message_type_constant.dart';
|
||||
import 'package:star_lock/talk/startChart/entity/scp_message.dart';
|
||||
import 'package:star_lock/talk/startChart/handle/scp_message_base_handle.dart';
|
||||
import 'package:star_lock/talk/startChart/handle/scp_message_handle.dart';
|
||||
@ -32,4 +36,20 @@ class UdpRemoteUnLockHandler extends ScpMessageBaseHandle implements ScpMessageH
|
||||
void handleRealTimeData(ScpMessage scpMessage) {
|
||||
|
||||
}
|
||||
|
||||
@override
|
||||
deserializePayload({required int payloadType, required int messageType, required List<int> byte, int? offset, int? PayloadLength, int? spTotal, int? spIndex, int? messageId}) {
|
||||
if (messageType == MessageTypeConstant.Resp) {
|
||||
final GenericResp genericResp = GenericResp();
|
||||
genericResp.mergeFromBuffer(byte);
|
||||
return genericResp;
|
||||
} else if (messageType == MessageTypeConstant.Req) {
|
||||
final RemoteUnlockResp remoteUnlockResp = RemoteUnlockResp();
|
||||
remoteUnlockResp.mergeFromBuffer(byte);
|
||||
return remoteUnlockResp;
|
||||
} else {
|
||||
String payload = utf8.decode(byte);
|
||||
return payload;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,16 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
import 'package:flutter_pcm_sound/flutter_pcm_sound.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:star_lock/talk/startChart/constant/message_type_constant.dart';
|
||||
import 'package:star_lock/talk/startChart/entity/scp_message.dart';
|
||||
import 'package:star_lock/talk/startChart/handle/scp_message_base_handle.dart';
|
||||
import 'package:star_lock/talk/startChart/handle/scp_message_handle.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/gateway_reset.pb.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/generic.pb.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/talk_accept.pb.dart';
|
||||
|
||||
import '../../start_chart_manage.dart';
|
||||
|
||||
@ -12,22 +18,16 @@ class UdpTalkAcceptHandler extends ScpMessageBaseHandle
|
||||
implements ScpMessageHandler {
|
||||
@override
|
||||
void handleReq(ScpMessage scpMessage) {
|
||||
print('收到同意接听请求');
|
||||
// 回复同意接听消息
|
||||
startChartManage.sendGenericRespSuccessMessage(
|
||||
ToPeerId: scpMessage.FromPeerId!,
|
||||
FromPeerId: scpMessage.ToPeerId!,
|
||||
PayloadType: scpMessage.PayloadType!,
|
||||
);
|
||||
replySuccessMessage(scpMessage);
|
||||
}
|
||||
|
||||
@override
|
||||
void handleResp(ScpMessage scpMessage) {
|
||||
void handleResp(ScpMessage scpMessage) {
|
||||
// 收到同意接听回复
|
||||
final GenericResp genericResp = scpMessage.Payload;
|
||||
if (checkGenericRespSuccess(genericResp)) {
|
||||
// 延迟2秒后启动监听
|
||||
Future.delayed(Duration(seconds: 4), () {
|
||||
Future.delayed(Duration(seconds: 1), () {
|
||||
// 启动通话保持定时器
|
||||
_handleStartTalkPing();
|
||||
// 启动发送预期数据请求
|
||||
@ -37,9 +37,11 @@ class UdpTalkAcceptHandler extends ScpMessageBaseHandle
|
||||
});
|
||||
// 停止播放铃声
|
||||
stopRingtone();
|
||||
// 设置状态为接听中
|
||||
// 设置状态为接听成功
|
||||
talkStatus.setAnsweredSuccessfully();
|
||||
talkStatus.setDuringCall();
|
||||
// 同意接听之后,停止对讲请求超时监听定时器
|
||||
talkeRequestOverTimeTimerManager.receiveMessage();
|
||||
talkeRequestOverTimeTimerManager.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,7 +51,31 @@ class UdpTalkAcceptHandler extends ScpMessageBaseHandle
|
||||
@override
|
||||
void handleRealTimeData(ScpMessage scpMessage) {}
|
||||
|
||||
// 启动通话保持
|
||||
@override
|
||||
deserializePayload(
|
||||
{required int payloadType,
|
||||
required int messageType,
|
||||
required List<int> byte,
|
||||
int? offset,
|
||||
int? PayloadLength,
|
||||
int? spTotal,
|
||||
int? spIndex,
|
||||
int? messageId}) {
|
||||
if (messageType == MessageTypeConstant.Resp) {
|
||||
final GenericResp genericResp = GenericResp();
|
||||
genericResp.mergeFromBuffer(byte);
|
||||
return genericResp;
|
||||
} else if (messageType == MessageTypeConstant.Req) {
|
||||
final TalkAcceptReq talkAccept = TalkAcceptReq();
|
||||
talkAccept.mergeFromBuffer(byte);
|
||||
return talkAccept;
|
||||
} else {
|
||||
String payload = utf8.decode(byte);
|
||||
return payload;
|
||||
}
|
||||
}
|
||||
|
||||
// 启动通话保持,判断x秒内是否收到通话保持
|
||||
void _handleStartTalkPing() {
|
||||
// 启动通话保持
|
||||
startChartManage.startTalkPingMessageTimer();
|
||||
|
||||
@ -1,7 +1,13 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:star_lock/app_settings/app_settings.dart';
|
||||
import 'package:star_lock/talk/call/g711.dart';
|
||||
import 'package:star_lock/talk/startChart/constant/message_type_constant.dart';
|
||||
import 'package:star_lock/talk/startChart/entity/scp_message.dart';
|
||||
import 'package:star_lock/talk/startChart/handle/scp_message_base_handle.dart';
|
||||
import 'package:star_lock/talk/startChart/handle/scp_message_handle.dart';
|
||||
@ -23,16 +29,61 @@ class UdpTalkDataHandler extends ScpMessageBaseHandle
|
||||
|
||||
@override
|
||||
void handleRealTimeData(ScpMessage scpMessage) {
|
||||
// 收到数据后调用更新,防止定时器超时
|
||||
talkDataOverTimeTimerManager.receiveMessage();
|
||||
if (scpMessage.Payload != null) {
|
||||
final TalkData talkData = scpMessage.Payload;
|
||||
// 处理音视频数据
|
||||
_handleTalkData(talkData: talkData);
|
||||
print('talkData:$talkData');
|
||||
// 收到数据后调用更新,防止定时器超时
|
||||
talkDataOverTimeTimerManager.receiveMessage();
|
||||
}
|
||||
}
|
||||
|
||||
String bufferToHexString(List<int> buffer) {
|
||||
return buffer.map((byte) => byte.toRadixString(16).padLeft(2, '0')).join();
|
||||
}
|
||||
|
||||
@override
|
||||
deserializePayload(
|
||||
{required int payloadType,
|
||||
required int messageType,
|
||||
required List<int> byte,
|
||||
int? offset,
|
||||
int? PayloadLength,
|
||||
int? spTotal,
|
||||
int? spIndex,
|
||||
int? messageId}) {
|
||||
// AppLog.log(
|
||||
// '没有组包之前的每一个包的数据:${byte.length} messageId:$messageId spTotal:$spTotal spIndex:$spIndex PayloadLength:$PayloadLength,byte:${bufferToHexString(byte)}');
|
||||
if (messageType == MessageTypeConstant.RealTimeData) {
|
||||
// 回声测试
|
||||
if (spTotal != null &&
|
||||
spTotal > 1 &&
|
||||
messageId != null &&
|
||||
spIndex != null) {
|
||||
// 分包处理
|
||||
return handleFragmentedPayload(
|
||||
messageId: messageId,
|
||||
spTotal: spTotal,
|
||||
spIndex: spIndex,
|
||||
byte: byte,
|
||||
payloadType: payloadType,
|
||||
);
|
||||
} else {
|
||||
// 没有分包直接解析
|
||||
final TalkData talkData = TalkData();
|
||||
talkData.mergeFromBuffer(byte);
|
||||
return talkData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String listToHexString(List<int> intList) {
|
||||
// 将整数列表转换为十六进制字符串列表
|
||||
List<String> hexList = intList.map((num) => num.toRadixString(16)).toList();
|
||||
// 将十六进制字符串列表连接成一个字符串,没有空格
|
||||
return hexList.join('');
|
||||
}
|
||||
|
||||
void _handleTalkData({required TalkData talkData}) {
|
||||
if (talkData == null) return;
|
||||
final contentType = talkData.contentType;
|
||||
@ -58,8 +109,65 @@ class UdpTalkDataHandler extends ScpMessageBaseHandle
|
||||
}
|
||||
|
||||
/// 处理图片数据
|
||||
void _handleVideoImage(TalkData talkData) {}
|
||||
void _handleVideoImage(TalkData talkData) async {
|
||||
final List<Uint8List> processCompletePayload =
|
||||
await _processCompletePayload(Uint8List.fromList(talkData.content));
|
||||
// AppLog.log('得到完整的帧:${processCompletePayload.length}'); // 循环发送每一帧的数据
|
||||
processCompletePayload.forEach((element) {
|
||||
talkData.content = element;
|
||||
talkDataRepository.addTalkData(talkData);
|
||||
// 设置状态为接听中
|
||||
talkStatus.setDuringCall();
|
||||
});
|
||||
}
|
||||
|
||||
/// 处理g711音频数据
|
||||
void _handleVideoG711(TalkData talkData) {}
|
||||
void _handleVideoG711(TalkData talkData) {
|
||||
try {
|
||||
final g711Data = talkData.content;
|
||||
// 转pcm数据
|
||||
List<int> pcmBytes = G711().convertList(g711Data);
|
||||
talkData.content = pcmBytes;
|
||||
talkDataRepository.addTalkData(talkData);
|
||||
// 设置状态为接听中
|
||||
talkStatus.setDuringCall();
|
||||
} catch (e) {
|
||||
print('Error decoding G.711 to PCM: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<Uint8List>> _processCompletePayload(Uint8List payload) async {
|
||||
// 存储找到的所有完整帧
|
||||
List<Uint8List> frames = [];
|
||||
|
||||
// 寻找完整帧 (0xFFD8 开始, 0xFFD9 结束)
|
||||
int startIdx = 0;
|
||||
while (startIdx < payload.length - 1) {
|
||||
// 找到帧的起始标志 0xFFD8
|
||||
startIdx = payload.indexOf(0xFF, startIdx);
|
||||
if (startIdx == -1 || startIdx + 1 >= payload.length) break;
|
||||
if (payload[startIdx + 1] == 0xD8) {
|
||||
// 找到帧的起始标志 0xFFD8
|
||||
int endIdx = startIdx + 2;
|
||||
while (endIdx < payload.length - 1) {
|
||||
endIdx = payload.indexOf(0xFF, endIdx);
|
||||
if (endIdx == -1 || endIdx + 1 >= payload.length) break;
|
||||
if (payload[endIdx + 1] == 0xD9) {
|
||||
// 找到帧的结束标志 0xFFD9
|
||||
Uint8List frame = payload.sublist(startIdx, endIdx + 2);
|
||||
frames.add(frame);
|
||||
startIdx = endIdx + 2; // 继续寻找下一个帧
|
||||
break;
|
||||
} else {
|
||||
endIdx += 1; // 继续寻找结束标志
|
||||
}
|
||||
}
|
||||
} else {
|
||||
startIdx += 1; // 继续寻找下一个起始标志
|
||||
}
|
||||
}
|
||||
|
||||
// 返回找到的所有完整帧
|
||||
return frames;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:star_lock/talk/startChart/constant/message_type_constant.dart';
|
||||
import 'package:star_lock/talk/startChart/entity/scp_message.dart';
|
||||
import 'package:star_lock/talk/startChart/handle/scp_message_base_handle.dart';
|
||||
import 'package:star_lock/talk/startChart/handle/scp_message_handle.dart';
|
||||
@ -18,7 +20,7 @@ class UdpTalkExpectHandler extends ScpMessageBaseHandle
|
||||
@override
|
||||
void handleReq(ScpMessage scpMessage) {
|
||||
// 收到预期音视频数据请求
|
||||
final TalkExpect talkExpect = scpMessage.Payload;
|
||||
final TalkExpectReq talkExpect = scpMessage.Payload;
|
||||
print('收到预期音视频数据请求:$talkExpect');
|
||||
|
||||
// 回复请求
|
||||
@ -42,4 +44,31 @@ class UdpTalkExpectHandler extends ScpMessageBaseHandle
|
||||
|
||||
@override
|
||||
void handleRealTimeData(ScpMessage scpMessage) {}
|
||||
|
||||
@override
|
||||
deserializePayload(
|
||||
{required int payloadType,
|
||||
required int messageType,
|
||||
required List<int> byte,
|
||||
int? offset,
|
||||
int? PayloadLength,
|
||||
int? spTotal,
|
||||
int? spIndex,
|
||||
int? messageId}) {
|
||||
if (messageType == MessageTypeConstant.Resp) {
|
||||
// final TalkExpectResp talkExpectResp = TalkExpectResp();
|
||||
// talkExpectResp.mergeFromBuffer(byte);
|
||||
// return talkExpectResp;
|
||||
final GenericResp genericResp = GenericResp();
|
||||
genericResp.mergeFromBuffer(byte);
|
||||
return genericResp;
|
||||
} else if (messageType == MessageTypeConstant.Req) {
|
||||
final TalkExpectReq talkExpect = TalkExpectReq();
|
||||
talkExpect.mergeFromBuffer(byte);
|
||||
return talkExpect;
|
||||
} else {
|
||||
String payload = utf8.decode(byte);
|
||||
return payload;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,14 @@
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:star_lock/talk/startChart/constant/message_type_constant.dart';
|
||||
import 'package:star_lock/talk/startChart/constant/talk_status.dart';
|
||||
import 'package:star_lock/talk/startChart/entity/scp_message.dart';
|
||||
import 'package:star_lock/talk/startChart/handle/scp_message_base_handle.dart';
|
||||
import 'package:star_lock/talk/startChart/handle/scp_message_handle.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/gateway_reset.pb.dart';
|
||||
|
||||
import 'package:star_lock/talk/startChart/proto/generic.pb.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/talk_hangup.pb.dart';
|
||||
|
||||
|
||||
import '../../start_chart_manage.dart';
|
||||
|
||||
@ -12,8 +16,10 @@ class UdpTalkHangUpHandler extends ScpMessageBaseHandle
|
||||
implements ScpMessageHandler {
|
||||
@override
|
||||
void handleReq(ScpMessage scpMessage) {
|
||||
// 通话中挂断请求
|
||||
print('收到通话中挂断请求');
|
||||
if (talkStatus.status != TalkStatus.duringCall) {
|
||||
// 如果不是接听中,不处理通话中挂断请求
|
||||
return;
|
||||
}
|
||||
startChartManage.sendGenericRespSuccessMessage(
|
||||
ToPeerId: scpMessage.FromPeerId!,
|
||||
FromPeerId: scpMessage.ToPeerId!,
|
||||
@ -23,28 +29,49 @@ class UdpTalkHangUpHandler extends ScpMessageBaseHandle
|
||||
startChartManage.stopTalkPingMessageTimer();
|
||||
startChartManage.stopTalkExpectMessageTimer();
|
||||
talkStatus.setHangingUpDuring();
|
||||
talkStatus.setEnd();
|
||||
stopRingtone();
|
||||
}
|
||||
|
||||
@override
|
||||
void handleResp(ScpMessage scpMessage) {
|
||||
print('收到通话中挂断回复');
|
||||
// 停止发送通话保持的命令
|
||||
startChartManage.stopTalkPingMessageTimer();
|
||||
startChartManage.stopTalkExpectMessageTimer();
|
||||
talkStatus.setHangingUpDuring();
|
||||
talkStatus.setEnd();
|
||||
stopRingtone();
|
||||
|
||||
// 拒绝接听之后,停止对讲请求超时监听定时器
|
||||
talkeRequestOverTimeTimerManager.receiveMessage();
|
||||
talkeRequestOverTimeTimerManager.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void handleInvalidReq(ScpMessage scpMessage) {
|
||||
|
||||
}
|
||||
void handleInvalidReq(ScpMessage scpMessage) {}
|
||||
|
||||
@override
|
||||
void handleRealTimeData(ScpMessage scpMessage) {
|
||||
void handleRealTimeData(ScpMessage scpMessage) {}
|
||||
|
||||
@override
|
||||
deserializePayload(
|
||||
{required int payloadType,
|
||||
required int messageType,
|
||||
required List<int> byte,
|
||||
int? offset,
|
||||
int? PayloadLength,
|
||||
int? spTotal,
|
||||
int? spIndex,
|
||||
int? messageId}) {
|
||||
if (messageType == MessageTypeConstant.Resp) {
|
||||
final GenericResp genericResp = GenericResp();
|
||||
genericResp.mergeFromBuffer(byte);
|
||||
return genericResp;
|
||||
} else if (messageType == MessageTypeConstant.RealTimeData) {
|
||||
final TalkHangup talkHangup = TalkHangup();
|
||||
talkHangup.mergeFromBuffer(byte);
|
||||
return talkHangup;
|
||||
} else {
|
||||
String payload = utf8.decode(byte);
|
||||
return payload;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,13 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:star_lock/talk/startChart/constant/message_type_constant.dart';
|
||||
import 'package:star_lock/talk/startChart/entity/scp_message.dart';
|
||||
import 'package:star_lock/talk/startChart/handle/scp_message_base_handle.dart';
|
||||
import 'package:star_lock/talk/startChart/handle/scp_message_handle.dart';
|
||||
|
||||
import 'package:star_lock/talk/startChart/proto/generic.pb.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/talk_ping.pb.dart';
|
||||
|
||||
class UdpTalkPingHandler extends ScpMessageBaseHandle
|
||||
implements ScpMessageHandler {
|
||||
@ -26,4 +31,28 @@ class UdpTalkPingHandler extends ScpMessageBaseHandle
|
||||
|
||||
@override
|
||||
void handleRealTimeData(ScpMessage scpMessage) {}
|
||||
|
||||
@override
|
||||
deserializePayload(
|
||||
{required int payloadType,
|
||||
required int messageType,
|
||||
required List<int> byte,
|
||||
int? offset,
|
||||
int? PayloadLength,
|
||||
int? spTotal,
|
||||
int? spIndex,
|
||||
int? messageId}) {
|
||||
if (messageType == MessageTypeConstant.Resp) {
|
||||
final GenericResp genericResp = GenericResp();
|
||||
genericResp.mergeFromBuffer(byte);
|
||||
return genericResp;
|
||||
} else if (messageType == MessageTypeConstant.Req) {
|
||||
final TalkPing talkPing = TalkPing();
|
||||
talkPing.mergeFromBuffer(byte);
|
||||
return talkPing;
|
||||
} else {
|
||||
String payload = utf8.decode(byte);
|
||||
return payload;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,15 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:star_lock/talk/startChart/constant/message_type_constant.dart';
|
||||
import 'package:star_lock/talk/startChart/entity/scp_message.dart';
|
||||
import 'package:star_lock/talk/startChart/handle/scp_message_base_handle.dart';
|
||||
import 'package:star_lock/talk/startChart/handle/scp_message_handle.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/gateway_reset.pb.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/generic.pb.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/talk_push.pb.dart';
|
||||
|
||||
import '../../start_chart_manage.dart';
|
||||
|
||||
@ -27,4 +32,28 @@ class UdpTalkPushHandler extends ScpMessageBaseHandle
|
||||
|
||||
@override
|
||||
void handleRealTimeData(ScpMessage scpMessage) {}
|
||||
|
||||
@override
|
||||
deserializePayload(
|
||||
{required int payloadType,
|
||||
required int messageType,
|
||||
required List<int> byte,
|
||||
int? offset,
|
||||
int? PayloadLength,
|
||||
int? spTotal,
|
||||
int? spIndex,
|
||||
int? messageId}) {
|
||||
if (messageType == MessageTypeConstant.Resp) {
|
||||
final GenericResp genericResp = GenericResp();
|
||||
genericResp.mergeFromBuffer(byte);
|
||||
return genericResp;
|
||||
} else if (messageType == MessageTypeConstant.Req) {
|
||||
final TalkPush talkPush = TalkPush();
|
||||
talkPush.mergeFromBuffer(byte);
|
||||
return talkPush;
|
||||
} else {
|
||||
String payload = utf8.decode(byte);
|
||||
return payload;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,17 +1,20 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:star_lock/talk/startChart/constant/message_type_constant.dart';
|
||||
import 'package:star_lock/talk/startChart/entity/scp_message.dart';
|
||||
import 'package:star_lock/talk/startChart/handle/scp_message_base_handle.dart';
|
||||
import 'package:star_lock/talk/startChart/handle/scp_message_handle.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/gateway_reset.pb.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/generic.pb.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/talk_receiver_transfer.pb.dart';
|
||||
|
||||
import '../../start_chart_manage.dart';
|
||||
|
||||
class UdpTalkReceiverTransferHandler extends ScpMessageBaseHandle
|
||||
implements ScpMessageHandler {
|
||||
|
||||
|
||||
@override
|
||||
void handleReq(ScpMessage scpMessage) {
|
||||
// TODO: 对讲接听者转移请求
|
||||
@ -23,12 +26,32 @@ class UdpTalkReceiverTransferHandler extends ScpMessageBaseHandle
|
||||
}
|
||||
|
||||
@override
|
||||
void handleInvalidReq(ScpMessage scpMessage) {
|
||||
|
||||
}
|
||||
void handleInvalidReq(ScpMessage scpMessage) {}
|
||||
|
||||
@override
|
||||
void handleRealTimeData(ScpMessage scpMessage) {
|
||||
void handleRealTimeData(ScpMessage scpMessage) {}
|
||||
|
||||
@override
|
||||
deserializePayload(
|
||||
{required int payloadType,
|
||||
required int messageType,
|
||||
required List<int> byte,
|
||||
int? offset,
|
||||
int? PayloadLength,
|
||||
int? spTotal,
|
||||
int? spIndex,
|
||||
int? messageId}) {
|
||||
if (messageType == MessageTypeConstant.Resp) {
|
||||
final GenericResp genericResp = GenericResp();
|
||||
genericResp.mergeFromBuffer(byte);
|
||||
return genericResp;
|
||||
} else if (messageType == MessageTypeConstant.Req) {
|
||||
final TalkReceiverTransfer talkReceiverTransfer = TalkReceiverTransfer();
|
||||
talkReceiverTransfer.mergeFromBuffer(byte);
|
||||
return talkReceiverTransfer;
|
||||
} else {
|
||||
String payload = utf8.decode(byte);
|
||||
return payload;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,15 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:star_lock/talk/startChart/constant/message_type_constant.dart';
|
||||
import 'package:star_lock/talk/startChart/entity/scp_message.dart';
|
||||
import 'package:star_lock/talk/startChart/handle/scp_message_base_handle.dart';
|
||||
import 'package:star_lock/talk/startChart/handle/scp_message_handle.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/gateway_reset.pb.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/generic.pb.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/talk_reject.pb.dart';
|
||||
|
||||
import '../../start_chart_manage.dart';
|
||||
|
||||
@ -13,35 +18,54 @@ class UdpTalkRejectHandler extends ScpMessageBaseHandle
|
||||
@override
|
||||
void handleReq(ScpMessage scpMessage) {
|
||||
// 收到接听拒绝请求
|
||||
startChartManage.sendGenericRespSuccessMessage(
|
||||
ToPeerId: scpMessage.FromPeerId!,
|
||||
FromPeerId: scpMessage.ToPeerId!,
|
||||
PayloadType: scpMessage.PayloadType!,
|
||||
);
|
||||
startChartManage.stopTalkPingMessageTimer();
|
||||
startChartManage.stopTalkExpectMessageTimer();
|
||||
talkStatus.setRejected();
|
||||
// 回复成功消息
|
||||
replySuccessMessage(scpMessage);
|
||||
// 停止铃声
|
||||
stopRingtone();
|
||||
talkStatus.setEnd();
|
||||
// 收到接听拒绝回复
|
||||
talkStatus.setRejected();
|
||||
|
||||
}
|
||||
|
||||
@override
|
||||
void handleResp(ScpMessage scpMessage) {
|
||||
// 收到接听拒绝回复
|
||||
talkStatus.setRejected();
|
||||
startChartManage.stopTalkPingMessageTimer();
|
||||
startChartManage.stopTalkExpectMessageTimer();
|
||||
stopRingtone();
|
||||
talkStatus.setEnd();
|
||||
|
||||
|
||||
// 拒绝接听之后,停止对讲请求超时监听定时器
|
||||
talkeRequestOverTimeTimerManager.receiveMessage();
|
||||
talkeRequestOverTimeTimerManager.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void handleInvalidReq(ScpMessage scpMessage) {
|
||||
|
||||
}
|
||||
void handleInvalidReq(ScpMessage scpMessage) {}
|
||||
|
||||
@override
|
||||
void handleRealTimeData(ScpMessage scpMessage) {
|
||||
void handleRealTimeData(ScpMessage scpMessage) {}
|
||||
|
||||
@override
|
||||
deserializePayload(
|
||||
{required int payloadType,
|
||||
required int messageType,
|
||||
required List<int> byte,
|
||||
int? offset,
|
||||
int? PayloadLength,
|
||||
int? spTotal,
|
||||
int? spIndex,
|
||||
int? messageId}) {
|
||||
if (messageType == MessageTypeConstant.Resp) {
|
||||
final GenericResp genericResp = GenericResp();
|
||||
genericResp.mergeFromBuffer(byte);
|
||||
return genericResp;
|
||||
} else if (messageType == MessageTypeConstant.Req) {
|
||||
final TalkReject talkReject = TalkReject();
|
||||
talkReject.mergeFromBuffer(byte);
|
||||
return talkReject;
|
||||
} else {
|
||||
String payload = utf8.decode(byte);
|
||||
return payload;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,22 +1,27 @@
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:star_lock/appRouters.dart';
|
||||
import 'package:star_lock/talk/startChart/constant/message_type_constant.dart';
|
||||
import 'package:star_lock/talk/startChart/constant/talk_status.dart';
|
||||
import 'package:star_lock/talk/startChart/entity/scp_message.dart';
|
||||
import 'package:star_lock/talk/startChart/handle/scp_message_base_handle.dart';
|
||||
import 'package:star_lock/talk/startChart/handle/scp_message_handle.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/gateway_reset.pb.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/generic.pb.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/talk_request.pb.dart';
|
||||
import 'package:star_lock/tools/storage.dart';
|
||||
|
||||
import '../../start_chart_manage.dart';
|
||||
|
||||
class UdpTalkRequestHandler extends ScpMessageBaseHandle
|
||||
implements ScpMessageHandler {
|
||||
@override
|
||||
void handleReq(ScpMessage scpMessage) {
|
||||
if (talkStatus == TalkStatus.waitingAnswer) {
|
||||
// 如果已经是等待接听了,就不在处理剩下的请求
|
||||
return;
|
||||
}
|
||||
// 收到对讲请求
|
||||
final TalkReq talkReq = scpMessage.Payload;
|
||||
// 回复收到对讲成功的消息
|
||||
@ -29,6 +34,16 @@ class UdpTalkRequestHandler extends ScpMessageBaseHandle
|
||||
startChartManage.ToPeerId = scpMessage.FromPeerId!;
|
||||
// 处理收到接听请求后的事件
|
||||
_talkRequestEvent(talkObjectName: talkReq.callerName);
|
||||
|
||||
// 启动对讲请求超时定时器
|
||||
talkeRequestOverTimeTimerManager.startTimer();
|
||||
talkeRequestOverTimeTimerManager.setOnTimeout(() {
|
||||
if (talkStatus.status == TalkStatus.waitingAnswer) {
|
||||
// 超时未接听,发送挂断请求
|
||||
startChartManage.sendTalkRejectMessage();
|
||||
Get.back();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
@ -52,9 +67,12 @@ class UdpTalkRequestHandler extends ScpMessageBaseHandle
|
||||
_showTalkRequestNotification(talkObjectName: talkObjectName);
|
||||
// 收到呼叫请求,跳转到接听页面
|
||||
Get.toNamed(
|
||||
Routers.starChartPage,
|
||||
arguments: <String, String>{'lockId': '111'},
|
||||
Routers.starChartTalkView,
|
||||
);
|
||||
// 触发震动反馈
|
||||
HapticFeedback.vibrate();
|
||||
// 设置为等待接听状态
|
||||
talkStatus.setWaitingAnswer();
|
||||
}
|
||||
|
||||
// 收到来电请求时进行本地通知
|
||||
@ -77,4 +95,28 @@ class UdpTalkRequestHandler extends ScpMessageBaseHandle
|
||||
'${'收到来自'.tr}($talkObjectName)${'锁的呼叫'.tr}。', platformChannelSpecifics,
|
||||
payload: 'item x');
|
||||
}
|
||||
|
||||
@override
|
||||
deserializePayload(
|
||||
{required int payloadType,
|
||||
required int messageType,
|
||||
required List<int> byte,
|
||||
int? offset,
|
||||
int? PayloadLength,
|
||||
int? spTotal,
|
||||
int? spIndex,
|
||||
int? messageId}) {
|
||||
if (messageType == MessageTypeConstant.Resp) {
|
||||
final GenericResp genericResp = GenericResp();
|
||||
genericResp.mergeFromBuffer(byte);
|
||||
return genericResp;
|
||||
} else if (messageType == MessageTypeConstant.Req) {
|
||||
final TalkReq talkReq = TalkReq();
|
||||
talkReq.mergeFromBuffer(byte);
|
||||
return talkReq;
|
||||
} else {
|
||||
String payload = utf8.decode(byte);
|
||||
return payload;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:star_lock/app_settings/app_settings.dart';
|
||||
import 'package:star_lock/talk/startChart/entity/scp_message.dart';
|
||||
import 'package:star_lock/talk/startChart/handle/scp_message_base_handle.dart';
|
||||
@ -27,4 +29,17 @@ class UnKnowPayloadTypeHandler extends ScpMessageBaseHandle
|
||||
void handleRealTimeData(ScpMessage scpMessage) {
|
||||
AppLog.log('❌未知的payloadType类型---》${scpMessage}');
|
||||
}
|
||||
|
||||
@override
|
||||
deserializePayload(
|
||||
{required int payloadType,
|
||||
required int messageType,
|
||||
required List<int> byte,
|
||||
int? offset,
|
||||
int? PayloadLength,
|
||||
int? spTotal,
|
||||
int? spIndex,
|
||||
int? messageId}) {
|
||||
AppLog.log('❌未知的payloadType类型---》');
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,9 +12,6 @@ class OverTimeTimerManager {
|
||||
// 超时时间(以秒为单位),是 final 的,因此必须在构造函数中初始化
|
||||
final int timeoutInSeconds;
|
||||
|
||||
// 默认超时时间(以秒为单位)
|
||||
static const int defaultTimeoutInSeconds = 5;
|
||||
|
||||
// 超时回调函数
|
||||
TimeoutCallback? _onTimeout;
|
||||
|
||||
@ -24,7 +21,7 @@ class OverTimeTimerManager {
|
||||
_timer = Timer(Duration(seconds: timeoutInSeconds), () {
|
||||
// 超时回调方法
|
||||
_onTimeout?.call();
|
||||
// 清楚定时器
|
||||
// 清除定时器
|
||||
_cancelTimer();
|
||||
});
|
||||
}
|
||||
|
||||
@ -19,7 +19,7 @@ class TalkDataRepository {
|
||||
Stream<TalkData> get talkDataStream => _talkDataStreamController.stream;
|
||||
|
||||
// 提供一个方法来添加 TalkData 到 Stream
|
||||
void addTalkData(TalkData talkData) {
|
||||
void addTalkData(TalkData talkData) async {
|
||||
_talkDataStreamController.add(talkData);
|
||||
}
|
||||
|
||||
|
||||
@ -1,37 +1,58 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:audioplayers/audioplayers.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
|
||||
import 'package:star_lock/app_settings/app_settings.dart';
|
||||
import 'package:star_lock/talk/other/audio_player_manager.dart';
|
||||
import 'package:star_lock/talk/startChart/constant/payload_type_constant.dart';
|
||||
import 'package:star_lock/talk/startChart/constant/udp_constant.dart';
|
||||
import 'package:star_lock/talk/startChart/entity/scp_message.dart';
|
||||
import 'package:star_lock/talk/startChart/handle/other/overtime_timer_manger.dart';
|
||||
import 'package:star_lock/talk/startChart/handle/other/talk_data_repository.dart';
|
||||
|
||||
import 'package:star_lock/talk/startChart/proto/generic.pb.dart';
|
||||
import 'package:star_lock/talk/startChart/proto/talk_data.pb.dart';
|
||||
import 'package:star_lock/talk/startChart/start_chart_manage.dart';
|
||||
import 'package:star_lock/talk/startChart/start_chart_talk_status.dart';
|
||||
|
||||
class ScpMessageBaseHandle {
|
||||
final startChartManage = StartChartManage();
|
||||
final List<int> _buffer = [];
|
||||
|
||||
/// 分包缓冲区
|
||||
// 存储每个 messageId 对应的分包数据
|
||||
static Map<String, List<List<int>>> _packetBuffer = {};
|
||||
final Map<String, Timer> _packetTimers = {};
|
||||
final Duration _timeoutDuration = Duration(seconds: 10); // 分包组包最大超时时间
|
||||
|
||||
// 通话数据流的单例流数据处理类
|
||||
final TalkDataRepository talkDataRepository = TalkDataRepository.instance;
|
||||
|
||||
// 获取 StartChartTalkStatus 的唯一实例
|
||||
final StartChartTalkStatus talkStatus = StartChartTalkStatus.instance;
|
||||
|
||||
final audioManager = AudioPlayerManager();
|
||||
|
||||
// 通话请求超时未处理监听定时器管理
|
||||
final talkeRequestOverTimeTimerManager = OverTimeTimerManager(
|
||||
timeoutInSeconds: 30,
|
||||
);
|
||||
|
||||
// 通话保持超时监听定时器管理
|
||||
final talkePingOverTimeTimerManager = OverTimeTimerManager(
|
||||
timeoutInSeconds: 5,
|
||||
timeoutInSeconds: 260,
|
||||
);
|
||||
|
||||
// 通话数据超时定时器
|
||||
final talkDataOverTimeTimerManager = OverTimeTimerManager(
|
||||
timeoutInSeconds: 3,
|
||||
timeoutInSeconds: 260,
|
||||
);
|
||||
|
||||
// 回复成功消息
|
||||
void replySuccessMessage(ScpMessage scpMessage){
|
||||
void replySuccessMessage(ScpMessage scpMessage) {
|
||||
startChartManage.sendGenericRespSuccessMessage(
|
||||
ToPeerId: scpMessage.FromPeerId!,
|
||||
FromPeerId: scpMessage.ToPeerId!,
|
||||
@ -39,9 +60,6 @@ class ScpMessageBaseHandle {
|
||||
);
|
||||
}
|
||||
|
||||
// 获取 StartChartTalkStatus 的唯一实例
|
||||
StartChartTalkStatus talkStatus = StartChartTalkStatus.instance;
|
||||
|
||||
bool checkGenericRespSuccess(GenericResp genericResp) {
|
||||
if (genericResp == null) return false;
|
||||
final code = genericResp.code;
|
||||
@ -63,4 +81,64 @@ class ScpMessageBaseHandle {
|
||||
void stopRingtone() async {
|
||||
await audioManager.stopRingtone();
|
||||
}
|
||||
|
||||
/// 处理分包逻辑
|
||||
/// 如果没有收到所有包则返回null
|
||||
dynamic handleFragmentedPayload({
|
||||
required int messageId,
|
||||
required int spTotal,
|
||||
required int spIndex,
|
||||
required List<int> byte,
|
||||
required int payloadType,
|
||||
}) {
|
||||
// 初始化分包列表
|
||||
String key = '$messageId-$payloadType';
|
||||
if (!_packetBuffer.containsKey(key)) {
|
||||
_packetBuffer[key] = List.filled(spTotal, []);
|
||||
_startTimer(key);
|
||||
}
|
||||
|
||||
// 检查分包索引是否在合法范围内
|
||||
if (spIndex < 1 || spIndex > spTotal) {
|
||||
// print(
|
||||
// 'Invalid spTotal: $spTotal spIndex: $spIndex for messageId: $messageId');
|
||||
return null;
|
||||
}
|
||||
|
||||
// 存储当前分包
|
||||
_packetBuffer[key]![spIndex - 1] = byte;
|
||||
|
||||
// 检查是否接收到所有分包
|
||||
if (_packetBuffer[key]!.every((packet) => packet.isNotEmpty)) {
|
||||
// 重组所有分包
|
||||
Uint8List completePayload = Uint8List.fromList(
|
||||
_packetBuffer[key]!.expand((packet) => packet).toList());
|
||||
// 清除已重组和超时的分包数据
|
||||
_clearPacketData(key);
|
||||
|
||||
// 使用重组的包构造成TalkData
|
||||
if (payloadType == PayloadTypeConstant.talkData) {
|
||||
final talkData = TalkData();
|
||||
talkData.mergeFromBuffer(completePayload);
|
||||
return talkData;
|
||||
}
|
||||
} else {
|
||||
// 如果分包尚未接收完全,返回 null 或其他指示符
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 启动定时器
|
||||
void _startTimer(String key) {
|
||||
_packetTimers[key]?.cancel();
|
||||
_packetTimers[key] = Timer(_timeoutDuration, () {
|
||||
_clearPacketData(key);
|
||||
});
|
||||
}
|
||||
|
||||
// 清除分包数据和定时器
|
||||
void _clearPacketData(String key) {
|
||||
_packetBuffer.remove(key);
|
||||
_packetTimers.remove(key)?.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:star_lock/talk/startChart/entity/scp_message.dart';
|
||||
|
||||
abstract class ScpMessageHandler {
|
||||
@ -12,4 +14,16 @@ abstract class ScpMessageHandler {
|
||||
|
||||
// 无效请求
|
||||
void handleInvalidReq(ScpMessage scpMessage);
|
||||
|
||||
// 处理荷载
|
||||
dynamic deserializePayload({
|
||||
required int payloadType,
|
||||
required int messageType,
|
||||
required List<int> byte,
|
||||
int? offset,
|
||||
int? PayloadLength,
|
||||
int? spTotal,
|
||||
int? spIndex,
|
||||
int? messageId,
|
||||
});
|
||||
}
|
||||
|
||||
@ -17,12 +17,13 @@ import 'talk_data.pbenum.dart';
|
||||
|
||||
export 'talk_data.pbenum.dart';
|
||||
|
||||
/// 注意这个包不应该使用Req,而应该只用单向发送类型,不等待响应。
|
||||
/// 注意这个包不应该使用请求响应(Req/Resp),应该用单向发送类型(RealTimeData),不等待响应。
|
||||
/// 在未收到对方的Ping,或者其他情况,即停止发送。
|
||||
class TalkData extends $pb.GeneratedMessage {
|
||||
factory TalkData({
|
||||
TalkData_ContentTypeE? contentType,
|
||||
$core.List<$core.int>? content,
|
||||
$core.int? durationMs,
|
||||
}) {
|
||||
final $result = create();
|
||||
if (contentType != null) {
|
||||
@ -31,6 +32,9 @@ class TalkData extends $pb.GeneratedMessage {
|
||||
if (content != null) {
|
||||
$result.content = content;
|
||||
}
|
||||
if (durationMs != null) {
|
||||
$result.durationMs = durationMs;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
TalkData._() : super();
|
||||
@ -40,6 +44,7 @@ class TalkData extends $pb.GeneratedMessage {
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'TalkData', package: const $pb.PackageName(_omitMessageNames ? '' : 'main'), createEmptyInstance: create)
|
||||
..e<TalkData_ContentTypeE>(1, _omitFieldNames ? '' : 'ContentType', $pb.PbFieldType.OE, protoName: 'ContentType', defaultOrMaker: TalkData_ContentTypeE.Image, valueOf: TalkData_ContentTypeE.valueOf, enumValues: TalkData_ContentTypeE.values)
|
||||
..a<$core.List<$core.int>>(2, _omitFieldNames ? '' : 'Content', $pb.PbFieldType.OY, protoName: 'Content')
|
||||
..a<$core.int>(3, _omitFieldNames ? '' : 'DurationMs', $pb.PbFieldType.OU3, protoName: 'DurationMs')
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
@ -73,6 +78,7 @@ class TalkData extends $pb.GeneratedMessage {
|
||||
@$pb.TagNumber(1)
|
||||
void clearContentType() => clearField(1);
|
||||
|
||||
/// 音视频数据,例如PCM的字节,或者H264的字节,或者图片的字节
|
||||
@$pb.TagNumber(2)
|
||||
$core.List<$core.int> get content => $_getN(1);
|
||||
@$pb.TagNumber(2)
|
||||
@ -81,6 +87,18 @@ class TalkData extends $pb.GeneratedMessage {
|
||||
$core.bool hasContent() => $_has(1);
|
||||
@$pb.TagNumber(2)
|
||||
void clearContent() => clearField(2);
|
||||
|
||||
/// 时间 毫秒,例如第一帧视频,就是0ms,第2秒的第一帧,就是1000ms
|
||||
/// 该字段仅用于协调音视频同步,而不是用于影响音视频播放时机
|
||||
/// 对于对讲场景,应该根据网络延迟和设备性能自行决定缓冲时长,在满足播放条件时立即进行渲染。
|
||||
@$pb.TagNumber(3)
|
||||
$core.int get durationMs => $_getIZ(2);
|
||||
@$pb.TagNumber(3)
|
||||
set durationMs($core.int v) { $_setUnsignedInt32(2, v); }
|
||||
@$pb.TagNumber(3)
|
||||
$core.bool hasDurationMs() => $_has(2);
|
||||
@$pb.TagNumber(3)
|
||||
void clearDurationMs() => clearField(3);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user