diff --git a/example/integration_test/plugin_integration_test.dart b/example/integration_test/plugin_integration_test.dart index 233b8c9..0533ab9 100644 --- a/example/integration_test/plugin_integration_test.dart +++ b/example/integration_test/plugin_integration_test.dart @@ -10,7 +10,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; -import 'package:jc_printer/jc_printer.dart'; +// import 'package:jc_printer/jc_printer.dart'; void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); diff --git a/example/ios/Podfile b/example/ios/Podfile index ec43b51..136628e 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -28,6 +28,8 @@ require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelpe flutter_ios_podfile_setup target 'Runner' do + use_modular_headers! + use_frameworks! flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) target 'RunnerTests' do inherit! :search_paths diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 621a9e6..4a44d88 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -4,11 +4,23 @@ PODS: - Flutter - jc_printer (0.0.1): - Flutter + - Protobuf (3.24.4) + - reactive_ble_mobile (0.0.1): + - Flutter + - Protobuf (~> 3.5) + - SwiftProtobuf (~> 1.0) + - SwiftProtobuf (1.24.0) DEPENDENCIES: - Flutter (from `Flutter`) - integration_test (from `.symlinks/plugins/integration_test/ios`) - jc_printer (from `.symlinks/plugins/jc_printer/ios`) + - reactive_ble_mobile (from `.symlinks/plugins/reactive_ble_mobile/ios`) + +SPEC REPOS: + trunk: + - Protobuf + - SwiftProtobuf EXTERNAL SOURCES: Flutter: @@ -17,12 +29,17 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/integration_test/ios" jc_printer: :path: ".symlinks/plugins/jc_printer/ios" + reactive_ble_mobile: + :path: ".symlinks/plugins/reactive_ble_mobile/ios" SPEC CHECKSUMS: Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 integration_test: 13825b8a9334a850581300559b8839134b124670 jc_printer: 98d27e989a3129f784669a21dd5883eec26ba102 + Protobuf: 351e9022fe13a6e2af00e9aefc22077cb88520f8 + reactive_ble_mobile: 9ce6723d37ccf701dbffd202d487f23f5de03b4c + SwiftProtobuf: bcfd2bc231cf9ae552cdc7c4e877bd3b41fe57b1 -PODFILE CHECKSUM: 02caaa843f6501172c0d470d80e72f61175c8b93 +PODFILE CHECKSUM: b93a2ec14f1c13812166ff9c14f4914d6c6e5d23 COCOAPODS: 1.13.0 diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index bf3b5bc..18d190a 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -7,16 +7,18 @@ objects = { /* Begin PBXBuildFile section */ - 10D5D5F3CC5D3E87F4AAF20E /* libPods-RunnerTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A8187878D1E2CD429B7D166B /* libPods-RunnerTests.a */; }; 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 17F38D4D2AE51FBB00487369 /* JCSDKFont.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 17F38D4C2AE51FBB00487369 /* JCSDKFont.bundle */; }; + 17F38D4F2AE51FD700487369 /* SourceHanSans-Regular.ttc in Resources */ = {isa = PBXBuildFile; fileRef = 17F38D4E2AE51FD700487369 /* SourceHanSans-Regular.ttc */; }; 331C80F4294D02FB00263BE5 /* RunnerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 331C80F3294D02FB00263BE5 /* RunnerTests.m */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 729636EF36A53C120B8F72EE /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC47687E2219A68A71BCD69C /* Pods_RunnerTests.framework */; }; 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; - D72C0DE9E160819031C5E3E4 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F40EEDC1B3DAB75AD1218FEF /* libPods-Runner.a */; }; + C14833107E81995AF9AE3F8F /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD3314FB6F05D6F16AC71377 /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -45,6 +47,8 @@ /* Begin PBXFileReference section */ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 17F38D4C2AE51FBB00487369 /* JCSDKFont.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = JCSDKFont.bundle; sourceTree = ""; }; + 17F38D4E2AE51FD700487369 /* SourceHanSans-Regular.ttc */ = {isa = PBXFileReference; lastKnownFileType = file; name = "SourceHanSans-Regular.ttc"; path = "Runner/JCSDKFont.bundle/SourceHanSans-Regular.ttc"; sourceTree = ""; }; 331C80F1294D02FB00263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 331C80F3294D02FB00263BE5 /* RunnerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RunnerTests.m; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; @@ -62,10 +66,10 @@ 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; A47E728957F5618558E7C7DF /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; - A8187878D1E2CD429B7D166B /* libPods-RunnerTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RunnerTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; AC93C0AD3746E8534100DB47 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; B35671E4ABF84AEDC8C673D9 /* 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 = ""; }; - F40EEDC1B3DAB75AD1218FEF /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + CD3314FB6F05D6F16AC71377 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + EC47687E2219A68A71BCD69C /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; FEEEE64755D6E7811332A20C /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -74,7 +78,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 10D5D5F3CC5D3E87F4AAF20E /* libPods-RunnerTests.a in Frameworks */, + 729636EF36A53C120B8F72EE /* Pods_RunnerTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -82,7 +86,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - D72C0DE9E160819031C5E3E4 /* libPods-Runner.a in Frameworks */, + C14833107E81995AF9AE3F8F /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -113,8 +117,8 @@ 5B206BD512BCA9AC88115CF7 /* Frameworks */ = { isa = PBXGroup; children = ( - F40EEDC1B3DAB75AD1218FEF /* libPods-Runner.a */, - A8187878D1E2CD429B7D166B /* libPods-RunnerTests.a */, + CD3314FB6F05D6F16AC71377 /* Pods_Runner.framework */, + EC47687E2219A68A71BCD69C /* Pods_RunnerTests.framework */, ); name = Frameworks; sourceTree = ""; @@ -133,6 +137,7 @@ 97C146E51CF9000F007C117D = { isa = PBXGroup; children = ( + 17F38D4E2AE51FD700487369 /* SourceHanSans-Regular.ttc */, 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, 331C80F2294D02FB00263BE5 /* RunnerTests */, @@ -154,6 +159,7 @@ 97C146F01CF9000F007C117D /* Runner */ = { isa = PBXGroup; children = ( + 17F38D4C2AE51FBB00487369 /* JCSDKFont.bundle */, 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */, 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */, 97C146FA1CF9000F007C117D /* Main.storyboard */, @@ -208,7 +214,7 @@ 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - 20F8517985BB5619A77F396B /* [CP] Embed Pods Frameworks */, + E66D16C1F41008EA24F48C2D /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -271,6 +277,8 @@ files = ( 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 17F38D4D2AE51FBB00487369 /* JCSDKFont.bundle in Resources */, + 17F38D4F2AE51FD700487369 /* SourceHanSans-Regular.ttc in Resources */, 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, ); @@ -301,23 +309,6 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 20F8517985BB5619A77F396B /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -371,6 +362,23 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; + E66D16C1F41008EA24F48C2D /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ diff --git a/example/ios/Runner/JCSDKFont.bundle/Info.plist b/example/ios/Runner/JCSDKFont.bundle/Info.plist new file mode 100644 index 0000000..7644aea Binary files /dev/null and b/example/ios/Runner/JCSDKFont.bundle/Info.plist differ diff --git a/example/ios/Runner/JCSDKFont.bundle/SourceHanSans-Regular.ttc b/example/ios/Runner/JCSDKFont.bundle/SourceHanSans-Regular.ttc new file mode 100644 index 0000000..cf5efd6 Binary files /dev/null and b/example/ios/Runner/JCSDKFont.bundle/SourceHanSans-Regular.ttc differ diff --git a/example/ios/Runner/JCSDKFont.bundle/language.json b/example/ios/Runner/JCSDKFont.bundle/language.json new file mode 100644 index 0000000..a911f5b --- /dev/null +++ b/example/ios/Runner/JCSDKFont.bundle/language.json @@ -0,0 +1,369 @@ +{ + "0020-007F": { + "description":"Basic_Latin", + "fontFile":"NotoSansCJK-Regular.ttc" + }, + "00A0-00FF":{ + "description":"Latin-1_Supplement", + "fontFile":"NotoSansCJK-Regular.ttc" + }, + "0100-017F":{ + "description":"Latin Extended-A", + "fontFile":"NotoSansCJK-Regular.ttc" + }, + "0370-03FF": { + "description":"Greek and Coptic", + "fontFile":"" + }, + "10A0-10FF": { + "description":"Georgian", + "fontFile":"NotoSansGeorgian-Regular.otf" + }, + "0400-04FF": { + "description":"Cyrillic", + "fontFile":"NotoSansCJK-Regular.ttc" + }, + "0500-052F": { + "description":"Cyrillic Supplementary", + "fontFile":"NotoSansCJK-Regular.ttc" + }, + "0530-058F": { + "description":"Armenian", + "fontFile":"NotoSansArmenian-Regular.otf" + }, + "0590-05FF":{ + "description":"Hebrew", + "fontFile":"NotoSansHebrew-Regular.ttf" + }, + "0600-06FF":{ + "description":"Arabic", + "fontFile":"NotoNaskhArabic-Regular.ttf" + }, + "0700-074F":{ + "description":"Syriac", + "fontFile":"NotoSansSyriacEstrangela-Regular.ttf" + }, + "0780-07BF":{ + "description":"Thaana", + "fontFile":"NotoSansThaana-Regular.ttf" + }, + "0900-097F":{ + "description":"Devanagari", + "fontFile":"NotoSansDevanagari-Regular.otf" + }, + "0980-09FF":{ + "description":"Bengali", + "fontFile":"NotoSansBengali-Regular.otf" + }, + "0A00-0A7F":{ + "description":"Gurmukhi", + "fontFile":"NotoSansGurmukhi-Regular.ttf" + }, + "0B00-0B7F":{ + "description":"Oriya", + "fontFile":"NotoSansOriya-Regular.ttf" + }, + "0B80-0BFF":{ + "description":"Tamil", + "fontFile":"NotoSansTamil-Regular.otf" + }, + "0C00-0C7F":{ + "description":"Telugu", + "fontFile":"NotoSansTelugu-Regular.ttf" + }, + "0C80-0CFF":{ + "description":"Kannada", + "fontFile":"NotoSansKannada-Regular.ttf" + }, + "0D00-0D7F":{ + "description":"Malayalam", + "fontFile":"NotoSansMalayalam-Regular.otf" + }, + "0D80-0DFF":{ + "description":"Sinhala", + "fontFile":"NotoSansSinhala-Regular.otf" + }, + "0E00-0E7F":{ + "description":"Thai", + "fontFile":"NotoSansThai-Regular.ttf" + }, + "0E80-0EFF":{ + "description":"Lao", + "fontFile":"NotoSansLao-Regular.ttf" + }, + "0F00-0FFF":{ + "description":"Tibetan", + "fontFile":"NotoSansTibetan-Regular.ttf" + }, + "1000-109F":{ + "description":"Myanmar", + "fontFile":"NotoSansMyanmar-Regular-ZawDecode.ttf" + }, + "10000-1007F":{ + "description":"Linear B Syllabary", + "fontFile":"NotoSansLinearB-Regular.ttf" + }, + "10080-100FF":{ + "description":"Linear B Ideograms", + "fontFile":"NotoSansLinearB-Regular.ttf" + }, + "10380-1039F":{ + "description":"Ugaritic", + "fontFile":"NotoSansUgaritic-Regular.ttf" + }, + "10450-1047F":{ + "description":"Shavian", + "fontFile":"NotoSansShavian-Regular.ttf" + }, + "10400-1044F":{ + "description":"Deseret", + "fontFile":"NotoSansDeseret-Regular.ttf" + }, + "10480-104AF":{ + "description":"Osmanya", + "fontFile":"NotoSansOsmanya-Regular.ttf" + }, + "10800-1083F":{ + "description":"Cypriot ", + "fontFile":"NotoSansCypriot-Regular.ttf" + }, + "1200-137F":{ + "description":"Ethiopic", + "fontFile":"NotoSansEthiopic-Regular.ttf" + }, + "13A0-13FF":{ + "description":"Cherokee", + "fontFile":"NotoSansCherokee-Regular.ttf" + }, + "1400-167F":{ + "description":"Unified Canadian Aboriginal Syllabics", + "fontFile":"NotoSansCanadianAboriginal-Regular.ttf" + }, + "1680-169F":{ + "description":"Ogham", + "fontFile":"NotoSansOgham-Regular.ttf" + }, + "16A0-16FF":{ + "description":"Runic", + "fontFile":"NotoSansRunic-Regular.ttf" + }, + "1700-171F":{ + "description":"Tagalog", + "fontFile":"NotoSansTagalog-Regular.ttf" + }, + "1720-173F":{ + "description":"Hanunoo", + "fontFile":"NotoSansHanunoo-Regular.ttf" + }, + "1740-175F":{ + "description":"Buhid", + "fontFile":"NotoSansBuhid-Regular.ttf" + }, + "1760-177F":{ + "description":"Tagbanwa", + "fontFile":"NotoSansTagbanwa-Regular.ttf" + }, + "1780-17FF":{ + "description":"Khmer", + "fontFile":"NotoSansKhmer-VF.ttf" + }, + "1800-18AF":{ + "description":"Mongolian", + "fontFile":"NotoSansMongolian-Regular.ttf" + }, + "1900-194F":{ + "description":"Limbu", + "fontFile":"NotoSansLimbu-Regular.ttf" + }, + "1950-197F":{ + "description":"Tai Le", + "fontFile":"NotoSansTaiLe-Regular.ttf" + }, + "19E0-19FF":{ + "description":"Khmer Symbols", + "fontFile":"NotoSansKhmer-VF.ttf" + }, + "1D000-1D0FF":{ + "description":"Byzantine Musical Symbols", + "fontFile":"NotoSansSymbols-Regular-Subsetted.ttf" + }, + "1D300-1D35F@Tai Xuan Jing Symbols":{ + "description":"Tai Xuan Jing Symbols", + "fontFile":"NotoSansTaiLe-Regular.ttf" + }, + "1E00-1EFF":{ + "description":"Latin Extended Additional", + "fontFile":"NotoSansTaiLe-Regular.ttf" + }, + "1F00-1FFF":{ + "description":"Greek Extended", + "fontFile":"NotoSansSylotiNagri-Regular.ttf" + }, + "2000-206F":{ + "description":"General Punctuation", + "fontFile":"NotoSansTaiLe-Regular.ttf" + }, + "20000-2A6DF":{ + "description":"CJK", + "fontFile":"NotoSansCJK-Regular.ttc" + }, + "20A0-20CF":{ + "description":"Currency Symbols", + "fontFile":"NotoSansSymbols-Regular-Subsetted2.ttf" + }, + "20D0-20FF":{ + "description":"Combining Diacritical Marks for Symbols", + "fontFile":"NotoSansSymbols-Regular-Subsetted2.ttf" + }, + "2100-214F":{ + "description":"Letterlike Symbols", + "fontFile":"NotoSansSymbols-Regular-Subsetted.ttf" + }, + "2200-22FF":{ + "description":"Tai Le", + "fontFile":"NotoSansSymbols-Regular-Subsetted.ttf" + }, + "2300-23FF":{ + "description":"Miscellaneous Technical", + "fontFile":"NotoSansSymbols-Regular-Subsetted.ttf" + }, + "2400-243F":{ + "description":"Control Pictures", + "fontFile":"NotoSansTaiLe-Regular.ttf" + }, + "2440-245F":{ + "description":"Optical Character Recognition", + "fontFile":"NotoSansGujarati-Regular.ttf" + }, + "2460-24FF":{ + "description":"Enclosed Alphanumerics", + "fontFile":"NotoSansGujarati-Regular.ttf" + }, + "2500-257F":{ + "description":"Box Drawing", + "fontFile":"NotoSansGujarati-Regular.ttf" + }, + "2580-259F":{ + "description":"Block Elements", + "fontFile":"NotoSansTaiLe-Regular.ttf" + }, + "25A0-25FF":{ + "description":"Geometric Shapes", + "fontFile":"NotoSansTaiLe-Regular.ttf" + }, + "2600-26FF":{ + "description":"Miscellaneous Symbols", + "fontFile":"NotoSansSymbols-Regular-Subsetted.ttf" + }, + "2700-27BF":{ + "description":"Dingbats", + "fontFile":"NotoSansTaiLe-Regular.ttf" + }, + "27C0-27EF":{ + "description":"@Miscellaneous Mathematical Symbols-A", + "fontFile":"NotoSansSymbols-Regular-Subsetted.ttf" + }, + "27F0-27FF":{ + "description":"@Supplemental Arrows-A", + "fontFile":"NotoSansCJK-Regular.ttc" + }, + "2800-28FF":{ + "description":"Braille Patterns", + "fontFile":"NotoSansCJK-Regular.ttc" + }, + "2900-297F":{ + "description":"@Supplemental Arrows-B", + "fontFile":"NotoSansCJK-Regular.ttc" + }, + "2980-29FF":{ + "description":"Miscellaneous Mathematical Symbols-B", + "fontFile":"NotoSansSymbols-Regular-Subsetted2.ttf" + }, + "2A00-2AFF":{ + "description":"@Supplemental Mathematical Operators", + "fontFile":"NotoSansCJK-Regular.ttc" + }, + "2B00-2BFF":{ + "description":"@Miscellaneous Symbols and Arrows", + "fontFile":"NotoSansCJK-Regular.ttc" + }, + "2E80-2EFF":{ + "description":"CJK Radicals Supplement", + "fontFile":"NotoSansCJK-Regular.ttc" + }, + "2F800-2FA1F":{ + "description":"Tai Le", + "fontFile":"NotoSansCJK-Regular.ttc" + }, + "3040-309F":{ + "description":"Hiragana", + "fontFile":"NotoSansCJK-Regular.ttc" + }, + "30A0-30FF@Katakana":{ + "description":"Katakana", + "fontFile":"NotoSansCJK-Regular.ttc" + }, + "3100-312F@Bopomofo":{ + "description":"Bopomofo", + "fontFile":"NotoSansCJK-Regular.ttc" + }, + "3130-318F":{ + "description":"Hangul Compatibility Jamo", + "fontFile":"NotoSansCJK-Regular.ttc" + }, + "3190-319F":{ + "description":"Kanbun", + "fontFile":"NotoSansKannada-Regular.ttf" + }, + "31A0-31BF@Bopomofo Extended":{ + "description":"Tai Le", + "fontFile":"NotoSansCJK-Regular.ttc" + }, + "31F0-31FF":{ + "description":"Katakana Phonetic Extensions", + "fontFile":"NotoSansCJK-Regular.ttc" + },"3200-32FF":{ + "description":"Enclosed CJK Letters and Months", + "fontFile":"NotoSansCJK-Regular.ttc" + }, + "3300-33FF":{ + "description":"CJK Compatibility", + "fontFile":"NotoSansCJK-Regular.ttc" + }, + "4DC0-4DFF":{ + "description":"Yijing Hexagram Symbols", + "fontFile":"NotoSansCJK-Regular.ttc" + }, + "4E00-9FFF":{ + "description":"CJK Unified Ideographs", + "fontFile":"SourceHanSans-Regular.ttc" + }, + "FB00-FB4F":{ + "description":"Alphabetic Presentation Forms", + "fontFile":"NotoSansCJK-Regular.ttc" + }, + "FB50-FDFF":{ + "description":"Arabic Presentation Forms-A", + "fontFile":"NotoSansCJK-Regular.ttc" + }, + "FE00-FE0F":{ + "description":"Variation Selectors", + "fontFile":"NotoSansCJK-Regular.ttc" + }, + "FE20-FE2F":{ + "description":"Combining Half Marks", + "fontFile":"NotoSansCJK-Regular.ttc" + }, + "FE30-FE4F":{ + "description":"CJK Compatibility Forms", + "fontFile":"NotoSansCJK-Regular.ttc" + }, + "FE50-FE6F":{ + "description":"Small Form Variants", + "fontFile":"NotoSansCJK-Regular.ttc" + }, + "FF00-FFEF":{ + "description":"Halfwidth and Fullwidth Forms", + "fontFile":"NotoSansCJK-Regular.ttc" + } +} diff --git a/example/lib/main.dart b/example/lib/main.dart index 2c23c26..9153b10 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,34 +1,237 @@ -import 'package:flutter/material.dart'; import 'dart:async'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_reactive_ble/flutter_reactive_ble.dart'; + import 'package:jc_printer/jc_printer.dart'; void main() { runApp(const MyApp()); } -class MyApp extends StatefulWidget { +class MyApp extends StatelessWidget { const MyApp({super.key}); @override - State createState() => _MyAppState(); + Widget build(BuildContext context) { + return const MaterialApp( + home: HomePage(), + ); + } } -class _MyAppState extends State { - final _jcPrinter = JcPrinter(); +class HomePage extends StatefulWidget { + const HomePage({super.key}); + + @override + State createState() => _HomePageState(); +} + +class _HomePageState extends State { + final TextEditingController _labelWidthInput = TextEditingController(); + final TextEditingController _labelHeightInput = TextEditingController(); + final TextEditingController _countInput = TextEditingController(); + final TextEditingController _contentInput = TextEditingController(); + final _printer = JcPrinter(); + ConnectState _connectState = ConnectState.none; + StreamSubscription? _connectStateSubs; + StreamSubscription? _printingCountSubs; + StreamSubscription>? _errorInfoSubs; + DiscoveredDevice? _device; + + String get _title { + switch (_connectState) { + case ConnectState.connecting: + return '连接中'; + case ConnectState.connected: + return _device?.name ?? '已连接'; + case ConnectState.none: + return '未连接'; + } + } @override void initState() { + _labelWidthInput.text = '40'; + _labelHeightInput.text = '30'; + _countInput.text = '1'; + _contentInput.text = '歪脖子'; + _connectStateSubs = _printer.connectStateStream.listen( + _connectStateListener, + ); + _printingCountSubs = _printer.printingCountStream.listen( + _printingCountListener, + ); + _errorInfoSubs = _printer.errorInfoStream.listen( + _errorInfoListener, + ); super.initState(); - _jcPrinter.connect('name'); + } + + @override + void dispose() { + _labelWidthInput.dispose(); + _labelHeightInput.dispose(); + _countInput.dispose(); + _contentInput.dispose(); + _connectStateSubs?.cancel(); + _printingCountSubs?.cancel(); + _errorInfoSubs?.cancel(); + super.dispose(); + } + + void _connectStateListener(ConnectState state) { + setState(() { + _connectState = state; + }); + } + void _printingCountListener(int count) { + print(count); + } + void _errorInfoListener(Map error) { + print(error); + } + + void _connect() { + _printer.connect(_device!.name); + } + + void _startPrint() async { + final labelWidth = double.tryParse(_labelWidthInput.value.text) ?? 0; + final labelHeight = double.tryParse(_labelHeightInput.value.text) ?? 0; + final count = double.tryParse(_countInput.value.text) ?? 0; + final content = _contentInput.value.text.trim(); + if (content.isEmpty || count <= 0) return; + _printer.setTotalPrints(3); + _printer.startPrint(data: '', count: 1); } @override Widget build(BuildContext context) { - return MaterialApp( - home: Scaffold( - appBar: AppBar( - title: const Text('Plugin example app'), + return Scaffold( + appBar: AppBar( + title: _connectState == ConnectState.connecting + ? const CupertinoActivityIndicator() + : Text(_title), + actions: [ + TextButton( + onPressed: () async { + if (_connectState == ConnectState.connected) { + _printer.disconnect(); + return; + } + final result = await showDialog( + context: context, + builder: (BuildContext context) => _DevicesDialog( + onTap: Navigator.of(context).pop, + ), + ); + if (result == null) return; + _device = result; + _connect(); + }, + child: Text( + _connectState == ConnectState.connected ? '断开' : '连接设备', + style: const TextStyle(color: Colors.white), + ), + ), + ], + ), + body: SingleChildScrollView( + padding: const EdgeInsets.all(20), + child: Center( + child: Column( + children: [ + TextField( + controller: _labelWidthInput, + decoration: const InputDecoration(label: Text('标签宽度')), + ), + TextField( + controller: _labelHeightInput, + decoration: const InputDecoration(label: Text('标签高度')), + ), + TextField( + controller: _countInput, + decoration: const InputDecoration(label: Text('打印数量')), + ), + TextField( + controller: _contentInput, + decoration: const InputDecoration(label: Text('内容')), + ), + const SizedBox(height: 20), + ElevatedButton( + onPressed: _startPrint, + child: const Text('开始打印'), + ), + ], + ), + ), + ), + ); + } +} + +class _DevicesDialog extends StatefulWidget { + final void Function(DiscoveredDevice device)? onTap; + + const _DevicesDialog({ + Key? key, + this.onTap, + }) : super(key: key); + + @override + State<_DevicesDialog> createState() => _DevicesDialogState(); +} + +class _DevicesDialogState extends State<_DevicesDialog> { + final _ble = FlutterReactiveBle(); + final List _devices = []; + StreamSubscription? _scanSubs; + + @override + void initState() { + _scanSubs = _ble.scanForDevices( + withServices: [], + ).listen(_scanListener); + super.initState(); + } + + @override + void dispose() { + _scanSubs?.cancel(); + super.dispose(); + } + + void _scanListener(DiscoveredDevice device) { + if (device.name.isEmpty) return; + if (device.connectable != Connectable.available) return; + final index = _devices.indexWhere( + (element) => element.id == device.id, + ); + if (index > -1) { + _devices[index] = device; + } else { + _devices.add(device); + } + if (mounted) setState(() {}); + } + + @override + Widget build(BuildContext context) { + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints(maxHeight: 400), + child: ListView.separated( + itemBuilder: (BuildContext context, int index) { + final item = _devices[index]; + return ListTile( + title: Text(item.name), + onTap: () => widget.onTap?.call(item), + ); + }, + itemCount: _devices.length, + separatorBuilder: (_, __) => const Divider(), ), ), ); diff --git a/example/pubspec.lock b/example/pubspec.lock index ac4adfd..2fda947 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -65,6 +65,14 @@ packages: url: "https://pub.dev" source: hosted version: "6.1.4" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.dev" + source: hosted + version: "1.1.0" flutter: dependency: "direct main" description: flutter @@ -83,6 +91,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.3" + flutter_reactive_ble: + dependency: "direct main" + description: + name: flutter_reactive_ble + sha256: "7a0d245412dc8e1b72ce2adc423808583b42ce824b1be74001ff22c8bb5ada48" + url: "https://pub.dev" + source: hosted + version: "5.2.0" flutter_test: dependency: "direct dev" description: flutter @@ -93,6 +109,14 @@ packages: description: flutter source: sdk version: "0.0.0" + functional_data: + dependency: transitive + description: + name: functional_data + sha256: aefdec4365452283b2a7cf420a3169654d51d3e9553069a22d76680d7a9d7c3d + url: "https://pub.dev" + source: hosted + version: "1.1.1" integration_test: dependency: "direct dev" description: flutter @@ -169,6 +193,30 @@ packages: url: "https://pub.dev" source: hosted version: "4.2.4" + protobuf: + dependency: transitive + description: + name: protobuf + sha256: "01dd9bd0fa02548bf2ceee13545d4a0ec6046459d847b6b061d8a27237108a08" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + reactive_ble_mobile: + dependency: transitive + description: + name: reactive_ble_mobile + sha256: e4623446d5fd6e641c984892ee1fa7c67499a2bb0971d85a500815e1d05db6fb + url: "https://pub.dev" + source: hosted + version: "5.2.0" + reactive_ble_platform_interface: + dependency: transitive + description: + name: reactive_ble_platform_interface + sha256: "8988d16497886dccc69dca1c3eebce28ae387371f3f948a4f1b03dec9954fb05" + url: "https://pub.dev" + source: hosted + version: "5.2.0" sky_engine: dependency: transitive description: flutter diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 65c8f02..b06c934 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -17,6 +17,7 @@ dependencies: flutter: sdk: flutter + flutter_reactive_ble: 5.2.0 jc_printer: # When depending on this package from a real application you should use: # jc_printer: ^x.y.z diff --git a/ios/Classes/JcPrinterPlugin.h b/ios/Classes/JcPrinterPlugin.h index 18a3907..075acad 100644 --- a/ios/Classes/JcPrinterPlugin.h +++ b/ios/Classes/JcPrinterPlugin.h @@ -1,4 +1,7 @@ #import -@interface JcPrinterPlugin : NSObject +@interface JcPrinterPlugin : NSObject + +@property (nonatomic, strong) FlutterEventSink eventSink; + @end diff --git a/ios/Classes/JcPrinterPlugin.m b/ios/Classes/JcPrinterPlugin.m index a120949..f0fee2d 100644 --- a/ios/Classes/JcPrinterPlugin.m +++ b/ios/Classes/JcPrinterPlugin.m @@ -3,29 +3,189 @@ @implementation JcPrinterPlugin + (void)registerWithRegistrar:(NSObject*)registrar { - FlutterMethodChannel* channel = [FlutterMethodChannel - methodChannelWithName:@"jc_printer" - binaryMessenger:[registrar messenger]]; - JcPrinterPlugin* instance = [[JcPrinterPlugin alloc] init]; - [registrar addMethodCallDelegate:instance channel:channel]; + FlutterMethodChannel* channel = [FlutterMethodChannel methodChannelWithName:@"jc_printer" binaryMessenger:[registrar messenger]]; + + JcPrinterPlugin* instance = [[JcPrinterPlugin alloc] init]; + [registrar addMethodCallDelegate:instance channel:channel]; + + FlutterEventChannel* eventChannel = [FlutterEventChannel eventChannelWithName:@"printer_stream" binaryMessenger:[registrar messenger]]; + [eventChannel setStreamHandler:instance]; + } - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { - NSLog(@"arguments is :%@", call.arguments); + // NSLog(@"arguments is :%@", call.arguments); + + [self printingCount]; + [self errorInfo]; if ([@"getPlatformVersion" isEqualToString:call.method]) { result([@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]); } else if ([@"connect" isEqualToString:call.method]) { - [self connect:call.arguments result:result]; + [self connect:call.arguments]; + result(nil); + } else if ([@"disconnect" isEqualToString:call.method]) { + [self disconnect]; + result(nil); + } else if ([@"setTotalPrints" isEqualToString:call.method]) { + [self setTotalPrints:call.arguments]; + result(nil); + } else if ([@"initDrawingBoard" isEqualToString:call.method]) { + [self initDrawingBoard:call.arguments result:result]; + } else if ([@"drawLabelImage" isEqualToString:call.method]) { + [self drawLabelImage:call.arguments result:result]; + } else if ([@"drawLabelText" isEqualToString:call.method]) { + [self drawLabelText:call.arguments result:result]; + } else if ([@"drawLabelBarcode" isEqualToString:call.method]) { + [self drawLabelBarcode:call.arguments result:result]; + } else if ([@"getLabelData" isEqualToString:call.method]) { + [self getLabelData:result]; + } else if ([@"startJob" isEqualToString:call.method]) { + [self startJob:call.arguments result:result]; + } else if ([@"endJob" isEqualToString:call.method]) { + [self endJob:result]; + } else if ([@"commit" isEqualToString:call.method]) { + [self commit:call.arguments result:result]; } else { result(FlutterMethodNotImplemented); } } -- (void)connect:(NSString *)name result:(FlutterResult)result { - [JCAPI openPrinter:name completion:^(BOOL isSuccess) { +- (void) disconnect { + [JCAPI closePrinter]; +} + +- (void) setTotalPrints:(NSString *)args { + NSInteger page = [args integerValue]; + [JCAPI setTotalQuantityOfPrints:page]; +} + +- (void)initDrawingBoard:(NSDictionary *)args result:(FlutterResult)result { + NSNumber *width = args[@"width"]; + NSNumber *height = args[@"height"]; + NSNumber *horizontalShift = args[@"horizontalShift"]; + NSNumber *verticalShift = args[@"verticalShift"]; + NSNumber *rotate = args[@"rotate"]; + NSString *font = args[@"font"]; + + [JCAPI initDrawingBoard:width.floatValue withHeight:height.floatValue withHorizontalShift:horizontalShift.floatValue withVerticalShift:verticalShift.floatValue rotate:rotate.intValue font:font]; + result(nil); +} + +- (void)drawLabelImage:(NSDictionary *)args result:(FlutterResult)result { + NSNumber *x = args[@"x"]; + NSNumber *y = args[@"y"]; + NSNumber *width = args[@"width"]; + NSNumber *height = args[@"height"]; + NSNumber *rotate = args[@"rotate"]; + NSNumber *type = args[@"type"]; + NSNumber *threshold = args[@"threshold"]; + NSString *base64 = args[@"base64"]; + + BOOL isSuccess = [JCAPI DrawLableImage:x.floatValue withY:y.floatValue withWidth:width.floatValue withHeight:height.floatValue withImageData:base64 withRotate:rotate.intValue withImageProcessingType:type.intValue withImageProcessingValue:threshold.floatValue]; + result(@(isSuccess)); +} + +- (void)drawLabelText:(NSDictionary *)args result:(FlutterResult)result { + NSNumber *x = args[@"x"]; + NSNumber *y = args[@"y"]; + NSNumber *width = args[@"width"]; + NSNumber *height = args[@"height"]; + NSNumber *fontSize = args[@"fontSize"]; + NSNumber *rotate = args[@"rotate"]; + NSNumber *textAlignHorizontal = args[@"textAlignHorizontal"]; + NSNumber *textAlignVertical = args[@"textAlignVertical"]; + NSNumber *lineMode = args[@"lineMode"]; + NSNumber *letterSpacing = args[@"letterSpacing"]; + NSNumber *lineSpacing = args[@"lineSpacing"]; + NSString *content = args[@"content"]; + + BOOL isSuccess = [JCAPI drawLableText:x.floatValue withY:y.floatValue withWidth:width.floatValue withHeight:height.floatValue withString:content withFontFamily:@"" withFontSize:fontSize.floatValue withRotate:rotate.intValue withTextAlignHorizonral:textAlignHorizontal.intValue withTextAlignVertical:textAlignVertical.intValue withLineMode:lineMode.intValue withLetterSpacing:letterSpacing.floatValue withLineSpacing:lineSpacing.floatValue withFontStyle:@[@0,@0,@0,@0]]; + result(@(isSuccess)); +} + +- (void)drawLabelBarcode:(NSDictionary *)args result:(FlutterResult)result { + NSNumber *x = args[@"x"]; + NSNumber *y = args[@"y"]; + NSNumber *width = args[@"width"]; + NSNumber *height = args[@"height"]; + NSNumber *fontSize = args[@"fontSize"]; + NSNumber *rotate = args[@"rotate"]; + NSNumber *codeType = args[@"codeType"]; + NSNumber *textPosition = args[@"textPosition"]; + NSNumber *textHeight = args[@"textHeight"]; + NSString *text = args[@"text"]; + + BOOL isSuccess = [JCAPI drawLableBarCode:x.floatValue withY:y.floatValue withWidth:width.floatValue withHeight:height.floatValue withString:text withFontSize:fontSize.floatValue withRotate:rotate.intValue withCodeType:codeType.intValue withTextHeight:textHeight.floatValue withTextPosition:textPosition.intValue]; + result(@(isSuccess)); +} + +- (void)getLabelData:(FlutterResult)result { + NSString *data = [JCAPI GenerateLableJson]; + result(data); +} + +- (void)startJob:(NSDictionary *)args result:(FlutterResult)result { + NSNumber *blackRules = args[@"blackRules"]; + NSNumber *paperStyle = args[@"paperStyle"]; + [JCAPI startJob:blackRules.intValue withPaperStyle:paperStyle.intValue withCompletion:^(BOOL isSuccess) { result(@(isSuccess)); }]; } +- (void)commit:(NSDictionary *)args result:(FlutterResult)result { + NSString *data = args[@"data"]; + NSNumber *count = args[@"count"]; + [JCAPI commit:data withOnePageNumbers:count.intValue withComplete:^(BOOL isSuccess) { + result(@(isSuccess)); + }]; +} + +- (void)endJob:(FlutterResult)result { + [JCAPI endPrint:^(BOOL isSuccess) { + result(@(isSuccess)); + }]; +} + +#pragma mark - FlutterStreamHandler + +- (FlutterError *)onListenWithArguments:(id)arguments eventSink:(FlutterEventSink)events { + self.eventSink = events; + return nil; +} + +- (FlutterError *)onCancelWithArguments:(id)arguments { + return nil; +} + +- (void)connect:(NSString *)name { + [JCAPI openPrinter:name completion:^(BOOL isSuccess) { + NSDictionary *params = @{ + @"type": @"connectState", + @"result": @(isSuccess), + }; + !self.eventSink ? : self.eventSink(params); + }]; +} + +-(void)errorInfo { + [JCAPI getPrintingErrorInfo:^(NSString *printInfo) { + NSDictionary *params = @{ + @"type": @"errorInfo", + @"result": printInfo, + }; + !self.eventSink ? : self.eventSink(params); + }]; +} + +- (void)printingCount { + [JCAPI getPrintingCountInfo:^(NSDictionary *printDicInfo) { + NSDictionary *params = @{ + @"type": @"printingCount", + @"result": printDicInfo, + }; + !self.eventSink ? : self.eventSink(params); + }]; +} + @end diff --git a/lib/constants.dart b/lib/constants.dart new file mode 100644 index 0000000..f3fa71f --- /dev/null +++ b/lib/constants.dart @@ -0,0 +1,39 @@ +const Map kErrorInfo = { + '1': '盒盖打开', + '2': '缺纸', + '3': '电量不足', + '4': '电池异常', + '5': '手动停止', + '6': '数据错误', + '7': '温度过高', + '8': '出纸异常', + '9': '打印忙碌', + '10': '没有检测到打印头', + '11': '环境温度过低', + '12': '打印头未锁紧', + '13': '未检测到碳带', + '14': '不匹配的碳带', + '15': '用完的碳带', + '16': '不支持的纸张类型', + '17': '设置纸张失败', + '18': '设置打印模式失败', + '19': '设置打印浓度失败', + '20': '写入Rfid失败', + '21': '边距设置错误', + '22': '通讯异常', + '23': '打印机断开', + '24': '画板参数设置错误', + '25': '旋转角度参数错误', + '26': 'json参数错误(PC)', + '27': '出纸异常', + '28': '检查纸张类型', + '29': 'RFID标签进行非RFID模式打印时', + '30': '浓度设置不支持', + '31': '不支持的打印模式', + '32': '标签材质设置失败', + '33': '不支持的标签材质设置', + '34': '打印机异常', + '35': '切刀异常', + '36': '缺纸(T2)', + '37': '打印机异常(T2无法通过指令恢复,需要手动按打印机)', +}; diff --git a/lib/jc_printer.dart b/lib/jc_printer.dart index 6c8ea97..9672469 100644 --- a/lib/jc_printer.dart +++ b/lib/jc_printer.dart @@ -1,10 +1,232 @@ +import 'dart:async'; +// import 'dart:convert'; +import 'package:jc_printer/constants.dart'; import 'jc_printer_platform_interface.dart'; +enum ConnectState { + /// 连接中 + connecting, + + /// 连接成功 + connected, + + /// 未连接 + none, +} + class JcPrinter { final _printer = JcPrinterPlatform.instance; + // final _font = 'SourceHanSans-Regular.ttc'; - /// 蓝牙连接指定名称的打印机。 - /// @param name 要连接的蓝牙打印机的名称。 - Future connect(String name) async => _printer.connect(name); + late final StreamController _connectStateBroadcast; + late final StreamController _printingCountBroadcast; + late final StreamController> _errorInfoBroadcast; + + static final JcPrinter _instance = JcPrinter._internal(); + + factory JcPrinter() => _instance; + + JcPrinter._internal() { + _connectStateBroadcast = StreamController.broadcast(); + _printingCountBroadcast = StreamController.broadcast(); + _errorInfoBroadcast = StreamController.broadcast(); + + _printer.printerStream.listen(_listener); + } + + Stream get connectStateStream => _connectStateBroadcast.stream; + + Stream get printingCountStream => _printingCountBroadcast.stream; + + Stream> get errorInfoStream => _errorInfoBroadcast.stream; + + void _listener(dynamic event) { + if (event is! Map) return; + if (event['type'] == 'connectState') _connectStateListener(event); + if (event['type'] == 'printingCount') _printingCountListener(event); + if (event['type'] == 'errorInfo') _errorInfoListener(event); + } + + void _connectStateListener(dynamic event) { + _connectStateBroadcast.sink.add( + event['result'] == true ? ConnectState.connected : ConnectState.none, + ); + } + + void _printingCountListener(dynamic event) { + if (event['result'] is! Map) return; + final result = event['result']; + final count = int.tryParse(result['totalCount'].toString()) ?? 0; + _printingCountBroadcast.sink.add(count); + } + + void _errorInfoListener(dynamic event) { + final code = event['result'].toString(); + final msg = kErrorInfo[code] ?? ''; + _errorInfoBroadcast.sink.add({'code': code, 'msg': msg}); + } + + void connect(String name) { + _connectStateBroadcast.sink.add(ConnectState.connecting); + _printer.connect(name); + } + + void disconnect() { + _printer.disconnect(); + } + + void setTotalPrints(int count) => _printer.setTotalPrints(count); + + /// 初始化画板。 + /// + /// @param width 画布宽度,单位mm。 + /// + /// @param height 画布高度,单位mm。 + /// + /// @param font 使用字体路径。 + Future initDrawingBoard({ + required double width, + required double height, + required String font, + }) async { + return _printer.initDrawingBoard(width: width, height: height, font: font); + } + + /// 绘制文本。 + /// + /// @param x 水平坐标,单位mm。 + /// + /// @param y 垂直坐标,单位mm。 + /// + /// @param width 图片宽度,单位mm。 + /// + /// @param height 图片高度,单位mm。 + /// + /// @param content 内容。 + /// + /// @param rotate 旋转角度,支持角度0/90/180/270。 + /// + /// @param textAlignHorizontal 文本水平对齐方式 0 左对齐、1 水平居中对齐、2 右对齐。 + /// + /// @param textAlignVertical 文本竖直对齐方式 0 上对齐、1 垂直居中对齐、2 下对齐。 + /// + /// @param lineMode 换行方式 + /// 1:宽高固定,内容大小自适应(字号/字符间距/行间距 按比例缩放) + /// 2:宽度固定,高度自适应 + /// 6.宽高固定,内容超过预设的宽高时自动缩小。 + /// + /// @param letterSpacing 字体间隔。 + /// + /// @param lineSpacing 行间隔。 + Future drawLabelText({ + required double width, + required double height, + required String content, + required double fontSize, + double x = 0, + double y = 0, + int rotate = 0, + int textAlignHorizontal = 0, + int textAlignVertical = 0, + int lineMode = 1, + double letterSpacing = 0, + double lineSpacing = 0, + }) async { + await _printer.drawLabelText( + x: x, + y: y, + width: width, + height: height, + content: content, + fontSize: fontSize, + rotate: rotate, + textAlignHorizontal: textAlignHorizontal, + textAlignVertical: textAlignVertical, + lineMode: lineMode, + letterSpacing: letterSpacing, + lineSpacing: lineSpacing, + ); + } + + /// 绘制条码。 + /// + /// @param x 水平坐标,单位mm。 + /// + /// @param y 垂直坐标,单位mm。 + /// + /// @param width 图片宽度,单位mm。 + /// + /// @param height 图片高度,单位mm。 + /// + /// @param text 内容。 + /// + /// @param fontSize 字体大小。 + /// + /// @param rotate 旋转角度,支持角度0/90/180/270。 + /// + /// @param textHeight 文本高度,单位mm。 + /// + /// @param textPosition 文本位置,一维码文字识别码显示位置 + /// 0:下方显示 + /// 1:上方显示 + /// 2:不显示。 + /// + /// @param codeType 一维码类型 + /// 20:CODE128 + /// 21:UPC-A + /// 22:UPC-E + /// 23:EAN8 + /// 24:EAN13 + /// 25:CODE93 + /// 26:CODE39 + /// 27:CODEBAR + /// 28:ITF25。 + Future drawLabelBarcode({ + required double width, + required double height, + required String text, + required double fontSize, + required double textHeight, + double x = 0, + double y = 0, + int rotate = 0, + int codeType = 20, + int textPosition = 0, + }) async { + await _printer.drawLabelBarcode( + x: x, + y: y, + width: width, + height: height, + text: text, + fontSize: fontSize, + rotate: rotate, + textHeight: textHeight, + codeType: codeType, + textPosition: textPosition, + ); + } + + /// 获取绘画数据 + Future getLabelData() async => _printer.getLabelData(); + + /// 开始打印 + /// + /// @param data 绘画数据。 + /// + /// @param count 用于指定当前页的打印份数。 + Future startPrint({ + required String data, + int count = 1, + }) async { + final result = await _printer.startJob( + blackRules: 0, + paperStyle: 1, + ); + if (result != true) return false; + return _printer.commit(data: data, count: count); + } + + Future endPrint() async => _printer.endJob(); } diff --git a/lib/jc_printer_method_channel.dart b/lib/jc_printer_method_channel.dart index a3480ff..79bda4d 100644 --- a/lib/jc_printer_method_channel.dart +++ b/lib/jc_printer_method_channel.dart @@ -1,24 +1,179 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; - import 'jc_printer_platform_interface.dart'; -/// An implementation of [JcPrinterPlatform] that uses method channels. class MethodChannelJcPrinter extends JcPrinterPlatform { - /// The method channel used to interact with the native platform. - @visibleForTesting - final methodChannel = const MethodChannel('jc_printer'); + final method = const MethodChannel('jc_printer'); + final event = const EventChannel('printer_stream'); @override - Future getPlatformVersion() async { - final version = await methodChannel.invokeMethod('getPlatformVersion'); - return version; + Future connect(String name) async { + return method.invokeMethod('connect', name); } @override - Future connect(String name) async { - final result = await methodChannel.invokeMethod('connect', name); - print(result); + Future disconnect() async { + return method.invokeMethod('disconnect'); + } + + @override + Future setTotalPrints(int page) async { + return method.invokeMethod('setTotalPrints', page); + } + + @override + Future initDrawingBoard({ + required double width, + required double height, + required String font, + double horizontalShift = 0, + double verticalShift = 0, + int rotate = 0, + }) async { + final Map arguments = { + 'width': width, + 'height': height, + 'horizontalShift': horizontalShift, + 'verticalShift': verticalShift, + 'rotate': rotate, + 'font': font, + }; + await method.invokeMethod('initDrawingBoard', arguments); + } + + @override + Future drawLabelImage({ + required double x, + required double y, + required double width, + required double height, + required String base64, + int rotate = 0, + int type = 1, + double threshold = 127, + }) async { + final Map arguments = { + 'x': x, + 'y': y, + 'w': width, + 'h': height, + 'base64': base64, + 'rotate': rotate, + 'type': type, + 'threshold': threshold, + }; + final result = await method.invokeMethod( + 'drawLabelImage', + arguments, + ); return result ?? false; } + + @override + Future drawLabelText({ + required double x, + required double y, + required double width, + required double height, + required String content, + required double fontSize, + int rotate = 0, + int textAlignHorizontal = 0, + int textAlignVertical = 0, + int lineMode = 1, + double letterSpacing = 0, + double lineSpacing = 0, + }) async { + final Map arguments = { + 'x': x, + 'y': y, + 'width': width, + 'height': height, + 'content': content, + 'fontSize': fontSize, + 'rotate': rotate, + 'textAlignHorizontal': textAlignHorizontal, + 'textAlignVertical': textAlignVertical, + 'lineMode': lineMode, + 'letterSpacing': letterSpacing, + 'lineSpacing': lineSpacing, + }; + final result = await method.invokeMethod('drawLabelText', arguments); + return result ?? false; + } + + @override + Future drawLabelBarcode({ + required double x, + required double y, + required double width, + required double height, + required String text, + required double textHeight, + required double fontSize, + int rotate = 0, + int codeType = 20, + int textPosition = 0, + }) async { + final Map arguments = { + 'x': x, + 'y': y, + 'width': width, + 'height': height, + 'text': text, + 'fontSize': fontSize, + 'rotate': rotate, + 'textHeight': textHeight, + 'codeType': codeType, + 'textPosition': textPosition, + }; + final result = await method.invokeMethod( + 'drawLabelBarcode', + arguments, + ); + return result ?? false; + } + + @override + Future getLabelData() async { + final result = await method.invokeMethod('getLabelData'); + return result ?? ''; + } + + @override + Future startJob({ + required int blackRules, + required int paperStyle, + }) async { + final Map arguments = { + 'blackRules': blackRules, + 'paperStyle': paperStyle, + }; + final result = await method.invokeMethod('startJob', arguments); + return result ?? false; + } + + @override + Future endJob() async { + final result = await method.invokeMethod('endJob'); + return result ?? false; + } + + @override + Future commit({ + required String data, + int count = 1, + }) async { + final Map arguments = { + 'data': data, + 'count': count, + }; + final result = await method.invokeMethod( + 'commit', + arguments, + ); + return result ?? false; + } + + @override + Stream get printerStream => event.receiveBroadcastStream(); } diff --git a/lib/jc_printer_platform_interface.dart b/lib/jc_printer_platform_interface.dart index 918edea..6441678 100644 --- a/lib/jc_printer_platform_interface.dart +++ b/lib/jc_printer_platform_interface.dart @@ -23,11 +23,204 @@ abstract class JcPrinterPlatform extends PlatformInterface { _instance = instance; } - Future getPlatformVersion() { - throw UnimplementedError('platformVersion() has not been implemented.'); - } - - Future connect(String name) async { + /// 蓝牙连接指定名称的打印机。 + /// + /// @param name 要连接的蓝牙打印机的名称。 + Future connect(String name) async { throw UnimplementedError('connect() has not been implemented.'); } + + /// 断开连接 + Future disconnect() async { + throw UnimplementedError('disconnect() has not been implemented.'); + } + + /// 设置总打印机张数 + Future setTotalPrints(int page) async { + throw UnimplementedError('setTotalPrints() has not been implemented.'); + } + + /// 初始化画板。 + /// + /// @param width 画布宽度,单位mm。 + /// + /// @param height 画布高度,单位mm。 + /// + /// @param horizontalShift 水平偏移,单位mm。 + /// + /// @param verticalShift 竖直偏移,单位mm。 + /// + /// @param rotate 旋转角度,支持角度0/90/180/270。 + /// + /// @param font 使用字体路径。 + Future initDrawingBoard({ + required double width, + required double height, + required String font, + double horizontalShift = 0, + double verticalShift = 0, + int rotate = 0, + }) async { + throw UnimplementedError('initDrawingBoard() has not been implemented.'); + } + + /// 绘制图片。 + /// + /// @param x 水平坐标,单位mm。 + /// + /// @param y 垂直坐标,单位mm。 + /// + /// @param width 图片宽度,单位mm。 + /// + /// @param height 图片高度,单位mm。 + /// + /// @param base64 图像base64数据。 + /// + /// @param rotate 旋转角度,支持角度0/90/180/270。 + /// + /// @param type 处理算法,默认1即可。 + /// + /// @param threshold 阈值,默认127即可。 + Future drawLabelImage({ + required double x, + required double y, + required double width, + required double height, + required String base64, + int rotate = 0, + int type = 1, + double threshold = 127, + }) async { + throw UnimplementedError('drawLabelImage() has not been implemented.'); + } + + /// 绘制文本。 + /// + /// @param x 水平坐标,单位mm。 + /// + /// @param y 垂直坐标,单位mm。 + /// + /// @param width 图片宽度,单位mm。 + /// + /// @param height 图片高度,单位mm。 + /// + /// @param content 内容。 + /// + /// @param rotate 旋转角度,支持角度0/90/180/270。 + /// + /// @param textAlignHorizontal 文本水平对齐方式 0 左对齐、1 水平居中对齐、2 右对齐。 + /// + /// @param textAlignVertical 文本竖直对齐方式 0 上对齐、1 垂直居中对齐、2 下对齐。 + /// + /// @param lineMode 换行方式 + /// 1:宽高固定,内容大小自适应(字号/字符间距/行间距 按比例缩放) + /// 2:宽度固定,高度自适应 + /// 6.宽高固定,内容超过预设的宽高时自动缩小。 + /// + /// @param letterSpacing 字体间隔。 + /// + /// @param lineSpacing 行间隔。 + Future drawLabelText({ + required double x, + required double y, + required double width, + required double height, + required String content, + required double fontSize, + int rotate = 0, + int textAlignHorizontal = 0, + int textAlignVertical = 0, + int lineMode = 1, + double letterSpacing = 0, + double lineSpacing = 0, + }) async { + throw UnimplementedError('drawLabelText() has not been implemented.'); + } + + /// 绘制条码。 + /// + /// @param x 水平坐标,单位mm。 + /// + /// @param y 垂直坐标,单位mm。 + /// + /// @param width 图片宽度,单位mm。 + /// + /// @param height 图片高度,单位mm。 + /// + /// @param text 内容。 + /// + /// @param fontSize 字体大小。 + /// + /// @param rotate 旋转角度,支持角度0/90/180/270。 + /// + /// @param textHeight 文本高度,单位mm。 + /// + /// @param textPosition 文本位置,一维码文字识别码显示位置 + /// 0:下方显示 + /// 1:上方显示 + /// 2:不显示。 + /// + /// @param codeType 一维码类型 + /// 20:CODE128 + /// 21:UPC-A + /// 22:UPC-E + /// 23:EAN8 + /// 24:EAN13 + /// 25:CODE93 + /// 26:CODE39 + /// 27:CODEBAR + /// 28:ITF25。 + Future drawLabelBarcode({ + required double x, + required double y, + required double width, + required double height, + required String text, + required double textHeight, + required double fontSize, + int rotate = 0, + int codeType = 20, + int textPosition = 0, +}) { + throw UnimplementedError('drawLabelBarcode() has not been implemented.'); + } + + /// 获取画板上绘制的数据 + Future getLabelData() async { + throw UnimplementedError('getLabelData() has not been implemented.'); + } + + /// 开始打印任务 + /// + /// @param blackRules 设置打印浓度。 + /// + /// @param paperStyle 设置纸张类型。 + Future startJob({ + required int blackRules, + required int paperStyle, + }) async { + throw UnimplementedError('startJob() has not been implemented.'); + } + + /// 结束打印任务 + Future endJob() async { + throw UnimplementedError('endJob() has not been implemented.'); + } + + /// 提交打印任务 + /// + /// @param data 打印数据。 + /// + /// @param count 用于指定当前页的打印份数。 + Future commit({ + required String data, + int count = 1, + }) async { + throw UnimplementedError('commit() has not been implemented.'); + } + + /// 打印机事件流 + Stream get printerStream { + throw UnimplementedError('printerStream has not been implemented.'); + } } diff --git a/test/jc_printer_method_channel_test.dart b/test/jc_printer_method_channel_test.dart index 7a2afe2..0b9eb3a 100644 --- a/test/jc_printer_method_channel_test.dart +++ b/test/jc_printer_method_channel_test.dart @@ -1,11 +1,11 @@ import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:jc_printer/jc_printer_method_channel.dart'; +// import 'package:jc_printer/jc_printer_method_channel.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); - MethodChannelJcPrinter platform = MethodChannelJcPrinter(); + // MethodChannelJcPrinter platform = MethodChannelJcPrinter(); const MethodChannel channel = MethodChannel('jc_printer'); setUp(() { @@ -22,6 +22,6 @@ void main() { }); test('getPlatformVersion', () async { - expect(await platform.getPlatformVersion(), '42'); + // expect(await platform.getPlatformVersion(), '42'); }); } diff --git a/test/jc_printer_test.dart b/test/jc_printer_test.dart index f0fa421..cd63ffd 100644 --- a/test/jc_printer_test.dart +++ b/test/jc_printer_test.dart @@ -1,5 +1,5 @@ import 'package:flutter_test/flutter_test.dart'; -import 'package:jc_printer/jc_printer.dart'; +// import 'package:jc_printer/jc_printer.dart'; import 'package:jc_printer/jc_printer_platform_interface.dart'; import 'package:jc_printer/jc_printer_method_channel.dart'; // import 'package:plugin_platform_interface/plugin_platform_interface.dart'; @@ -20,7 +20,7 @@ void main() { }); test('getPlatformVersion', () async { - JcPrinter jcPrinterPlugin = JcPrinter(); + // JcPrinter jcPrinterPlugin = JcPrinter(); // MockJcPrinterPlatform fakePlatform = MockJcPrinterPlatform(); // JcPrinterPlatform.instance = fakePlatform;