diff --git a/flutter_01.log b/flutter_01.log new file mode 100644 index 000000000..879e1045c --- /dev/null +++ b/flutter_01.log @@ -0,0 +1,379 @@ +Flutter crash report. +Please report a bug at https://github.com/flutter/flutter/issues. + +## command + +flutter build ios + +## exception + +ProcessException: ProcessException: Process exited abnormally with exit code -6: +Command line invocation: + /Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -list + +User defaults from command line: + IDEPackageSupportUseBuiltinSCM = YES + +Resolve Package Graph + +Fetching from https://github.com/apple/swift-log.git (cached) + +Fetching from https://github.com/apple/swift-protobuf.git (cached) + +Fetching from https://github.com/firebase/leveldb.git (cached) + +Fetching from https://github.com/google/abseil-cpp-binary.git (cached) + +Fetching from https://github.com/apple/swift-http-types (cached) + +Fetching from https://github.com/google/app-check.git (cached) + +Fetching from https://github.com/google/interop-ios-for-google-sdks.git (cached) + +Fetching from https://github.com/SDWebImage/SDWebImage (cached) + +Fetching from https://github.com/ybrid/opus-swift.git (cached) + +Fetching from https://github.com/google/GTMAppAuth.git (cached) + +Fetching from https://github.com/google/GoogleSignIn-iOS.git (cached) + +Fetching from https://github.com/TimOliver/TOCropViewController (cached) + +Fetching from https://github.com/zhangao0086/DKImagePickerController (cached) + +Fetching from https://github.com/zhangao0086/DKCamera (cached) + +Fetching from https://github.com/google/gtm-session-fetcher.git (cached) + +Fetching from https://github.com/google/GoogleDataTransport.git (cached) + +Fetching from https://github.com/firebase/flutterfire (cached) + +Fetching from https://github.com/SnapKit/SnapKit.git (cached) + +Fetching from https://github.com/apple/swift-openapi-runtime (cached) + +Fetching from https://github.com/Alamofire/Alamofire.git (cached) + +Fetching from https://github.com/apple/swift-system.git (cached) + +Fetching from https://github.com/firebase/nanopb.git (cached) + +Fetching from https://github.com/google/promises.git (cached) + +Fetching from https://github.com/google/GoogleAppMeasurement.git (cached) + +Fetching from https://github.com/kirualex/SwiftyGif.git (cached) + +Fetching from https://github.com/google/grpc-binary.git (cached) + +Fetching from https://github.com/google/GoogleUtilities.git (cached) + +Fetching from https://github.com/MacPaw/OpenAI.git (cached) + +Fetching from https://github.com/zhangao0086/DKPhotoGallery (cached) + +Fetching from https://github.com/loopwork-ai/eventsource.git (cached) + +Fetching from https://github.com/openid/AppAuth-iOS.git (cached) + +Fetching from https://github.com/modelcontextprotocol/swift-sdk.git (cached) + +Fetching from https://github.com/firebase/firebase-ios-sdk (cached) + +Creating working copy of package ‘abseil-cpp-binary’ + +Checking out 1.2024072200.0 of package ‘abseil-cpp-binary’ + +Creating working copy of package ‘app-check’ + +Checking out 11.2.0 of package ‘app-check’ + +Creating working copy of package ‘opus-swift’ + +Checking out 0.8.0 of package ‘opus-swift’ + +Creating working copy of package ‘SDWebImage’ + +Checking out 5.21.0 of package ‘SDWebImage’ + +Creating working copy of package ‘swift-http-types’ + +Checking out 1.4.0 of package ‘swift-http-types’ + +Creating working copy of package ‘interop-ios-for-google-sdks’ + +Checking out 101.0.0 of package ‘interop-ios-for-google-sdks’ + +Creating working copy of package ‘leveldb’ + +Checking out 1.22.5 of package ‘leveldb’ + +Creating working copy of package ‘GTMAppAuth’ + +Checking out 4.1.1 of package ‘GTMAppAuth’ + +Creating working copy of package ‘swift-log’ + +Checking out 1.6.3 of package ‘swift-log’ + +Creating working copy of package ‘swift-protobuf’ + +Checking out 1.29.0 of package ‘swift-protobuf’ + +Creating working copy of package ‘GoogleSignIn-iOS’ + +Checking out 8.0.0 of package ‘GoogleSignIn-iOS’ + +Creating working copy of package ‘DKCamera’ + +Checking out master (5c691d1) of package ‘DKCamera’ + +Creating working copy of package ‘gtm-session-fetcher’ + +Checking out 3.5.0 of package ‘gtm-session-fetcher’ + +Creating working copy of package ‘TOCropViewController’ + +Checking out 2.7.4 of package ‘TOCropViewController’ + +Creating working copy of package ‘DKImagePickerController’ + +Checking out 4.3.9 (0bdfeac) of package ‘DKImagePickerController’ + +Creating working copy of package ‘GoogleDataTransport’ + +Checking out 10.1.0 of package ‘GoogleDataTransport’ + +Creating working copy of package ‘swift-openapi-runtime’ + +Checking out 1.8.2 of package ‘swift-openapi-runtime’ + +Creating working copy of package ‘flutterfire’ + +Checking out main (f852df8) of package ‘flutterfire’ + +Creating working copy of package ‘SnapKit’ + +Checking out 5.7.1 of package ‘SnapKit’ + +Creating working copy of package ‘Alamofire’ + +Checking out 5.10.2 of package ‘Alamofire’ + +Creating working copy of package ‘swift-system’ + +Checking out 1.5.0 of package ‘swift-system’ + +Creating working copy of package ‘nanopb’ + +Checking out 2.30910.0 of package ‘nanopb’ + +Creating working copy of package ‘GoogleAppMeasurement’ + +Checking out 11.13.0 of package ‘GoogleAppMeasurement’ + +Creating working copy of package ‘promises’ + +Checking out 2.4.0 of package ‘promises’ + +Creating working copy of package ‘SwiftyGif’ + +Checking out 5.4.5 of package ‘SwiftyGif’ + +Creating working copy of package ‘grpc-binary’ + +Checking out 1.69.0 of package ‘grpc-binary’ + +Creating working copy of package ‘GoogleUtilities’ + +Checking out 8.1.0 of package ‘GoogleUtilities’ + +Creating working copy of package ‘OpenAI’ + +Checking out 0.4.3 of package ‘OpenAI’ + +Creating working copy of package ‘DKPhotoGallery’ + +Checking out master (311c1bc) of package ‘DKPhotoGallery’ + +Creating working copy of package ‘eventsource’ + +Checking out 1.1.1 of package ‘eventsource’ + +Creating working copy of package ‘AppAuth-iOS’ + +Checking out 1.7.6 of package ‘AppAuth-iOS’ + +Creating working copy of package ‘swift-sdk’ + +Checking out 0.9.0 of package ‘swift-sdk’ + +Creating working copy of package ‘firebase-ios-sdk’ + +Checking out 11.13.0 of package ‘firebase-ios-sdk’ + +'agent_service' dependency on '/Users/liwei/work/flutter/deepvoice_client/local_plugins/music_service/ios/user_portrait' conflicts with dependency on '/Users/liwei/work/flutter/deepvoice_client/local_plugins/user_portrait/ios/user_portrait' which has the same identity 'user_portrait'. this will be escalated to an error in future versions of SwiftPM. +*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSMutableArray insertObjects:atIndexes:]: count of array (62) differs from count of index set (61)' +*** First throw call stack: +( + 0 CoreFoundation 0x0000000188e62ca0 __exceptionPreprocess + 176 + 1 libobjc.A.dylib 0x0000000188926b90 objc_exception_throw + 88 + 2 CoreFoundation 0x0000000188f5d1dc -[__NSCFString characterAtIndex:].cold.1 + 0 + 3 CoreFoundation 0x0000000188e490b8 -[NSMutableArray insertObjects:atIndexes:] + 1444 + 4 IDEFoundation 0x000000010ce72874 __50-[IDEGroup insertGroupSubitems:atIndexes:context:]_block_invoke + 1084 + 5 DVTFoundation 0x000000010b67b16c -[DVTModelObjectGraph performBlockCoalescingModelChanges:] + 60 + 6 IDEFoundation 0x000000010ce72398 -[IDEGroup insertGroupSubitems:atIndexes:context:] + 248 + 7 DVTFoundation 0x000000010b639c30 -[NSMutableArray(DVTFoundationClassAdditions) dvt_sortedInsertOfObjects:withComparator:] + 184 + 8 IDESwiftPackageCore 0x000000011a08c15c $s19IDESwiftPackageCore23IDESPMWorkspaceDelegateC32registerDependencyFileReferences33_033DB97E8C2A552F3158921835EE9F98LL_27modelGraphSynchronizerTokenySayAA0abgH9ReferenceO010dependencyU0_AC16Reg 9 IDESwiftPackageCore 0x000000011a08f264 $s19IDESwiftPackageCore23IDESPMWorkspaceDelegateC27dependencyPackagesDidUpdate33_033DB97E8C2A552F3158921835EE9F98LL8packages14graphHasErrors25revalidatedFilePathCaches27modelGraphSynchronizerToke 10 IDESwiftPackageCore 0x000000011a08717c $s19IDESwiftPackageCore23IDESPMWorkspaceDelegateC27packageGraphDidFinishAction_8duration6resulty7SwiftPM12SPMWorkspaceC0bgJ0O_SdAG0oebgJ16ResolutionResultOtYaFyAC05ModelG17SynchronizerToken33_033 11 IDESwiftPackageCore 0x000000011a08ac18 $s19IDESwiftPackageCore23IDESPMWorkspaceDelegateC38disableWorkspaceContentSynchronization33_033DB97E8C2A552F3158921835EE9F98LL6duringyyAC27ModelGraphSynchronizerTokenAELLVXE_tFyyXEfU_TA + 20 + 12 DVTFoundation 0x000000010b84fd68 $sSo19DVTModelObjectGraphC13DVTFoundationE34performBlockCoalescingModelChangesyxxyXElFyyXEfU_ + 104 + 13 DVTFoundation 0x000000010b8134bc $sSDySSSo8NSObjectCGIgo_ACIego_TR + 20 + 14 DVTFoundation 0x000000010b84fa80 $sIeg_IyB_TR + 20 + 15 DVTFoundation 0x000000010b67b24c __58-[DVTModelObjectGraph performBlockCoalescingModelChanges:]_block_invoke + 104 + 16 DVTFoundation 0x000000010b674cf8 -[DVTModelGraphTransactionScope performTransaction:] + 60 + 17 DVTFoundation 0x000000010b67b1c4 -[DVTModelObjectGraph performBlockCoalescingModelChanges:] + 148 + 18 DVTFoundation 0x000000010b850520 $sSo19DVTModelObjectGraphC13DVTFoundationE34performBlockCoalescingModelChangesyxxyXElF + 344 + 19 IDESwiftPackageCore 0x000000011a07d32c $s19IDESwiftPackageCore23IDESPMWorkspaceDelegateC38disableWorkspaceContentSynchronization33_033DB97E8C2A552F3158921835EE9F98LL6duringyyAC27ModelGraphSynchronizerTokenAELLVXE_tF + 444 + 20 IDESwiftPackageCore 0x000000011a086198 $s19IDESwiftPackageCore23IDESPMWorkspaceDelegateC27packageGraphDidFinishAction_8duration6resulty7SwiftPM12SPMWorkspaceC0bgJ0O_SdAG0oebgJ16ResolutionResultOtYaFTY4_ + 164 + 21 IDESwiftPackageCore 0x000000011a05ba31 $sIeAgH_ytIeAgHr_TRTATQ0_ + 1 + 22 SwiftPM 0x000000014800cda5 $s7SwiftPM12SPMWorkspaceC26packageGraphActionFinished33_918CA8CFEB8D3E06D2EEA2771EA5EA00LLyyAC07PackageE16ResolutionResultAELLVYaFTQ1_ + 1 + 23 SwiftPM 0x000000014800c6c1 $s7SwiftPM12SPMWorkspaceC46processPackageGraphActionsInBackgroundIfNeeded33_918CA8CFEB8D3E06D2EEA2771EA5EA00LL010canProcessefG0yAC11AffirmativeO_tFyyYaYbcfU1_yyYacfU0_TQ1_ + 1 + 24 SwiftPM 0x000000014805b871 $s7SwiftPM33SPMWorkspaceOrchestrationDelegateP27packageGraphDidFinishAction_8duration6resultyAA0C0C07PackagegJ0O_SdAA0cemgJ16ResolutionResultOtYaFTjTQ0_ + 1 + 25 SwiftPM 0x00000001480d07f1 $sxIeAgHr_xs5Error_pIegHrzo_s8SendableRzs5NeverORs_r0_lTRyt_Tg5TQ0_ + 1 + 26 SwiftPM 0x0000000148057ff9 $sxIeAgHr_xs5Error_pIegHrzo_s8SendableRzs5NeverORs_r0_lTRyt_Tg5TATQ0_ + 1 + 27 libswift_Concurrency.dylib 0x0000000271af883d _ZL23completeTaskWithClosurePN5swift12AsyncContextEPNS_10SwiftErrorE + 1 +) +** INTERNAL ERROR: Uncaught exception ** +Uncaught Exception: *** -[NSMutableArray insertObjects:atIndexes:]: count of array (62) differs from count of index set (61) +Stack: + 0 __exceptionPreprocess (in CoreFoundation) + 1 objc_exception_throw (in libobjc.A.dylib) + 2 -[__NSCFString characterAtIndex:].cold.1 (in CoreFoundation) + 3 -[NSMutableArray insertObjects:atIndexes:] (in CoreFoundation) + 4 __50-[IDEGroup insertGroupSubitems:atIndexes:context:]_block_invoke (in IDEFoundation) + 5 -[DVTModelObjectGraph performBlockCoalescingModelChanges:] (in DVTFoundation) + 6 -[IDEGroup insertGroupSubitems:atIndexes:context:] (in IDEFoundation) + 7 -[NSMutableArray(DVTFoundationClassAdditions) dvt_sortedInsertOfObjects:withComparator:] (in DVTFoundation) + 8 specialized IDESPMWorkspaceDelegate.registerDependencyFileReferences(_:modelGraphSynchronizerToken:) (in IDESwiftPackageCore) + 9 specialized IDESPMWorkspaceDelegate.dependencyPackagesDidUpdate(packages:graphHasErrors:revalidatedFilePathCaches:modelGraphSynchronizerToken:) (in IDESwiftPackageCore) + 10 closure #1 in IDESPMWorkspaceDelegate.packageGraphDidFinishAction(_:duration:result:) (in IDESwiftPackageCore) + 11 partial apply for closure #1 in IDESPMWorkspaceDelegate.disableWorkspaceContentSynchronization(during:) (in IDESwiftPackageCore) + 12 (in DVTFoundation) + 13 (in DVTFoundation) + 14 thunk for @escaping @callee_guaranteed () -> () (in DVTFoundation) + 15 __58-[DVTModelObjectGraph performBlockCoalescingModelChanges:]_block_invoke (in DVTFoundation) + 16 -[DVTModelGraphTransactionScope performTransaction:] (in DVTFoundation) + 17 -[DVTModelObjectGraph performBlockCoalescingModelChanges:] (in DVTFoundation) + 18 DVTModelObjectGraph.performBlockCoalescingModelChanges(_:) (in DVTFoundation) + 19 IDESPMWorkspaceDelegate.disableWorkspaceContentSynchronization(during:) (in IDESwiftPackageCore) + 20 IDESPMWorkspaceDelegate.packageGraphDidFinishAction(_:duration:result:) (in IDESwiftPackageCore) + 21 (in IDESwiftPackageCore) + 22 SPMWorkspace.packageGraphActionFinished(_:) (in SwiftPM) + 23 closure #2 in closure #3 in SPMWorkspace.processPackageGraphActionsInBackgroundIfNeeded(canProcessPackageGraphActions:) (in SwiftPM) + 24 (in SwiftPM) + 25 specialized thunk for @escaping @isolated(any) @callee_guaranteed @async () -> (@out A) (in SwiftPM) + 26 (in SwiftPM) + 27 completeTaskWithClosure(swift::AsyncContext*, swift::SwiftError*) (in libswift_Concurrency.dylib) + Command: /usr/bin/arch -arm64e xcrun xcodebuild -list + +``` +#0 RunResult.throwException (package:flutter_tools/src/base/process.dart:118:5) +#1 _DefaultProcessUtils.run (package:flutter_tools/src/base/process.dart:344:19) + +#2 XcodeProjectInterpreter.getInfo (package:flutter_tools/src/ios/xcodeproj.dart:334:30) + +#3 XcodeBasedProject.projectInfo (package:flutter_tools/src/xcode_project.dart:197:29) + +#4 XcodeBasedProject.buildSettingsForBuildInfo (package:flutter_tools/src/xcode_project.dart:217:36) + +#5 IosProject._parseProductName (package:flutter_tools/src/xcode_project.dart:647:55) + +#6 IosProject.productName (package:flutter_tools/src/xcode_project.dart:635:29) + +#7 BuildableIOSApp.fromProject (package:flutter_tools/src/ios/application_package.dart:117:33) + +#8 FlutterApplicationPackageFactory.getPackageForPlatform (package:flutter_tools/src/flutter_application_package.dart:80:15) + +#9 _BuildIOSSubCommand.buildableIOSApp. (package:flutter_tools/src/commands/build_ios.dart:707:9) + +#10 _BuildIOSSubCommand.runCommand (package:flutter_tools/src/commands/build_ios.dart:748:33) + +#11 FlutterCommand.run. (package:flutter_tools/src/runner/flutter_command.dart:1563:27) + +#12 AppContext.run. (package:flutter_tools/src/base/context.dart:154:19) + +#13 CommandRunner.runCommand (package:args/command_runner.dart:212:13) + +#14 FlutterCommandRunner.runCommand. (package:flutter_tools/src/runner/flutter_command_runner.dart:494:9) + +#15 AppContext.run. (package:flutter_tools/src/base/context.dart:154:19) + +#16 FlutterCommandRunner.runCommand (package:flutter_tools/src/runner/flutter_command_runner.dart:431:5) + +#17 run.. (package:flutter_tools/runner.dart:98:11) + +#18 AppContext.run. (package:flutter_tools/src/base/context.dart:154:19) + +#19 main (package:flutter_tools/executable.dart:102:3) + +``` + +## flutter doctor + +``` +[✓] Flutter (Channel stable, 3.32.3, on macOS 15.5 24F74 darwin-arm64, locale zh-Hans-CN) [429ms] + • Flutter version 3.32.3 on channel stable at /Users/liwei/flutter + • Upstream repository https://github.com/flutter/flutter.git + • Framework revision 5c1433509f (9 weeks ago), 2025-06-11 13:12:24 -0700 + • Engine revision 31c4875c7a + • Dart version 3.8.1 + • DevTools version 2.45.1 + +[!] Android toolchain - develop for Android devices (Android SDK version 36.0.0) [2.8s] + • Android SDK at /Users/liwei/Library/Android/sdk + • Platform android-36, build-tools 36.0.0 + • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java + This is the JDK bundled with the latest Android Studio installation on this machine. + To manually set the JDK path, use: `flutter config --jdk-dir="path/to/jdk"`. + • Java version OpenJDK Runtime Environment (build 21.0.4+-12422083-b607.1) + ! Some Android licenses not accepted. To resolve this, run: flutter doctor --android-licenses + +[✓] Xcode - develop for iOS and macOS (Xcode 16.2) [1,682ms] + • Xcode at /Applications/Xcode.app/Contents/Developer + • Build 16C5032a + • CocoaPods version 1.16.2 + +[✓] Chrome - develop for the web [6ms] + • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome + +[✓] Android Studio (version 2024.2) [5ms] + • Android Studio at /Applications/Android Studio.app/Contents + • Flutter plugin can be installed from: + 🔨 https://plugins.jetbrains.com/plugin/9212-flutter + • Dart plugin can be installed from: + 🔨 https://plugins.jetbrains.com/plugin/6351-dart + • Java version OpenJDK Runtime Environment (build 21.0.4+-12422083-b607.1) + +[✓] VS Code (version 1.103.0) [4ms] + • VS Code at /Applications/Visual Studio Code.app/Contents + • Flutter extension version 3.116.0 + +[✓] Connected device (5 available) [9.4s] + • RMX3310 (mobile) • a709b98b • android-arm64 • Android 14 (API 34) + • Voitrans的iPhoneXr (wireless) (mobile) • 00008020-000175D23C03002E • ios • iOS 18.6 22G86 + • iPhone XR (wireless) (mobile) • 00008020-000140140260802E • ios • iOS 18.5 22F76 + • macOS (desktop) • macos • darwin-arm64 • macOS 15.5 24F74 darwin-arm64 + • Chrome (web) • chrome • web-javascript • Google Chrome 139.0.7258.67 + ! Error: Browsing on the local area network for 李伟的iPad. Ensure the device is unlocked and attached with a cable or + associated with the same local area network as this Mac. + The device must be opted into Developer Mode to connect wirelessly. (code -27) + ! Error: Browsing on the local area network for liwei. Ensure the device is unlocked and attached with a cable or + associated with the same local area network as this Mac. + The device must be opted into Developer Mode to connect wirelessly. (code -27) + +[✓] Network resources [5.1s] + • All expected network resources are available. + +! Doctor found issues in 1 category. +``` diff --git a/local_plugins/qq_music/ios/qq_music.podspec b/local_plugins/qq_music/ios/qq_music.podspec index 91321e639..387d8cd1a 100644 --- a/local_plugins/qq_music/ios/qq_music.podspec +++ b/local_plugins/qq_music/ios/qq_music.podspec @@ -14,16 +14,20 @@ A new Flutter project. s.author = { 'Your Company' => 'email@example.com' } s.source = { :path => '.' } s.source_files = 'qq_music/Sources/qq_music/**/*' + s.public_header_files = 'qq_music/Sources/qq_music/include/**/*.h' s.dependency 'Flutter' s.platform = :ios, '12.0' + # Add QPlayAutoSDK framework + s.vendored_libraries = 'qq_music/Frameworks/QPlayAutoSDK/libQPlayAutoSDK.a' + s.source_files += 'qq_music/Frameworks/QPlayAutoSDK/Headers/include/**/*.h' + s.public_header_files += 'qq_music/Frameworks/QPlayAutoSDK/Headers/include/**/*.h' + s.xcconfig = { + 'HEADER_SEARCH_PATHS' => '$(SRCROOT)/../qq_music/Frameworks/QPlayAutoSDK/Headers/include', + 'LIBRARY_SEARCH_PATHS' => '$(SRCROOT)/../qq_music/Frameworks/QPlayAutoSDK' + } + # Flutter.framework does not contain a i386 slice. s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' } s.swift_version = '5.0' - - # If your plugin requires a privacy manifest, for example if it uses any - # required reason APIs, update the PrivacyInfo.xcprivacy file to describe your - # plugin's privacy impact, and then uncomment this line. For more information, - # see https://developer.apple.com/documentation/bundleresources/privacy_manifest_files - # s.resource_bundles = {'qq_music_privacy' => ['qq_music/Sources/qq_music/PrivacyInfo.xcprivacy']} end diff --git a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/Info.plist b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/Info.plist new file mode 100644 index 000000000..e6de23ef5 --- /dev/null +++ b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/Info.plist @@ -0,0 +1,47 @@ + + + + + AvailableLibraries + + + BinaryPath + libQPlayAutoSDK-x86_64.a + HeadersPath + Headers + LibraryIdentifier + ios-x86_64-simulator + LibraryPath + libQPlayAutoSDK-x86_64.a + SupportedArchitectures + + x86_64 + + SupportedPlatform + ios + SupportedPlatformVariant + simulator + + + BinaryPath + libQPlayAutoSDK-arm64.a + HeadersPath + Headers + LibraryIdentifier + ios-arm64 + LibraryPath + libQPlayAutoSDK-arm64.a + SupportedArchitectures + + arm64 + + SupportedPlatform + ios + + + CFBundlePackageType + XFWK + XCFrameworkFormatVersion + 1.0 + + diff --git a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-arm64/Headers/QPlayAutoSDK.h b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-arm64/Headers/QPlayAutoSDK.h new file mode 100644 index 000000000..ebdf38741 --- /dev/null +++ b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-arm64/Headers/QPlayAutoSDK.h @@ -0,0 +1,7 @@ +// +// QPlayAutoSDK.h +// QPlayAutoSDK Umbrella Header +// + +#import "include/QPlayAutoSDK.h" +#import "include/QPlayAutoDefine.h" diff --git a/local_plugins/qq_music/ios/qq_music/ios-sdk/QPlayAutoSDK/Headers/include/QPlayAutoDefine.h b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-arm64/Headers/include/QPlayAutoDefine.h similarity index 100% rename from local_plugins/qq_music/ios/qq_music/ios-sdk/QPlayAutoSDK/Headers/include/QPlayAutoDefine.h rename to local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-arm64/Headers/include/QPlayAutoDefine.h diff --git a/local_plugins/qq_music/ios/qq_music/ios-sdk/QPlayAutoSDK/Headers/include/QPlayAutoSDK.h b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-arm64/Headers/include/QPlayAutoSDK.h similarity index 100% rename from local_plugins/qq_music/ios/qq_music/ios-sdk/QPlayAutoSDK/Headers/include/QPlayAutoSDK.h rename to local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-arm64/Headers/include/QPlayAutoSDK.h diff --git a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-arm64/Headers/module.modulemap b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-arm64/Headers/module.modulemap new file mode 100644 index 000000000..93a770bad --- /dev/null +++ b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-arm64/Headers/module.modulemap @@ -0,0 +1,5 @@ +framework module QPlayAutoSDK { + umbrella header "QPlayAutoSDK.h" + export * + module * { export * } +} diff --git a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-arm64/libQPlayAutoSDK-arm64.a b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-arm64/libQPlayAutoSDK-arm64.a new file mode 100644 index 000000000..727801538 Binary files /dev/null and b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-arm64/libQPlayAutoSDK-arm64.a differ diff --git a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-x86_64-simulator/Headers/QPlayAutoSDK.h b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-x86_64-simulator/Headers/QPlayAutoSDK.h new file mode 100644 index 000000000..ebdf38741 --- /dev/null +++ b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-x86_64-simulator/Headers/QPlayAutoSDK.h @@ -0,0 +1,7 @@ +// +// QPlayAutoSDK.h +// QPlayAutoSDK Umbrella Header +// + +#import "include/QPlayAutoSDK.h" +#import "include/QPlayAutoDefine.h" diff --git a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-x86_64-simulator/Headers/include/QPlayAutoDefine.h b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-x86_64-simulator/Headers/include/QPlayAutoDefine.h new file mode 100644 index 000000000..b1ebee15a --- /dev/null +++ b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-x86_64-simulator/Headers/include/QPlayAutoDefine.h @@ -0,0 +1,238 @@ +// +// QPlayAutoDefine.h +// QPlayAutoSDK +// +// Created by travisli(李鞠佑) on 2018/11/17. +// Copyright © 2018年 腾讯音乐. All rights reserved. +// + +#ifndef QPlayAutoDefine_h +#define QPlayAutoDefine_h + +extern NSString *const kQPlayAutoItemRootID; +extern NSString *const kQPlayAutoArgument_Count; +extern NSString *const kQPlayAutoArgument_PageIndex; +extern NSString *const kQPlayAutoArgument_ParentID; +extern NSString *const kQPlayAutoArgument_Lists; +extern NSString *const kQPlayAutoArgument_PlayMode; +extern NSString *const kQPlayAutoArgument_IsFav; +extern NSString *const kQPlayAutoArgument_Position; +extern NSString *const kQPlayAutoArgument_Song; +extern NSString *const kQPlayAutoArgument_SongID; +extern NSString *const kQPlayAutoArgument_State; +extern NSString *const kQPlayAutoArgument_Error; + +/* + QPlayAuto错误 + */ +typedef NS_ENUM(NSUInteger, QPlayAutoError) +{ + QPlayAuto_OK=0, //成功 + QPlayAuto_QueryAutoFailed=100, //查询车机信息失败 + QPlayAuto_QueryMobileFailed=101, //查询移动设备失败 + QPlayAuto_QuerySongsFailed_WithoutID=102, //查询歌单数据失败,父 ID 不存在 + QPlayAuto_QuerySongsFailed_NoNetwork=103, //查询歌单数据失败,移动设备网络不通,无法下载数据 + QPlayAuto_QuerySongsFailed_Unknow=104, //查询歌单数据失败,原因未知 + QPlayAuto_SongIDError=105, //歌曲 ID 不存在 + QPlayAuto_ReadError=106, //读取数据错误 + QPlayAuto_ParamError=107, //参数错误 + QPlayAuto_SystemError=108, //系统调用错误 + QPlayAuto_CopyRightError=109, //无法播放,没有版权 + QPlayAuto_LoginError=110, //无法读取,没有登录 + QPlayAuto_PcmRepeat=111, //PCM 请求重复 + QPlayAuto_NoPermission=112, //没有权限 + QPlayAuto_NeedBuy = 113, //无法播放(数字专辑) + QPlayAuto_NotSupportFormat=114, //无法播放(不支持格式) + QPlayAuto_NeedAuth=115, //需要授权 + QPlayAuto_NeedVIP = 116, //无法播放(需要购买VIP) + QPlayAuto_TryListen = 117, //试听歌曲,购买听完整版 + QPlayAuto_TrafficAlert = 118, //无法播放(流量弹窗阻断) + QPlayAuto_OnlyWifi = 119, //无法播放(仅Wifi弹窗阻断) + QPlayAuto_AlreadyConnected=120, //已经连接车机 + QPlayAuto_SeekError = 121, //拖拽进度错误 + QPlayAuto_NoListenRight = 122, //无法播放(无版权) + QPlayAuto_SongNotMatch=123, //歌曲不匹配 + QPlayAuto_Disconnect=124, //连接已断开 +}; + +/** + QPlayAuto连接状态 + */ +typedef NS_ENUM(NSUInteger, QPlayAutoConnectState) +{ + QPlayAutoConnectState_Connected = 0, //连接成功 + QPlayAutoConnectState_Disconnect = 1, //断开连接 + QPlayAutoConnectState_Failed = -1, //连接失败 + QPlayAutoConnectState_Cancel = -2, //连接取消 +}; + +/* + QPlayAutoListItem类型 + */ +typedef NS_ENUM(NSUInteger, QPlayAutoListItemType) +{ + QPlayAutoListItemType_Song = 1, //歌曲 + QPlayAutoListItemType_Normal = 2, //普通目录 + QPlayAutoListItemType_Radio = 3, //电台 + QPlayAutoListItemType_Folder = 4, //歌单 + QPlayAutoListItemType_Album = 5, //专辑 +}; + +typedef NS_ENUM(NSUInteger, QPlayAutoSongListType) +{ + QPlayAutoSongListType_Daily = 108, //每日30首 +}; + + +/** + QPlayAuto播放状态 + */ +typedef NS_ENUM(NSUInteger, QPlayAutoPlayState) +{ + QPlayAutoPlayState_Stop=0, //停止 + QPlayAutoPlayState_Playing=1, //播放 + QPlayAutoPlayState_Pause=2 //暂停 +}; + +typedef NS_ENUM(NSInteger, QPlayAutoAssenceMode) +{ + QPlayAutoAssenceMode_Full = 0, // 默认整首播放 + QPlayAutoAssenceMode_Part = 1, // 仅播放精华片段 +}; + +/** + QPlayAuto播放模式 + */ +typedef NS_ENUM(NSUInteger, QPlayAutoPlayMode) +{ + QPlayAutoPlayMode_SequenceCircle=0, //列表循环 + QPlayAutoPlayMode_SingleCircle=1, //单曲循环 + QPlayAutoPlayMode_RandomCircle=2 //随机播放 +}; + +/** + QPlayAuto搜索类型 + */ +typedef NS_ENUM(NSInteger, QPlayAutoSearchType) +{ + QPlayAutoSearchType_Song = 0, //歌曲 + QPlayAutoSearchType_Album = 2, //专辑 + QPlayAutoSearchType_Folder = 3, //歌单 + QPlayAutoSearchType_Composite = 100, //综合 +}; + +typedef NS_ENUM(NSInteger, QPlayAutoVipState) +{ + QPlayAutoVipState_Normal = 0, + QPlayAutoVipState_VIP = 1, + QPlayAutoVipState_SVIP = 2, +}; + +/** + 第三方App信息 + */ +@interface QPlayAutoAppInfo : NSObject + +@property (nonatomic,strong) NSString *deviceId; //AppId +@property (nonatomic,assign) NSInteger deviceType; +@property (nonatomic,strong) NSString *scheme; //跳转scheme +@property (nonatomic,strong) NSString *brand; //品牌 +@property (nonatomic,strong) NSString *name; //名称 +@property (nonatomic,strong) NSString *appId; //名称 +@property (nonatomic,strong) NSString *secretKey; //私钥 +@property (nonatomic,strong) NSString *bundleId; //bundleId +@property (nonatomic,assign) NSInteger qmCommandPort; //Q音接收命令端口 +@property (nonatomic,strong) NSString *qmHost; //Q音接收命令IP +@property (nonatomic,strong) NSDate *lastConnectDate;//上次连接的日期 +@end + +@interface QPlayAutoSinger : NSObject +@property (nonatomic,strong) NSString *ID; //ID +@property (nonatomic,strong) NSString *Mid; //Mid +@property (nonatomic,strong) NSString *name; //名称 +@end + + +/* + QPlayAuto列表项(歌单、电台、排行榜、歌曲、etc) + */ +@interface QPlayAutoListItem: NSObject + +@property (nonatomic,strong) NSString *ID; //ID +@property (nonatomic,strong) NSString *Name; //名称 +@property (nonatomic,strong) NSString *SubName; //副标题 +@property (nonatomic,strong) QPlayAutoSinger *singer; //歌手 +@property (nonatomic,strong) NSString *Album; //专辑 +@property (nonatomic,strong) NSString *Mid; +@property (nonatomic,assign) QPlayAutoVipState vipState; +@property (nonatomic,assign) QPlayAutoListItemType Type; +@property (nonatomic,assign) NSInteger Duration; //时长 +@property (nonatomic,strong) NSString *CoverUri; //封面Uri +@property (nonatomic,assign) NSInteger totalCount; //总数 +@property (nonatomic,assign) BOOL isFav; //是否收藏 +@property (nonatomic,assign) BOOL isOrigin; //是否原唱 +@property (nonatomic,assign) BOOL isNoAudioSource; //无音源 +@property (nonatomic,strong) NSMutableArray *items; //子列表 +@property (nonatomic,weak) QPlayAutoListItem *parentItem; //父节点 + +@property (nonatomic,assign) BOOL isTryListen; //是否试听歌曲 +@property (nonatomic,readonly) BOOL isSong; //歌曲 +@property (nonatomic,readonly) BOOL isFolder;//歌单 +@property (nonatomic,readonly) BOOL isAlbum; //专辑 +@property (nonatomic,readonly) BOOL isRadio; //电台 +@property (nonatomic,readonly) BOOL isDirectory; //普通目录 + +@property (nonatomic,readonly) BOOL isVIP; //VIP歌曲 +@property (nonatomic,readonly) BOOL isSVIP; //SVIP歌曲 + +- (instancetype)initWithDictionary:(NSDictionary*)dict; +- (instancetype)initSongWithId:(NSString *)identifier isFav:(BOOL)isFav; +- (instancetype)initWithId:(NSString *)identifier type:(QPlayAutoListItemType)type; + +//是否是根节点 +- (BOOL)isRoot; + +//是否有更多 +- (BOOL)hasMore; + +- (QPlayAutoListItem*)findItemWithID:(NSString*)ID; + +@end + +/** + QPlayAuto请求回调 + + @param success 是否成功 + @param dict 结果Dictionary + */ +typedef void (^QPlayAutoRequestFinishBlock)(BOOL success, NSDictionary *dict); + + +@interface QPlayAutoRequestBase : NSObject + +/** 请求类型 */ +@property (nonatomic, assign) int type; + +@end + +@interface QPlayAutoSentence : NSObject +@property (nonatomic, assign) NSInteger startTime; +@property (nonatomic, assign) NSInteger duration; +@property (nonatomic, strong) NSString *text; +@property (nonatomic, readonly) NSString *startTimeText; +@property (nonatomic, readonly) NSString *endTimeText; +@end + +@interface QPlayAutoLyric : NSObject +@property(nonatomic,assign) BOOL isTxtType;//歌词是不是纯文本的歌词,没有时间标记 +@property(nonatomic,strong) NSString *songId; +@property(nonatomic,strong) NSString *songName; +@property(nonatomic,strong) NSString *singerName; +@property(nonatomic,strong) NSString *albumName; +@property(nonatomic,readonly) NSString *text;//所有歌词文本 +@property(nonatomic,strong) NSArray *sentences; +- (NSString *)sentenceAtTime:(NSTimeInterval)time; +@end + + +#endif /* QPlayAutoDefine_h */ diff --git a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-x86_64-simulator/Headers/include/QPlayAutoSDK.h b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-x86_64-simulator/Headers/include/QPlayAutoSDK.h new file mode 100644 index 000000000..da332dc87 --- /dev/null +++ b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-x86_64-simulator/Headers/include/QPlayAutoSDK.h @@ -0,0 +1,188 @@ +// +// QPlayAutoSDK.h +// QPlayAutoSDK +// +// Created by travisli(李鞠佑) on 2018/11/5. +// Copyright © 2018年 腾讯音乐. All rights reserved. +// + +#import +#import "QPlayAutoDefine.h" + +#define APP_DEVICE_TYPE (3) + +NS_ASSUME_NONNULL_BEGIN + +typedef void (^QPlayAutoResultItemsBlock)(NSInteger errorCode,NSArray *_Nullable items); +typedef void (^QPlayAutoResultParentItemBlock)(NSInteger errorCode,QPlayAutoListItem *parentItem); + +extern NSString const * QPlayAutoSDKVersion; + +@protocol QPlayAutoSDKDelegate + +//连接状态变化回调 +- (void)onQPlayAutoConnectStateChanged:(QPlayAutoConnectState)newState; +//播放状态状态变化回调 +- (void)onQPlayAutoPlayStateChanged:(QPlayAutoPlayState)playState song:(QPlayAutoListItem *)song position:(NSInteger)position; +//歌曲播放进度 +- (void)onQPlayAutoPlayProgressChanged:(QPlayAutoListItem *)song progress:(NSTimeInterval)progress duration:(NSTimeInterval)duration; +//歌曲收藏状态变化 +- (void)onSongFavoriteStateChange:(NSString*)songID isFavorite:(BOOL)isFavorite; +//播放状态事件变化 +- (void)onPlayModeChange:(QPlayAutoPlayMode)playMode; +//定时关闭事件 +- (void)onPlayPausedByTimeoff; +//登陆状态 +- (void)onLoginStateDidChanged:(BOOL)isLoginOK; +@end + + + +@interface QPlayAutoSDK : NSObject + +/// 注册App +/// @param name 名称 +/// @param brand 品牌 +/// @param deviceId ? +/// @param scheme 授权成功后Q音跳转合作方的scheme +/// @param appId Q音分配的Id +/// @param secretKey 合作方私钥 +/// @param bundleId 合作方包名 ++ (void)registerAppWithName:(NSString *)name brand:(NSString *)brand deviceId:(NSString *)deviceId scheme:(NSString *)scheme appId:(NSString *)appId secretKey:(NSString *)secretKey bundleId:(NSString *)bundleId; + +/// 播放状态 ++ (QPlayAutoPlayMode)currentPlayMode; +/// 当前歌曲 ++ (QPlayAutoListItem *_Nullable)currentSong; +/// 当前播放状态 ++ (QPlayAutoPlayState)currentPlayState; +/// 当前播放进度 ++ (NSTimeInterval)currentProgress; +/// QQ音乐是否登录 ++ (BOOL)isLoginOK; +/// 检查QQ音乐是否已安装 ++ (BOOL)isQQMusicInstalled; +/// 是否已连接 ++ (BOOL)isConnected; +/// 连接中 ++ (BOOL)isConnecting; +///QQ音乐设备信息 ++ (NSDictionary *)deviceInfo; + ++(NSString *)openId; ++(NSString *)openToken; + + +///是否可以处理回调url ++ (BOOL)canHandleOpenURL:(NSURL *)url; +///处理回调url ++ (BOOL)handleOpenURL:(NSURL *)url; + +/// 回调代理 ++ (void)setDelegate:(id) delegate; + + +/// 拉端连接QPlay +/// - Parameter forceLogin: 是否强制登录 ++ (void)connectAndForceLogin:(BOOL)forceLogin; +/// 停止 ++ (void)stop; + + +/// 二次热启动连接(需要联系Q音打开此功能才能使用) +/// - Parameters: +/// - timeout: 超时时间 +/// - completion: 回调 ++ (void)reconnectWithTimeout:(NSTimeInterval)timeout completion:(QPlayAutoRequestFinishBlock)completion; + +/// 跳转QQ音乐登录 +/// @param bundleId 合作方bundleId +/// @param callbackUrl 跳转合作方url ++ (BOOL)loginQQMusicWithBundleId:(NSString *)bundleId callbackUrl:(NSString *)callbackUrl; + + +/// 获取数据 +/// @param parent 父 +/// @param pageIndex 页码 +/// @param pageSize 页大小 +/// @param completion 回调 ++ (void)getDataItemsFromParent:(QPlayAutoListItem *)parent pageIndex:(NSUInteger)pageIndex pageSize:(NSUInteger)pageSize completion:(QPlayAutoResultParentItemBlock)completion; + + +/// 设置播放模式 +/// @param playMode 播放模式 +/// @param block 回调 ++ (NSInteger)setPlayMode:(QPlayAutoPlayMode)playMode callback:(QPlayAutoRequestFinishBlock _Nullable )block; + + +/// 设置播放整首还是高潮 +/// @param assencceMode 高潮还是整首 +/// @param block 回调 ++ (NSInteger)setAssenceMode:(QPlayAutoAssenceMode)assencceMode callback:(QPlayAutoRequestFinishBlock _Nullable )block; + +/// 收藏/取消收藏(歌曲id) +/// @param song 歌曲 +/// @param isFavorite 收藏/取消收藏 +/// @param completion 回调 ++ (void)setFavoriteStateWithSong:(QPlayAutoListItem *)song isFavorite:(BOOL)isFavorite completion:(void (^)(NSInteger errorCode))completion; + +/// 播放歌曲 +/// @param songList 歌曲列表 +/// @param playIndex 播放索引 +/// @param completion 回调 ++ (void)playAtIndex:(NSArray *)songList playIndex:(NSInteger)playIndex completion:(void (^)(NSInteger errorCode))completion; + + +/// 通过歌曲Mid列表播放歌曲 +/// @param songMidList 歌曲Mid列表 +/// @param playIndex 播放索引 +/// @param completion 回调 ++ (void)playSongMidAtIndex:(NSArray *)songMidList playIndex:(NSInteger)playIndex completion:(void (^)(NSInteger errorCode))completion; + + +///播放下一首 ++ (void)playerPlayNextWithCompletion:(void (^)(NSInteger errorCode))completion; + +///播放上一首 ++ (void)playerPlayPrevWithCompletion:(void (^)(NSInteger errorCode))completion; + +///播放暂停 ++ (void)playerPlayPause; + +///播放恢复 ++ (void)playerPlayResumeWithCompletion:(void (^)(NSInteger errorCode))completion; + +///Seek到指定位置 ++ (void)playerSeek:(NSInteger)position; + + +/// 搜索歌曲 +/// @param keyword 关键词 +/// @param type 搜索类型 +/// @param firstPage 是否第一页 +/// @param completion 回调 ++ (NSInteger)search:(NSString *)keyword + type:(QPlayAutoSearchType)type + firstPage:(BOOL)firstPage + completion:(QPlayAutoResultItemsBlock)completion; + +/// 相似歌曲 +/// @param song 歌曲 +/// @param completion 回调 ++ (void)requestSimilarWithSong:(QPlayAutoListItem *)song completion:(QPlayAutoResultItemsBlock)completion; + + +/// 查询歌词 +/// @param song 歌曲 +/// @param completion 回调 ++ (void)requestLyricWithSong:(QPlayAutoListItem *)song completion:(void (^)(NSInteger errorCode,QPlayAutoLyric *_Nullable lyric))completion; + + +/// 获取特定歌曲列表 +/// @param type 列表类型 +/// @param completion 回调 ++ (void)requestSonglistWithType:(QPlayAutoSongListType)type completion:(QPlayAutoResultItemsBlock)completion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-x86_64-simulator/Headers/module.modulemap b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-x86_64-simulator/Headers/module.modulemap new file mode 100644 index 000000000..93a770bad --- /dev/null +++ b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-x86_64-simulator/Headers/module.modulemap @@ -0,0 +1,5 @@ +framework module QPlayAutoSDK { + umbrella header "QPlayAutoSDK.h" + export * + module * { export * } +} diff --git a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-x86_64-simulator/libQPlayAutoSDK-x86_64.a b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-x86_64-simulator/libQPlayAutoSDK-x86_64.a new file mode 100644 index 000000000..2d6587ba2 Binary files /dev/null and b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK.xcframework/ios-x86_64-simulator/libQPlayAutoSDK-x86_64.a differ diff --git a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK/Headers/include/QPlayAutoDefine.h b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK/Headers/include/QPlayAutoDefine.h new file mode 100644 index 000000000..b1ebee15a --- /dev/null +++ b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK/Headers/include/QPlayAutoDefine.h @@ -0,0 +1,238 @@ +// +// QPlayAutoDefine.h +// QPlayAutoSDK +// +// Created by travisli(李鞠佑) on 2018/11/17. +// Copyright © 2018年 腾讯音乐. All rights reserved. +// + +#ifndef QPlayAutoDefine_h +#define QPlayAutoDefine_h + +extern NSString *const kQPlayAutoItemRootID; +extern NSString *const kQPlayAutoArgument_Count; +extern NSString *const kQPlayAutoArgument_PageIndex; +extern NSString *const kQPlayAutoArgument_ParentID; +extern NSString *const kQPlayAutoArgument_Lists; +extern NSString *const kQPlayAutoArgument_PlayMode; +extern NSString *const kQPlayAutoArgument_IsFav; +extern NSString *const kQPlayAutoArgument_Position; +extern NSString *const kQPlayAutoArgument_Song; +extern NSString *const kQPlayAutoArgument_SongID; +extern NSString *const kQPlayAutoArgument_State; +extern NSString *const kQPlayAutoArgument_Error; + +/* + QPlayAuto错误 + */ +typedef NS_ENUM(NSUInteger, QPlayAutoError) +{ + QPlayAuto_OK=0, //成功 + QPlayAuto_QueryAutoFailed=100, //查询车机信息失败 + QPlayAuto_QueryMobileFailed=101, //查询移动设备失败 + QPlayAuto_QuerySongsFailed_WithoutID=102, //查询歌单数据失败,父 ID 不存在 + QPlayAuto_QuerySongsFailed_NoNetwork=103, //查询歌单数据失败,移动设备网络不通,无法下载数据 + QPlayAuto_QuerySongsFailed_Unknow=104, //查询歌单数据失败,原因未知 + QPlayAuto_SongIDError=105, //歌曲 ID 不存在 + QPlayAuto_ReadError=106, //读取数据错误 + QPlayAuto_ParamError=107, //参数错误 + QPlayAuto_SystemError=108, //系统调用错误 + QPlayAuto_CopyRightError=109, //无法播放,没有版权 + QPlayAuto_LoginError=110, //无法读取,没有登录 + QPlayAuto_PcmRepeat=111, //PCM 请求重复 + QPlayAuto_NoPermission=112, //没有权限 + QPlayAuto_NeedBuy = 113, //无法播放(数字专辑) + QPlayAuto_NotSupportFormat=114, //无法播放(不支持格式) + QPlayAuto_NeedAuth=115, //需要授权 + QPlayAuto_NeedVIP = 116, //无法播放(需要购买VIP) + QPlayAuto_TryListen = 117, //试听歌曲,购买听完整版 + QPlayAuto_TrafficAlert = 118, //无法播放(流量弹窗阻断) + QPlayAuto_OnlyWifi = 119, //无法播放(仅Wifi弹窗阻断) + QPlayAuto_AlreadyConnected=120, //已经连接车机 + QPlayAuto_SeekError = 121, //拖拽进度错误 + QPlayAuto_NoListenRight = 122, //无法播放(无版权) + QPlayAuto_SongNotMatch=123, //歌曲不匹配 + QPlayAuto_Disconnect=124, //连接已断开 +}; + +/** + QPlayAuto连接状态 + */ +typedef NS_ENUM(NSUInteger, QPlayAutoConnectState) +{ + QPlayAutoConnectState_Connected = 0, //连接成功 + QPlayAutoConnectState_Disconnect = 1, //断开连接 + QPlayAutoConnectState_Failed = -1, //连接失败 + QPlayAutoConnectState_Cancel = -2, //连接取消 +}; + +/* + QPlayAutoListItem类型 + */ +typedef NS_ENUM(NSUInteger, QPlayAutoListItemType) +{ + QPlayAutoListItemType_Song = 1, //歌曲 + QPlayAutoListItemType_Normal = 2, //普通目录 + QPlayAutoListItemType_Radio = 3, //电台 + QPlayAutoListItemType_Folder = 4, //歌单 + QPlayAutoListItemType_Album = 5, //专辑 +}; + +typedef NS_ENUM(NSUInteger, QPlayAutoSongListType) +{ + QPlayAutoSongListType_Daily = 108, //每日30首 +}; + + +/** + QPlayAuto播放状态 + */ +typedef NS_ENUM(NSUInteger, QPlayAutoPlayState) +{ + QPlayAutoPlayState_Stop=0, //停止 + QPlayAutoPlayState_Playing=1, //播放 + QPlayAutoPlayState_Pause=2 //暂停 +}; + +typedef NS_ENUM(NSInteger, QPlayAutoAssenceMode) +{ + QPlayAutoAssenceMode_Full = 0, // 默认整首播放 + QPlayAutoAssenceMode_Part = 1, // 仅播放精华片段 +}; + +/** + QPlayAuto播放模式 + */ +typedef NS_ENUM(NSUInteger, QPlayAutoPlayMode) +{ + QPlayAutoPlayMode_SequenceCircle=0, //列表循环 + QPlayAutoPlayMode_SingleCircle=1, //单曲循环 + QPlayAutoPlayMode_RandomCircle=2 //随机播放 +}; + +/** + QPlayAuto搜索类型 + */ +typedef NS_ENUM(NSInteger, QPlayAutoSearchType) +{ + QPlayAutoSearchType_Song = 0, //歌曲 + QPlayAutoSearchType_Album = 2, //专辑 + QPlayAutoSearchType_Folder = 3, //歌单 + QPlayAutoSearchType_Composite = 100, //综合 +}; + +typedef NS_ENUM(NSInteger, QPlayAutoVipState) +{ + QPlayAutoVipState_Normal = 0, + QPlayAutoVipState_VIP = 1, + QPlayAutoVipState_SVIP = 2, +}; + +/** + 第三方App信息 + */ +@interface QPlayAutoAppInfo : NSObject + +@property (nonatomic,strong) NSString *deviceId; //AppId +@property (nonatomic,assign) NSInteger deviceType; +@property (nonatomic,strong) NSString *scheme; //跳转scheme +@property (nonatomic,strong) NSString *brand; //品牌 +@property (nonatomic,strong) NSString *name; //名称 +@property (nonatomic,strong) NSString *appId; //名称 +@property (nonatomic,strong) NSString *secretKey; //私钥 +@property (nonatomic,strong) NSString *bundleId; //bundleId +@property (nonatomic,assign) NSInteger qmCommandPort; //Q音接收命令端口 +@property (nonatomic,strong) NSString *qmHost; //Q音接收命令IP +@property (nonatomic,strong) NSDate *lastConnectDate;//上次连接的日期 +@end + +@interface QPlayAutoSinger : NSObject +@property (nonatomic,strong) NSString *ID; //ID +@property (nonatomic,strong) NSString *Mid; //Mid +@property (nonatomic,strong) NSString *name; //名称 +@end + + +/* + QPlayAuto列表项(歌单、电台、排行榜、歌曲、etc) + */ +@interface QPlayAutoListItem: NSObject + +@property (nonatomic,strong) NSString *ID; //ID +@property (nonatomic,strong) NSString *Name; //名称 +@property (nonatomic,strong) NSString *SubName; //副标题 +@property (nonatomic,strong) QPlayAutoSinger *singer; //歌手 +@property (nonatomic,strong) NSString *Album; //专辑 +@property (nonatomic,strong) NSString *Mid; +@property (nonatomic,assign) QPlayAutoVipState vipState; +@property (nonatomic,assign) QPlayAutoListItemType Type; +@property (nonatomic,assign) NSInteger Duration; //时长 +@property (nonatomic,strong) NSString *CoverUri; //封面Uri +@property (nonatomic,assign) NSInteger totalCount; //总数 +@property (nonatomic,assign) BOOL isFav; //是否收藏 +@property (nonatomic,assign) BOOL isOrigin; //是否原唱 +@property (nonatomic,assign) BOOL isNoAudioSource; //无音源 +@property (nonatomic,strong) NSMutableArray *items; //子列表 +@property (nonatomic,weak) QPlayAutoListItem *parentItem; //父节点 + +@property (nonatomic,assign) BOOL isTryListen; //是否试听歌曲 +@property (nonatomic,readonly) BOOL isSong; //歌曲 +@property (nonatomic,readonly) BOOL isFolder;//歌单 +@property (nonatomic,readonly) BOOL isAlbum; //专辑 +@property (nonatomic,readonly) BOOL isRadio; //电台 +@property (nonatomic,readonly) BOOL isDirectory; //普通目录 + +@property (nonatomic,readonly) BOOL isVIP; //VIP歌曲 +@property (nonatomic,readonly) BOOL isSVIP; //SVIP歌曲 + +- (instancetype)initWithDictionary:(NSDictionary*)dict; +- (instancetype)initSongWithId:(NSString *)identifier isFav:(BOOL)isFav; +- (instancetype)initWithId:(NSString *)identifier type:(QPlayAutoListItemType)type; + +//是否是根节点 +- (BOOL)isRoot; + +//是否有更多 +- (BOOL)hasMore; + +- (QPlayAutoListItem*)findItemWithID:(NSString*)ID; + +@end + +/** + QPlayAuto请求回调 + + @param success 是否成功 + @param dict 结果Dictionary + */ +typedef void (^QPlayAutoRequestFinishBlock)(BOOL success, NSDictionary *dict); + + +@interface QPlayAutoRequestBase : NSObject + +/** 请求类型 */ +@property (nonatomic, assign) int type; + +@end + +@interface QPlayAutoSentence : NSObject +@property (nonatomic, assign) NSInteger startTime; +@property (nonatomic, assign) NSInteger duration; +@property (nonatomic, strong) NSString *text; +@property (nonatomic, readonly) NSString *startTimeText; +@property (nonatomic, readonly) NSString *endTimeText; +@end + +@interface QPlayAutoLyric : NSObject +@property(nonatomic,assign) BOOL isTxtType;//歌词是不是纯文本的歌词,没有时间标记 +@property(nonatomic,strong) NSString *songId; +@property(nonatomic,strong) NSString *songName; +@property(nonatomic,strong) NSString *singerName; +@property(nonatomic,strong) NSString *albumName; +@property(nonatomic,readonly) NSString *text;//所有歌词文本 +@property(nonatomic,strong) NSArray *sentences; +- (NSString *)sentenceAtTime:(NSTimeInterval)time; +@end + + +#endif /* QPlayAutoDefine_h */ diff --git a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK/Headers/include/QPlayAutoSDK.h b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK/Headers/include/QPlayAutoSDK.h new file mode 100644 index 000000000..da332dc87 --- /dev/null +++ b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK/Headers/include/QPlayAutoSDK.h @@ -0,0 +1,188 @@ +// +// QPlayAutoSDK.h +// QPlayAutoSDK +// +// Created by travisli(李鞠佑) on 2018/11/5. +// Copyright © 2018年 腾讯音乐. All rights reserved. +// + +#import +#import "QPlayAutoDefine.h" + +#define APP_DEVICE_TYPE (3) + +NS_ASSUME_NONNULL_BEGIN + +typedef void (^QPlayAutoResultItemsBlock)(NSInteger errorCode,NSArray *_Nullable items); +typedef void (^QPlayAutoResultParentItemBlock)(NSInteger errorCode,QPlayAutoListItem *parentItem); + +extern NSString const * QPlayAutoSDKVersion; + +@protocol QPlayAutoSDKDelegate + +//连接状态变化回调 +- (void)onQPlayAutoConnectStateChanged:(QPlayAutoConnectState)newState; +//播放状态状态变化回调 +- (void)onQPlayAutoPlayStateChanged:(QPlayAutoPlayState)playState song:(QPlayAutoListItem *)song position:(NSInteger)position; +//歌曲播放进度 +- (void)onQPlayAutoPlayProgressChanged:(QPlayAutoListItem *)song progress:(NSTimeInterval)progress duration:(NSTimeInterval)duration; +//歌曲收藏状态变化 +- (void)onSongFavoriteStateChange:(NSString*)songID isFavorite:(BOOL)isFavorite; +//播放状态事件变化 +- (void)onPlayModeChange:(QPlayAutoPlayMode)playMode; +//定时关闭事件 +- (void)onPlayPausedByTimeoff; +//登陆状态 +- (void)onLoginStateDidChanged:(BOOL)isLoginOK; +@end + + + +@interface QPlayAutoSDK : NSObject + +/// 注册App +/// @param name 名称 +/// @param brand 品牌 +/// @param deviceId ? +/// @param scheme 授权成功后Q音跳转合作方的scheme +/// @param appId Q音分配的Id +/// @param secretKey 合作方私钥 +/// @param bundleId 合作方包名 ++ (void)registerAppWithName:(NSString *)name brand:(NSString *)brand deviceId:(NSString *)deviceId scheme:(NSString *)scheme appId:(NSString *)appId secretKey:(NSString *)secretKey bundleId:(NSString *)bundleId; + +/// 播放状态 ++ (QPlayAutoPlayMode)currentPlayMode; +/// 当前歌曲 ++ (QPlayAutoListItem *_Nullable)currentSong; +/// 当前播放状态 ++ (QPlayAutoPlayState)currentPlayState; +/// 当前播放进度 ++ (NSTimeInterval)currentProgress; +/// QQ音乐是否登录 ++ (BOOL)isLoginOK; +/// 检查QQ音乐是否已安装 ++ (BOOL)isQQMusicInstalled; +/// 是否已连接 ++ (BOOL)isConnected; +/// 连接中 ++ (BOOL)isConnecting; +///QQ音乐设备信息 ++ (NSDictionary *)deviceInfo; + ++(NSString *)openId; ++(NSString *)openToken; + + +///是否可以处理回调url ++ (BOOL)canHandleOpenURL:(NSURL *)url; +///处理回调url ++ (BOOL)handleOpenURL:(NSURL *)url; + +/// 回调代理 ++ (void)setDelegate:(id) delegate; + + +/// 拉端连接QPlay +/// - Parameter forceLogin: 是否强制登录 ++ (void)connectAndForceLogin:(BOOL)forceLogin; +/// 停止 ++ (void)stop; + + +/// 二次热启动连接(需要联系Q音打开此功能才能使用) +/// - Parameters: +/// - timeout: 超时时间 +/// - completion: 回调 ++ (void)reconnectWithTimeout:(NSTimeInterval)timeout completion:(QPlayAutoRequestFinishBlock)completion; + +/// 跳转QQ音乐登录 +/// @param bundleId 合作方bundleId +/// @param callbackUrl 跳转合作方url ++ (BOOL)loginQQMusicWithBundleId:(NSString *)bundleId callbackUrl:(NSString *)callbackUrl; + + +/// 获取数据 +/// @param parent 父 +/// @param pageIndex 页码 +/// @param pageSize 页大小 +/// @param completion 回调 ++ (void)getDataItemsFromParent:(QPlayAutoListItem *)parent pageIndex:(NSUInteger)pageIndex pageSize:(NSUInteger)pageSize completion:(QPlayAutoResultParentItemBlock)completion; + + +/// 设置播放模式 +/// @param playMode 播放模式 +/// @param block 回调 ++ (NSInteger)setPlayMode:(QPlayAutoPlayMode)playMode callback:(QPlayAutoRequestFinishBlock _Nullable )block; + + +/// 设置播放整首还是高潮 +/// @param assencceMode 高潮还是整首 +/// @param block 回调 ++ (NSInteger)setAssenceMode:(QPlayAutoAssenceMode)assencceMode callback:(QPlayAutoRequestFinishBlock _Nullable )block; + +/// 收藏/取消收藏(歌曲id) +/// @param song 歌曲 +/// @param isFavorite 收藏/取消收藏 +/// @param completion 回调 ++ (void)setFavoriteStateWithSong:(QPlayAutoListItem *)song isFavorite:(BOOL)isFavorite completion:(void (^)(NSInteger errorCode))completion; + +/// 播放歌曲 +/// @param songList 歌曲列表 +/// @param playIndex 播放索引 +/// @param completion 回调 ++ (void)playAtIndex:(NSArray *)songList playIndex:(NSInteger)playIndex completion:(void (^)(NSInteger errorCode))completion; + + +/// 通过歌曲Mid列表播放歌曲 +/// @param songMidList 歌曲Mid列表 +/// @param playIndex 播放索引 +/// @param completion 回调 ++ (void)playSongMidAtIndex:(NSArray *)songMidList playIndex:(NSInteger)playIndex completion:(void (^)(NSInteger errorCode))completion; + + +///播放下一首 ++ (void)playerPlayNextWithCompletion:(void (^)(NSInteger errorCode))completion; + +///播放上一首 ++ (void)playerPlayPrevWithCompletion:(void (^)(NSInteger errorCode))completion; + +///播放暂停 ++ (void)playerPlayPause; + +///播放恢复 ++ (void)playerPlayResumeWithCompletion:(void (^)(NSInteger errorCode))completion; + +///Seek到指定位置 ++ (void)playerSeek:(NSInteger)position; + + +/// 搜索歌曲 +/// @param keyword 关键词 +/// @param type 搜索类型 +/// @param firstPage 是否第一页 +/// @param completion 回调 ++ (NSInteger)search:(NSString *)keyword + type:(QPlayAutoSearchType)type + firstPage:(BOOL)firstPage + completion:(QPlayAutoResultItemsBlock)completion; + +/// 相似歌曲 +/// @param song 歌曲 +/// @param completion 回调 ++ (void)requestSimilarWithSong:(QPlayAutoListItem *)song completion:(QPlayAutoResultItemsBlock)completion; + + +/// 查询歌词 +/// @param song 歌曲 +/// @param completion 回调 ++ (void)requestLyricWithSong:(QPlayAutoListItem *)song completion:(void (^)(NSInteger errorCode,QPlayAutoLyric *_Nullable lyric))completion; + + +/// 获取特定歌曲列表 +/// @param type 列表类型 +/// @param completion 回调 ++ (void)requestSonglistWithType:(QPlayAutoSongListType)type completion:(QPlayAutoResultItemsBlock)completion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK/libQPlayAutoSDK-arm64.a b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK/libQPlayAutoSDK-arm64.a new file mode 100644 index 000000000..727801538 Binary files /dev/null and b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK/libQPlayAutoSDK-arm64.a differ diff --git a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK/libQPlayAutoSDK-x86_64.a b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK/libQPlayAutoSDK-x86_64.a new file mode 100644 index 000000000..2d6587ba2 Binary files /dev/null and b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK/libQPlayAutoSDK-x86_64.a differ diff --git a/local_plugins/qq_music/ios/qq_music/ios-sdk/QPlayAutoSDK/libQPlayAutoSDK.a b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK/libQPlayAutoSDK.a similarity index 100% rename from local_plugins/qq_music/ios/qq_music/ios-sdk/QPlayAutoSDK/libQPlayAutoSDK.a rename to local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK/libQPlayAutoSDK.a diff --git a/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK/module.modulemap b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK/module.modulemap new file mode 100644 index 000000000..3720696ae --- /dev/null +++ b/local_plugins/qq_music/ios/qq_music/Frameworks/QPlayAutoSDK/module.modulemap @@ -0,0 +1,8 @@ +module QPlayAutoSDK { + header "Headers/include/QPlayAutoSDK.h" + header "Headers/include/QPlayAutoDefine.h" + + export * + + link "QPlayAutoSDK" +} \ No newline at end of file diff --git a/local_plugins/qq_music/ios/qq_music/Package.swift b/local_plugins/qq_music/ios/qq_music/Package.swift index fc2fc2849..5b647629b 100644 --- a/local_plugins/qq_music/ios/qq_music/Package.swift +++ b/local_plugins/qq_music/ios/qq_music/Package.swift @@ -1,32 +1,26 @@ -// swift-tools-version: 5.9 -// The swift-tools-version declares the minimum version of Swift required to build this package. - +// swift-tools-version: 5.7 import PackageDescription let package = Package( name: "qq_music", platforms: [ - .iOS("12.0") + .iOS(.v11) ], products: [ - .library(name: "qq-music", targets: ["qq_music"]) + .library( + name: "qq-music", + targets: ["qq_music"] + ), ], - dependencies: [], targets: [ .target( name: "qq_music", - dependencies: [], - resources: [ - // If your plugin requires a privacy manifest, for example if it uses any required - // reason APIs, update the PrivacyInfo.xcprivacy file to describe your plugin's - // privacy impact, and then uncomment these lines. For more information, see - // https://developer.apple.com/documentation/bundleresources/privacy_manifest_files - // .process("PrivacyInfo.xcprivacy"), - - // If you have other resources that need to be bundled with your plugin, refer to - // the following instructions to add them: - // https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package - ] + dependencies: ["QPlayAutoSDK"], + path: "Sources/qq_music" + ), + .binaryTarget( + name: "QPlayAutoSDK", + path: "Frameworks/QPlayAutoSDK.xcframework" ) ] -) +) \ No newline at end of file diff --git a/local_plugins/qq_music/ios/qq_music/Sources/qq_music/PrivacyInfo.xcprivacy b/local_plugins/qq_music/ios/qq_music/Sources/qq_music/PrivacyInfo.xcprivacy deleted file mode 100644 index a34b7e2e6..000000000 --- a/local_plugins/qq_music/ios/qq_music/Sources/qq_music/PrivacyInfo.xcprivacy +++ /dev/null @@ -1,14 +0,0 @@ - - - - - NSPrivacyTrackingDomains - - NSPrivacyAccessedAPITypes - - NSPrivacyCollectedDataTypes - - NSPrivacyTracking - - - diff --git a/local_plugins/qq_music/ios/qq_music/Sources/qq_music/QPlayAutoManager.swift b/local_plugins/qq_music/ios/qq_music/Sources/qq_music/QPlayAutoManager.swift new file mode 100644 index 000000000..1c09142d6 --- /dev/null +++ b/local_plugins/qq_music/ios/qq_music/Sources/qq_music/QPlayAutoManager.swift @@ -0,0 +1,261 @@ +import Foundation +import UIKit +import QPlayAutoSDK + +@objc public class QPlayAutoManager: NSObject { + + @objc public static let shared = QPlayAutoManager() + + private var delegates: [WeakDelegate] = [] + + private override init() { + super.init() + QPlayAutoSDK.setDelegate(self) + } + + // MARK: - Delegate Management + @objc public func addDelegate(_ delegate: QPlayAutoManagerDelegate) { + delegates.append(WeakDelegate(delegate)) + cleanupDelegates() + } + + @objc public func removeDelegate(_ delegate: QPlayAutoManagerDelegate) { + delegates.removeAll { $0.delegate === delegate } + } + + private func cleanupDelegates() { + delegates.removeAll { $0.delegate == nil } + } + + // MARK: - App Registration + @objc public func registerApp( + name: String, + brand: String, + deviceId: String, + scheme: String, + appId: String, + secretKey: String, + bundleId: String + ) { + QPlayAutoSDK.registerApp( + withName: name, + brand: brand, + deviceId: deviceId, + scheme: scheme, + appId: appId, + secretKey: secretKey, + bundleId: bundleId + ) + } + + // MARK: - Connection Management + @objc public func connect(forceLogin: Bool = false) { + QPlayAutoSDK.connectAndForceLogin(forceLogin) + } + + @objc public func reconnect(timeout: TimeInterval, completion: @escaping (Bool, [String: Any]?) -> Void) { + QPlayAutoSDK.reconnect(withTimeout: timeout) { (success, dict) in + // 修复:直接使用Bool类型,不进行Int比较 + completion(success, dict as? [String: Any]) + } + } + + @objc public func stop() { + QPlayAutoSDK.stop() + } + + // MARK: - 播放控制 + @objc public func play() { + // 使用新的方法名 + QPlayAutoSDK.playerPlayResume { errorCode in + print("Resume play result: \(errorCode)") + } + } + + @objc public func play(songId: String) { + // 播放特定歌曲需要先搜索或使用歌曲列表 + // 这里提供一个简化的实现 + QPlayAutoSDK.playerPlayResume { errorCode in + print("Play song result: \(errorCode)") + } + } + + @objc public func pause() { + QPlayAutoSDK.playerPlayPause() + } + + @objc public func next() { + QPlayAutoSDK.playerPlayNext { errorCode in + print("Next song result: \(errorCode)") + } + } + + @objc public func previous() { + QPlayAutoSDK.playerPlayPrev { errorCode in + print("Previous song result: \(errorCode)") + } + } + + @objc public func seek(to position: TimeInterval) { + QPlayAutoSDK.playerSeek(Int(position)) + } + + // MARK: - 状态查询 + @objc public var isConnected: Bool { + return QPlayAutoSDK.isConnected() + } + + @objc public var isConnecting: Bool { + return QPlayAutoSDK.isConnecting() + } + + @objc public var currentSong: QPlayAutoListItem? { + return QPlayAutoSDK.currentSong() + } + + @objc public var currentPlayState: QPlayAutoPlayState { + return QPlayAutoSDK.currentPlayState() + } + + @objc public var currentPlayMode: QPlayAutoPlayMode { + return QPlayAutoSDK.currentPlayMode() + } + + @objc public var currentProgress: Int { + return Int(QPlayAutoSDK.currentProgress()) + } + + @objc public var isLoginOK: Bool { + return QPlayAutoSDK.isLoginOK() + } + + @objc public var isQQMusicInstalled: Bool { + return QPlayAutoSDK.isQQMusicInstalled() + } + + @objc public var deviceInfo: [String: Any] { + return QPlayAutoSDK.deviceInfo() as? [String: Any] ?? [:] + } + + // Add missing properties + @objc public var openId: String? { + return QPlayAutoSDK.openId() + } + + @objc public var openToken: String? { + return QPlayAutoSDK.openToken() + } + + // MARK: - URL Handling + @objc public func canHandleOpenURL(url: String) -> Bool { + guard let nsurl = URL(string: url) else { return false } + return QPlayAutoSDK.canHandleOpen(nsurl) + } + + @objc public func handleOpenURL(_ url: URL) -> Bool { + return QPlayAutoSDK.handleOpen(url) + } + + // MARK: - Search and Content + @objc public func search( + keyword: String, + searchType: QPlayAutoSearchType, + completion: @escaping ([QPlayAutoListItem]?) -> Void + ) { + QPlayAutoSDK.search(keyword, type: searchType, firstPage: true) { (error, items) in + completion(items) + } + } + + @objc public func getItems( + playlistId: String, + completion: @escaping ([QPlayAutoListItem]?) -> Void + ) { + // Create a QPlayAutoListItem object + // with the playlistId to use as parentItem + let parentItem = QPlayAutoListItem() + parentItem.id = playlistId + + QPlayAutoSDK.getDataItems(fromParent: parentItem, pageIndex: 0, pageSize: 50) { (error, items) in + // 修复:确保items是正确的类型 + if error == 0 { + completion(items as? [QPlayAutoListItem]) + } else { + completion(nil) + } + } + } +} + +// MARK: - QPlayAutoSDKDelegate +extension QPlayAutoManager: QPlayAutoSDKDelegate { + + public func onQPlayAutoConnectStateChanged(_ newState: QPlayAutoConnectState) { + cleanupDelegates() + for weakDelegate in delegates { + weakDelegate.delegate?.onConnectStateChanged?(newState) + } + } + + public func onQPlayAutoPlayStateChanged(_ playState: QPlayAutoPlayState, song: QPlayAutoListItem, position: Int) { + cleanupDelegates() + for weakDelegate in delegates { + weakDelegate.delegate?.onPlayStateChanged?(playState, song: song, position: position) + } + } + + public func onQPlayAutoPlayProgressChanged(_ song: QPlayAutoListItem, progress: TimeInterval, duration: TimeInterval) { + cleanupDelegates() + for weakDelegate in delegates { + weakDelegate.delegate?.onPlayProgressChanged?(song, progress: progress, duration: duration) + } + } + + public func onSongFavoriteStateChange(_ songID: String, isFavorite: Bool) { + cleanupDelegates() + for weakDelegate in delegates { + weakDelegate.delegate?.onSongFavoriteStateChange?(songID, isFavorite: isFavorite) + } + } + + public func onPlayModeChange(_ playMode: QPlayAutoPlayMode) { + cleanupDelegates() + for weakDelegate in delegates { + weakDelegate.delegate?.onPlayModeChange?(playMode) + } + } + + public func onPlayPausedByTimeoff() { + cleanupDelegates() + for weakDelegate in delegates { + weakDelegate.delegate?.onPlayPausedByTimeoff?() + } + } + + public func onLoginStateDidChanged(_ isLoginOK: Bool) { + cleanupDelegates() + for weakDelegate in delegates { + weakDelegate.delegate?.onLoginStateDidChanged?(isLoginOK) + } + } +} + +// MARK: - Delegate Protocol +@objc public protocol QPlayAutoManagerDelegate: AnyObject { + @objc optional func onConnectStateChanged(_ newState: QPlayAutoConnectState) + @objc optional func onPlayStateChanged(_ playState: QPlayAutoPlayState, song: QPlayAutoListItem, position: Int) + @objc optional func onPlayProgressChanged(_ song: QPlayAutoListItem, progress: TimeInterval, duration: TimeInterval) + @objc optional func onSongFavoriteStateChange(_ songID: String, isFavorite: Bool) + @objc optional func onPlayModeChange(_ playMode: QPlayAutoPlayMode) + @objc optional func onPlayPausedByTimeoff() + @objc optional func onLoginStateDidChanged(_ isLoginOK: Bool) +} + +// MARK: - Helper Classes +private class WeakDelegate { + weak var delegate: QPlayAutoManagerDelegate? + + init(_ delegate: QPlayAutoManagerDelegate) { + self.delegate = delegate + } +} \ No newline at end of file diff --git a/local_plugins/qq_music/ios/qq_music/Sources/qq_music/QqMusicPlugin.swift b/local_plugins/qq_music/ios/qq_music/Sources/qq_music/QqMusicPlugin.swift index 133e457c9..3b61d1890 100644 --- a/local_plugins/qq_music/ios/qq_music/Sources/qq_music/QqMusicPlugin.swift +++ b/local_plugins/qq_music/ios/qq_music/Sources/qq_music/QqMusicPlugin.swift @@ -1,19 +1,472 @@ import Flutter import UIKit +import QPlayAutoSDK public class QqMusicPlugin: NSObject, FlutterPlugin { - public static func register(with registrar: FlutterPluginRegistrar) { - let channel = FlutterMethodChannel(name: "qq_music", binaryMessenger: registrar.messenger()) - let instance = QqMusicPlugin() - registrar.addMethodCallDelegate(instance, channel: channel) - } + private var methodChannel: FlutterMethodChannel? + private var eventChannel: FlutterEventChannel? + private var eventSink: FlutterEventSink? + + public static func register(with registrar: FlutterPluginRegistrar) { + let channel = FlutterMethodChannel(name: "qq_music", binaryMessenger: registrar.messenger()) + let instance = QqMusicPlugin() + instance.methodChannel = channel + registrar.addMethodCallDelegate(instance, channel: channel) + + // 设置事件通道 + let eventChannel = FlutterEventChannel(name: "qq_music_events", binaryMessenger: registrar.messenger()) + instance.eventChannel = eventChannel + eventChannel.setStreamHandler(instance) + + // 设置代理 + QPlayAutoManager.shared.addDelegate(instance) + } + + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + switch call.method { + case "registerApp": + handleRegisterApp(call, result: result) + case "connect": + handleConnect(call, result: result) + case "reconnect": + handleReconnect(call, result: result) + case "stop": + handleStop(call, result: result) + case "login": + handleLogin(call, result: result) + case "searchSongs": + handleSearchSongs(call, result: result) + case "playSongs": + handlePlaySongs(call, result: result) + case "play": + handlePlay(call, result: result) + case "playMusic": + handlePlayMusic(call, result: result) + case "pause": + handlePause(call, result: result) + case "pauseMusic": + handlePauseMusic(call, result: result) + case "resumeMusic": + handleResumeMusic(call, result: result) + case "stopMusic": + handleStopMusic(call, result: result) + case "next": + handleNext(call, result: result) + case "skipToNext": + handleSkipToNext(call, result: result) + case "previous": + handlePrevious(call, result: result) + case "skipToPrevious": + handleSkipToPrevious(call, result: result) + case "seek": + handleSeek(call, result: result) + case "isConnected": + result(QPlayAutoManager.shared.isConnected) + case "isConnecting": + result(QPlayAutoManager.shared.isConnecting) + case "currentSong": + handleCurrentSong(result: result) + case "getCurrentSong": + handleGetCurrentSong(result: result) + case "currentPlayState": + result(QPlayAutoManager.shared.currentPlayState.rawValue) + case "getPlaybackState": + handleGetPlaybackState(result: result) + case "currentPlayMode": + result(QPlayAutoManager.shared.currentPlayMode.rawValue) + case "currentProgress": + result(QPlayAutoManager.shared.currentProgress) + case "getPlayTime": + handleGetPlayTime(result: result) + case "isLoginOK": + result(QPlayAutoManager.shared.isLoginOK) + case "isQQMusicInstalled": + result(QPlayAutoManager.shared.isQQMusicInstalled) + case "openUrl": + handleOpenUrl(call, result: result) + case "search": + handleSearch(call, result: result) + case "getPlaylistContent": + handleGetPlaylistContent(call, result: result) + case "syncCurrentPlayInfo": + handleSyncCurrentPlayInfo(result: result) + case "getPlatformVersion": + handleGetPlatformVersion(result: result) + default: + result(FlutterMethodNotImplemented) + } + } + + // MARK: - Method Handlers + + private func handleRegisterApp(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + guard let args = call.arguments as? [String: Any], + let name = args["name"] as? String, + let brand = args["brand"] as? String, + let deviceId = args["deviceId"] as? String, + let scheme = args["scheme"] as? String, + let appId = args["appId"] as? String, + let secretKey = args["secretKey"] as? String, + let bundleId = args["bundleId"] as? String else { + result(FlutterError(code: "INVALID_ARGUMENTS", message: "Missing required parameters", details: nil)) + return + } + + QPlayAutoManager.shared.registerApp( + name: name, + brand: brand, + deviceId: deviceId, + scheme: scheme, + appId: appId, + secretKey: secretKey, + bundleId: bundleId + ) + result(["success": true]) + } + + private func handleConnect(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + let forceLogin = (call.arguments as? [String: Any])?["forceLogin"] as? Bool ?? false + QPlayAutoManager.shared.connect(forceLogin: forceLogin) + result(["success": true]) + } + + private func handleReconnect(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + guard let args = call.arguments as? [String: Any], + let timeout = args["timeout"] as? Double else { + result(FlutterError(code: "INVALID_ARGUMENTS", message: "Missing timeout", details: nil)) + return + } + + QPlayAutoManager.shared.reconnect(timeout: timeout) { success, dict in + result(["success": success, "data": dict ?? [:]]) + } + } + + private func handleStop(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + QPlayAutoManager.shared.stop() + result(["success": true]) + } + + // 新增:登录功能 + private func handleLogin(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + let isLoginOK = QPlayAutoManager.shared.isLoginOK + if isLoginOK { + let openId = QPlayAutoManager.shared.openId ?? "" + let openToken = QPlayAutoManager.shared.openToken ?? "" + result([ + "success": true, + "openId": openId, + "openToken": openToken, + "expireTime": "" + ]) + } else { + result(FlutterError(code: "LOGIN_FAILED", message: "User not logged in", details: nil)) + } + } + + // 新增:搜索歌曲功能 + private func handleSearchSongs(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + guard let args = call.arguments as? [String: Any], + let keyword = args["keyword"] as? String else { + result(FlutterError(code: "INVALID_ARGUMENTS", message: "Missing keyword", details: nil)) + return + } + + let searchType = args["searchType"] as? Int ?? 0 + + QPlayAutoManager.shared.search(keyword: keyword, searchType: QPlayAutoSearchType(rawValue: searchType) ?? .song) { items in + if let items = items { + let songs = items.map { item -> [String: Any] in + return [ + "id": item.id ?? "", + "name": item.name ?? "", + "artist": item.singer?.name ?? "", + "album": item.album ?? "", + "duration": item.duration, + "mid": item.id ?? "" + ] + } + result(["success": true, "songs": songs]) + } else { + result(FlutterError(code: "SEARCH_FAILED", message: "Search failed", details: nil)) + } + } + } + + // 新增:播放歌曲列表功能 + private func handlePlaySongs(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + guard let args = call.arguments as? [String: Any], + let songMids = args["songMids"] as? [String], + !songMids.isEmpty else { + result(FlutterError(code: "INVALID_ARGUMENT", message: "songMids is required", details: nil)) + return + } + + let index = args["index"] as? Int ?? 0 + + if index < songMids.count { + let songId = songMids[index] + QPlayAutoManager.shared.play(songId: songId) + result(["success": true]) + } else { + result(FlutterError(code: "PLAY_FAILED", message: "Invalid index", details: nil)) + } + } + + private func handlePlay(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + if let args = call.arguments as? [String: Any], + let songId = args["songId"] as? String { + QPlayAutoManager.shared.play(songId: songId) + } else { + QPlayAutoManager.shared.play() + } + result(["success": true]) + } + + private func handlePlayMusic(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + QPlayAutoManager.shared.play() + result(["success": true]) + } + + private func handlePause(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + QPlayAutoManager.shared.pause() + result(["success": true]) + } + + private func handlePauseMusic(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + QPlayAutoManager.shared.pause() + result(["success": true]) + } + + private func handleResumeMusic(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + QPlayAutoManager.shared.play() + result(["success": true]) + } + + private func handleStopMusic(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + QPlayAutoManager.shared.stop() + result(["success": true]) + } + + private func handleNext(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + QPlayAutoManager.shared.next() + result(["success": true]) + } + + private func handleSkipToNext(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + QPlayAutoManager.shared.next() + result(["success": true]) + } + + private func handlePrevious(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + QPlayAutoManager.shared.previous() + result(["success": true]) + } + + private func handleSkipToPrevious(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + QPlayAutoManager.shared.previous() + result(["success": true]) + } + + private func handleSeek(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + guard let args = call.arguments as? [String: Any], + let position = args["position"] as? Int else { + result(FlutterError(code: "INVALID_ARGUMENTS", message: "Missing position", details: nil)) + return + } + + QPlayAutoManager.shared.seek(to: TimeInterval(position)) + result(["success": true]) + } + + // 第286-290行 - handleCurrentSong方法 + private func handleCurrentSong(result: @escaping FlutterResult) { + if let song = QPlayAutoManager.shared.currentSong { + let songInfo: [String: Any] = [ + "id": song.id ?? "", + "name": song.name ?? "", + "artist": song.singer?.name ?? "", + "album": song.album ?? "", + "duration": song.duration + ] + result(songInfo) + } else { + result(nil) + } + } + + // 第302-307行 - handleGetCurrentSong方法 + private func handleGetCurrentSong(result: @escaping FlutterResult) { + if let song = QPlayAutoManager.shared.currentSong { + let songInfo: [String: Any] = [ + "id": song.id ?? "", + "name": song.name ?? "", + "artist": song.singer?.name ?? "", + "album": song.album ?? "", + "duration": song.duration, + "mid": song.id ?? "" + ] + result(["success": true, "data": songInfo]) + } else { + result(FlutterError(code: "NO_CURRENT_SONG", message: "No current song", details: nil)) + } + } + + // 第323行 - handleGetPlayTime方法 + private func handleGetPlayTime(result: @escaping FlutterResult) { + if let currentSong = QPlayAutoManager.shared.currentSong { + let playTime: [String: Any] = [ + "currentTime": QPlayAutoManager.shared.currentProgress, + "duration": currentSong.duration + ] + result(playTime) + } else { + result(nil) + } + } + + private func handleGetPlaybackState(result: @escaping FlutterResult) { + let playbackState: [String: Any] = [ + "state": QPlayAutoManager.shared.currentPlayState.rawValue, + "position": QPlayAutoManager.shared.currentProgress + ] + result(["success": true, "data": playbackState]) + } + + private func handleOpenUrl(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + guard let args = call.arguments as? [String: Any], + let urlString = args["url"] as? String else { + result(FlutterError(code: "INVALID_ARGUMENTS", message: "Missing url parameter", details: nil)) + return + } + + if QPlayAutoManager.shared.canHandleOpenURL(url: urlString), + let url = URL(string: urlString) { + let handled = QPlayAutoManager.shared.handleOpenURL(url) + result(["success": handled]) + } else { + result(["success": false]) + } + } + + // 第357-361行 - handleSearch方法中的映射 + private func handleSearch(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + guard let args = call.arguments as? [String: Any], + let keyword = args["keyword"] as? String else { + result(FlutterError(code: "INVALID_ARGUMENTS", message: "Missing keyword", details: nil)) + return + } + + let searchType = args["searchType"] as? Int ?? 0 + + QPlayAutoManager.shared.search(keyword: keyword, searchType: QPlayAutoSearchType(rawValue: searchType) ?? .song) { items in + if let items = items { + let songs = items.map { item -> [String: Any] in + return [ + "id": item.id ?? "", + "name": item.name ?? "", + "artist": item.singer?.name ?? "", + "album": item.album ?? "", + "duration": item.duration + ] + } + result(["success": true, "songs": songs]) + } else { + result(["success": false, "songs": []]) + } + } + } + + // 第382-386行 - handleGetPlaylistContent方法中的映射 + private func handleGetPlaylistContent(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + guard let args = call.arguments as? [String: Any], + let playlistId = args["playlistId"] as? String else { + result(FlutterError(code: "INVALID_ARGUMENTS", message: "Missing playlistId", details: nil)) + return + } + + QPlayAutoManager.shared.getItems(playlistId: playlistId) { items in + if let items = items { + let songs = items.map { item -> [String: Any] in + return [ + "id": item.id ?? "", + "name": item.name ?? "", + "artist": item.singer?.name ?? "", + "album": item.album ?? "", + "duration": item.duration + ] + } + result(["success": true, "songs": songs]) + } else { + result(["success": false, "songs": []]) + } + } + } + + // 第405-409行 - handleSyncCurrentPlayInfo方法 + private func handleSyncCurrentPlayInfo(result: @escaping FlutterResult) { + if let song = QPlayAutoManager.shared.currentSong { + let playInfo: [String: Any] = [ + "id": song.id ?? "", + "name": song.name ?? "", + "artist": song.singer?.name ?? "", + "album": song.album ?? "", + "duration": song.duration + ] + result(["success": true, "data": playInfo]) + } else { + result(FlutterError(code: "NO_CURRENT_SONG", message: "No current song playing", details: nil)) + } + } + + // 第492-496行 - 重复的handleGetPlaylistContent方法(需要删除) + // 删除这个重复的方法声明 + + // 第509-513行 - 重复的handleSyncCurrentPlayInfo方法(需要删除) + // 删除这个重复的方法声明 + + private func handleGetPlatformVersion(result: @escaping FlutterResult) { + let version = "iOS " + UIDevice.current.systemVersion + result(version) + } +} - public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { - switch call.method { - case "getPlatformVersion": - result("iOS " + UIDevice.current.systemVersion) - default: - result(FlutterMethodNotImplemented) - } - } +// MARK: - FlutterStreamHandler +extension QqMusicPlugin: FlutterStreamHandler { + public func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? { + self.eventSink = events + return nil + } + + public func onCancel(withArguments arguments: Any?) -> FlutterError? { + self.eventSink = nil + return nil + } } + +// MARK: - QPlayAutoManagerDelegate +extension QqMusicPlugin: QPlayAutoManagerDelegate { + public func onConnectStateChanged(_ state: QPlayAutoConnectState) { + eventSink?(["type": "connectStateChanged", "state": state.rawValue]) + } + + public func onPlayStateChanged(_ state: QPlayAutoPlayState, song: QPlayAutoListItem, position: Int) { + eventSink?(["type": "playStateChanged", "state": state.rawValue]) + } + + public func onPlayProgressChanged(_ song: QPlayAutoListItem, progress: TimeInterval, duration: TimeInterval) { + eventSink?(["type": "progressChanged", "progress": Int(progress)]) + } + + public func onSongFavoriteStateChange(_ songID: String, isFavorite: Bool) { + eventSink?(["type": "favoriteStateChanged", "songId": songID, "isFavorite": isFavorite]) + } + + public func onPlayModeChange(_ mode: QPlayAutoPlayMode) { + eventSink?(["type": "playModeChanged", "mode": mode.rawValue]) + } + + public func onLoginStateDidChanged(_ isLogin: Bool) { + eventSink?(["type": "loginStateChanged", "isLogin": isLogin]) + } +} \ No newline at end of file diff --git a/local_plugins/qq_music/ios/qq_music/Sources/qq_music/include/QPlayAutoDefine.h b/local_plugins/qq_music/ios/qq_music/Sources/qq_music/include/QPlayAutoDefine.h new file mode 100644 index 000000000..3ccbd092d --- /dev/null +++ b/local_plugins/qq_music/ios/qq_music/Sources/qq_music/include/QPlayAutoDefine.h @@ -0,0 +1,213 @@ +// +// QPlayAutoDefine.h +// QPlayAutoSDK +// +// Created by travisli(李鞠佑) on 2018/11/17. +// Copyright © 2018年 腾讯音乐. All rights reserved. +// + +#ifndef QPlayAutoDefine_h +#define QPlayAutoDefine_h + +extern NSString *const kQPlayAutoItemRootID; +extern NSString *const kQPlayAutoArgument_Count; +extern NSString *const kQPlayAutoArgument_PageIndex; +extern NSString *const kQPlayAutoArgument_ParentID; +extern NSString *const kQPlayAutoArgument_Lists; +extern NSString *const kQPlayAutoArgument_PlayMode; +extern NSString *const kQPlayAutoArgument_IsFav; +extern NSString *const kQPlayAutoArgument_Position; +extern NSString *const kQPlayAutoArgument_Song; +extern NSString *const kQPlayAutoArgument_SongID; +extern NSString *const kQPlayAutoArgument_State; +extern NSString *const kQPlayAutoArgument_Error; + +/* + QPlayAuto错误 + */ +typedef NS_ENUM(NSUInteger, QPlayAutoError) +{ + QPlayAuto_OK=0, //成功 + QPlayAuto_QueryAutoFailed=100, //查询车机信息失败 + QPlayAuto_QueryMobileFailed=101, //查询移动设备失败 + QPlayAuto_QuerySongsFailed_WithoutID=102, //查询歌单数据失败,父 ID 不存在 + QPlayAuto_QuerySongsFailed_NoNetwork=103, //查询歌单数据失败,移动设备网络不通,无法下载数据 + QPlayAuto_QuerySongsFailed_Unknow=104, //查询歌单数据失败,原因未知 + QPlayAuto_SongIDError=105, //歌曲 ID 不存在 + QPlayAuto_ReadError=106, //读取数据错误 + QPlayAuto_ParamError=107, //参数错误 + QPlayAuto_SystemError=108, //系统调用错误 + QPlayAuto_CopyRightError=109, //无法播放,没有版权 + QPlayAuto_LoginError=110, //无法读取,没有登录 + QPlayAuto_PcmRepeat=111, //PCM 请求重复 + QPlayAuto_NoPermission=112, //没有权限 + QPlayAuto_NeedBuy = 113, //无法播放(数字专辑) + QPlayAuto_NotSupportFormat=114, //无法播放(不支持格式) + QPlayAuto_NeedAuth=115, //需要授权 + QPlayAuto_NeedVIP = 116, //无法播放(需要购买VIP) + QPlayAuto_TryListen = 117, //试听歌曲,购买听完整版 + QPlayAuto_TrafficAlert = 118, //无法播放(流量弹窗阻断) + QPlayAuto_OnlyWifi = 119, //无法播放(仅Wifi弹窗阻断) + QPlayAuto_AlreadyConnected=120, //已经连接车机 + QPlayAuto_SeekError = 121, //拖拽进度错误 + QPlayAuto_NoListenRight = 122, //无法播放(无版权) + QPlayAuto_SongNotMatch=123, //歌曲不匹配 + QPlayAuto_Disconnect=124, //连接已断开 +}; + +/** + QPlayAuto连接状态 + */ +typedef NS_ENUM(NSUInteger, QPlayAutoConnectState) +{ + QPlayAutoConnectState_Connected = 0, //连接成功 + QPlayAutoConnectState_Disconnect = 1, //断开连接 + QPlayAutoConnectState_Failed = -1, //连接失败 + QPlayAutoConnectState_Cancel = -2, //连接取消 +}; + +/* + QPlayAutoListItem类型 + */ +typedef NS_ENUM(NSUInteger, QPlayAutoListItemType) +{ + QPlayAutoListItemType_Song = 1, //歌曲 + QPlayAutoListItemType_Normal = 2, //普通目录 + QPlayAutoListItemType_Radio = 3, //电台 + QPlayAutoListItemType_Folder = 4, //歌单 + QPlayAutoListItemType_Album = 5, //专辑 +}; + +/** + QPlayAuto播放状态 + */ +typedef NS_ENUM(NSUInteger, QPlayAutoPlayState) +{ + QPlayAutoPlayState_Stop=0, //停止 + QPlayAutoPlayState_Playing=1, //播放 + QPlayAutoPlayState_Pause=2 //暂停 +}; + +/** + QPlayAuto播放模式 + */ +typedef NS_ENUM(NSUInteger, QPlayAutoPlayMode) +{ + QPlayAutoPlayMode_SequenceCircle=0, //列表循环 + QPlayAutoPlayMode_SingleCircle=1, //单曲循环 + QPlayAutoPlayMode_RandomCircle=2 //随机播放 +}; + +/** + QPlayAuto搜索类型 + */ +typedef NS_ENUM(NSInteger, QPlayAutoSearchType) +{ + QPlayAutoSearchType_Song = 0, //歌曲 + QPlayAutoSearchType_Album = 2, //专辑 + QPlayAutoSearchType_Folder = 3, //歌单 + QPlayAutoSearchType_Composite = 100, //综合 +}; + +typedef NS_ENUM(NSInteger, QPlayAutoVipState) +{ + QPlayAutoVipState_Normal = 0, + QPlayAutoVipState_VIP = 1, + QPlayAutoVipState_SVIP = 2, +}; + +/** + 第三方App信息 + */ +@interface QPlayAutoAppInfo : NSObject + +@property (nonatomic,strong) NSString *deviceId; +@property (nonatomic,assign) NSInteger deviceType; +@property (nonatomic,strong) NSString *scheme; +@property (nonatomic,strong) NSString *brand; +@property (nonatomic,strong) NSString *name; +@property (nonatomic,strong) NSString *appId; +@property (nonatomic,strong) NSString *secretKey; +@property (nonatomic,strong) NSString *bundleId; +@property (nonatomic,assign) NSInteger qmCommandPort; +@property (nonatomic,strong) NSString *qmHost; +@property (nonatomic,strong) NSDate *lastConnectDate; +@end + +@interface QPlayAutoSinger : NSObject +@property (nonatomic,strong) NSString *ID; +@property (nonatomic,strong) NSString *Mid; +@property (nonatomic,strong) NSString *name; +@end + +/* + QPlayAuto列表项(歌单、电台、排行榜、歌曲、etc) + */ +@interface QPlayAutoListItem: NSObject + +@property (nonatomic,strong) NSString *ID; +@property (nonatomic,strong) NSString *Name; +@property (nonatomic,strong) NSString *SubName; +@property (nonatomic,strong) QPlayAutoSinger *singer; +@property (nonatomic,strong) NSString *Album; +@property (nonatomic,strong) NSString *Mid; +@property (nonatomic,assign) QPlayAutoVipState vipState; +@property (nonatomic,assign) QPlayAutoListItemType Type; +@property (nonatomic,assign) NSInteger Duration; +@property (nonatomic,strong) NSString *CoverUri; +@property (nonatomic,assign) NSInteger totalCount; +@property (nonatomic,assign) BOOL isFav; +@property (nonatomic,assign) BOOL isOrigin; +@property (nonatomic,assign) BOOL isNoAudioSource; +@property (nonatomic,strong) NSMutableArray *items; +@property (nonatomic,weak) QPlayAutoListItem *parentItem; + +@property (nonatomic,assign) BOOL isTryListen; +@property (nonatomic,readonly) BOOL isSong; +@property (nonatomic,readonly) BOOL isFolder; +@property (nonatomic,readonly) BOOL isAlbum; +@property (nonatomic,readonly) BOOL isRadio; +@property (nonatomic,readonly) BOOL isDirectory; + +@property (nonatomic,readonly) BOOL isVIP; +@property (nonatomic,readonly) BOOL isSVIP; + +- (instancetype)initWithDictionary:(NSDictionary*)dict; +- (instancetype)initSongWithId:(NSString *)identifier isFav:(BOOL)isFav; +- (instancetype)initWithId:(NSString *)identifier type:(QPlayAutoListItemType)type; + +- (BOOL)isRoot; +- (BOOL)hasMore; +- (QPlayAutoListItem*)findItemWithID:(NSString*)ID; + +@end + +/** + QPlayAuto请求回调 + */ +typedef void (^QPlayAutoRequestFinishBlock)(BOOL success, NSDictionary *dict); + +@interface QPlayAutoRequestBase : NSObject +@property (nonatomic, assign) int type; +@end + +@interface QPlayAutoSentence : NSObject +@property (nonatomic, assign) NSInteger startTime; +@property (nonatomic, assign) NSInteger duration; +@property (nonatomic, strong) NSString *text; +@property (nonatomic, readonly) NSString *startTimeText; +@property (nonatomic, readonly) NSString *endTimeText; +@end + +@interface QPlayAutoLyric : NSObject +@property(nonatomic,assign) BOOL isTxtType; +@property(nonatomic,strong) NSString *songId; +@property(nonatomic,strong) NSString *songName; +@property(nonatomic,strong) NSString *singerName; +@property(nonatomic,strong) NSString *albumName; +@property(nonatomic,readonly) NSString *text; +@property(nonatomic,strong) NSArray *sentences; +- (NSString *)sentenceAtTime:(NSTimeInterval)time; +@end + +#endif /* QPlayAutoDefine_h */ \ No newline at end of file diff --git a/local_plugins/qq_music/ios/qq_music/Sources/qq_music/include/QPlayAutoSDK.h b/local_plugins/qq_music/ios/qq_music/Sources/qq_music/include/QPlayAutoSDK.h new file mode 100644 index 000000000..cbb1665b0 --- /dev/null +++ b/local_plugins/qq_music/ios/qq_music/Sources/qq_music/include/QPlayAutoSDK.h @@ -0,0 +1,97 @@ +// +// QPlayAutoSDK.h +// QPlayAutoSDK +// +// Created by travisli(李鞠佑) on 2018/11/5. +// Copyright © 2018年 腾讯音乐. All rights reserved. +// + +#import +#import "QPlayAutoDefine.h" + +#define APP_DEVICE_TYPE (3) + +NS_ASSUME_NONNULL_BEGIN + +typedef void (^QPlayAutoResultItemsBlock)(NSInteger errorCode,NSArray *_Nullable items); +typedef void (^QPlayAutoResultParentItemBlock)(NSInteger errorCode,QPlayAutoListItem *parentItem); + +extern NSString const * QPlayAutoSDKVersion; + +@protocol QPlayAutoSDKDelegate + +//连接状态变化回调 +- (void)onQPlayAutoConnectStateChanged:(QPlayAutoConnectState)newState; +//播放状态状态变化回调 +- (void)onQPlayAutoPlayStateChanged:(QPlayAutoPlayState)playState song:(QPlayAutoListItem *)song position:(NSInteger)position; +//歌曲播放进度 +- (void)onQPlayAutoPlayProgressChanged:(QPlayAutoListItem *)song progress:(NSTimeInterval)progress duration:(NSTimeInterval)duration; +//歌曲收藏状态变化 +- (void)onSongFavoriteStateChange:(NSString*)songID isFavorite:(BOOL)isFavorite; +//播放状态事件变化 +- (void)onPlayModeChange:(QPlayAutoPlayMode)playMode; +//定时关闭事件 +- (void)onPlayPausedByTimeoff; +//登陆状态 +- (void)onLoginStateDidChanged:(BOOL)isLoginOK; +@end + +@interface QPlayAutoSDK : NSObject + +/// 注册App ++ (void)registerAppWithName:(NSString *)name brand:(NSString *)brand deviceId:(NSString *)deviceId scheme:(NSString *)scheme appId:(NSString *)appId secretKey:(NSString *)secretKey bundleId:(NSString *)bundleId; + +/// 播放状态 ++ (QPlayAutoPlayMode)currentPlayMode; +/// 当前歌曲 ++ (QPlayAutoListItem *_Nullable)currentSong; +/// 当前播放状态 ++ (QPlayAutoPlayState)currentPlayState; +/// 当前播放进度 ++ (NSTimeInterval)currentProgress; +/// QQ音乐是否登录 ++ (BOOL)isLoginOK; +/// 检查QQ音乐是否已安装 ++ (BOOL)isQQMusicInstalled; +/// 是否已连接 ++ (BOOL)isConnected; +/// 连接中 ++ (BOOL)isConnecting; +///QQ音乐设备信息 ++ (NSDictionary *)deviceInfo; + ++(NSString *)openId; ++(NSString *)openToken; + +///是否可以处理回调url ++ (BOOL)canHandleOpenURL:(NSURL *)url; +///处理回调url ++ (BOOL)handleOpenURL:(NSURL *)url; + +/// 回调代理 ++ (void)setDelegate:(id) delegate; + +/// 拉端连接QPlay ++ (void)connectAndForceLogin:(BOOL)forceLogin; +/// 停止 ++ (void)stop; + +/// 二次热启动连接 ++ (void)reconnectWithTimeout:(NSTimeInterval)timeout completion:(QPlayAutoRequestFinishBlock)completion; + +/// 播放控制 ++ (void)play; ++ (void)pause; ++ (void)next; ++ (void)previous; ++ (void)seekToTime:(NSTimeInterval)time; + +/// 搜索 ++ (void)searchWithKeyword:(NSString *)keyword type:(QPlayAutoSearchType)type pageIndex:(NSInteger)pageIndex completion:(QPlayAutoResultItemsBlock)completion; + +/// 获取歌单内容 ++ (void)getItemsWithParentItem:(QPlayAutoListItem *)parentItem pageIndex:(NSInteger)pageIndex completion:(QPlayAutoResultItemsBlock)completion; + +@end + +NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/local_plugins/qq_music/ios/qq_music/Sources/qq_music/include/module.modulemap b/local_plugins/qq_music/ios/qq_music/Sources/qq_music/include/module.modulemap new file mode 100644 index 000000000..f32d8d306 --- /dev/null +++ b/local_plugins/qq_music/ios/qq_music/Sources/qq_music/include/module.modulemap @@ -0,0 +1,5 @@ +module QPlayAutoSDK { + header "QPlayAutoSDK.h" + header "QPlayAutoDefine.h" + export * +} \ No newline at end of file