基于騰訊云播放器封裝的Flutter Video Player插件
項目github地址:https://github.com/RandyWei/flt_video_player
Flutter版本現在已經更新到了v1.5.4-hotfix.2,在國內也越來越火。
在之前項目中有視頻播放功能,使用了flutter官方出的video_player庫完成實現。flutter官方所有插件,詳見https://github.com/flutter/plugins
官方的video_player,安卓是基于ExoPlayer,蘋果是基于原生的AVPlayer,目前項目使用中也沒什么毛病。
在閑暇之余,出于學習開發flutter plugin目的,基于騰訊云(https://cloud.tencent.com/document/product/881)播放器封裝了一個flutter視頻播放器。
目前項目在開發測試階段,還沒發布到pub平臺上,可通過git配置使用。
項目github地址:https://github.com/RandyWei/flt_video_player
播放器開放了部分騰訊云播放器的功能,如:倍速、靜音等。
參考資料:
https://github.com/An-uking/Flutter_IJKPlayer
https://github.com/CaiJingLong/flutter_ijkplayer
https://github.com/flutter/plugins/tree/master/packages/video_player
在項目開發過程中碰到了以下問題,作了一下總結:
1、出現label標簽沖突問題,如下錯誤
Attribute application@label value=(flutter_plugin_demo_example) from AndroidManifest.xml:13:9-52is also present at [LiteAVSDK_Player_6.3.7089.aar] AndroidManifest.xml:19:9-41 value=(@string/app_name).Suggestion: add 'tools:replace="android:label"' to <application> element at AndroidManifest.xml:11:5-35:19 to override.
這個錯誤是在安卓端出現的,因為使用了LiteAVSDK類似這種使用了各種第三方庫包含android:label的,所以沖突了
解決辦法:其實錯誤代碼提示也很是明確,或者直接上谷歌去百度一下就可以得到答案,在mainfest Application標簽中添加tools:relpace=”label”即可。
2、在使用EventChannel進行Flutter和Native通信過程中出現以下錯誤:
E/EventChannel#flutter_plugin_demo.event.status(15177): Failed to open event streamE/EventChannel#flutter_plugin_demo.event.status(15177): java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter oE/EventChannel#flutter_plugin_demo.event.status(15177): at com.chinahrt.flutter_plugin_demo2.FlutterPluginDemo2Plugin$onMethodCall$1.onListen(Unknown Source:2)E/EventChannel#flutter_plugin_demo.event.status(15177): at io.flutter.plugin.common.EventChannel$IncomingStreamRequestHandler.onListen(EventChannel.java:181)E/EventChannel#flutter_plugin_demo.event.status(15177): at io.flutter.plugin.common.EventChannel$IncomingStreamRequestHandler.onMessage(EventChannel.java:160)E/EventChannel#flutter_plugin_demo.event.status(15177): at io.flutter.view.FlutterNativeView$PlatformMessageHandlerImpl.handleMessageFromDart(FlutterNativeView.java:188)E/EventChannel#flutter_plugin_demo.event.status(15177): at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(FlutterJNI.java:202)E/EventChannel#flutter_plugin_demo.event.status(15177): at android.os.MessageQueue.nativePollOnce(Native Method)E/EventChannel#flutter_plugin_demo.event.status(15177): at android.os.MessageQueue.next(MessageQueue.java:326)E/EventChannel#flutter_plugin_demo.event.status(15177): at android.os.Looper.loop(Looper.java:160)E/EventChannel#flutter_plugin_demo.event.status(15177): at android.app.ActivityThread.main(ActivityThread.java:6718)E/EventChannel#flutter_plugin_demo.event.status(15177): at java.lang.reflect.Method.invoke(Native Method)E/EventChannel#flutter_plugin_demo.event.status(15177): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)E/EventChannel#flutter_plugin_demo.event.status(15177): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)I/flutter (15177): ══╡ EXCEPTION CAUGHT BY SERVICES LIBRARY ╞══════════════════════════════════════════════════════════I/flutter (15177): The following PlatformException was thrown while activating platform stream on channelI/flutter (15177): flutter_plugin_demo.event.status:I/flutter (15177): PlatformException(error, Parameter specified as non-null is null: methodI/flutter (15177): kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter o, null)I/flutter (15177):I/flutter (15177): When the exception was thrown, this was the stack:I/flutter (15177): #0 ?????StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:564:7)I/flutter (15177): #1 ?????MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:302:33)I/flutter (15177): <asynchronous suspension>I/flutter (15177): #2 ?????EventChannel.receiveBroadcastStream.<anonymous closure> (package:flutter/src/services/platform_channel.dart:490:29)I/flutter (15177): <asynchronous suspension>I/flutter (15177): #7 ?????VideoPlayerController.initialize (package:flutter_plugin_demo2/video_player.dart:33:10)I/flutter (15177): <asynchronous suspension>I/flutter (15177): #8 ?????_MyAppState.initState (package:flutter_plugin_demo2_example/main.dart:25:9)I/flutter (15177): #9 ?????StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3846:58)I/flutter (15177): #10 ????ComponentElement.mount (package:flutter/src/widgets/framework.dart:3711:5)I/flutter (15177): #11 ????Element.inflateWidget (package:flutter/src/widgets/framework.dart:2956:14)I/flutter (15177): #12 ????Element.updateChild (package:flutter/src/widgets/framework.dart:2759:12)I/flutter (15177): #13 ????RenderObjectToWidgetElement._rebuild (package:flutter/src/widgets/binding.dart:933:16)I/flutter (15177): #14 ????RenderObjectToWidgetElement.mount (package:flutter/src/widgets/binding.dart:904:5)I/flutter (15177): #15 ????RenderObjectToWidgetAdapter.attachToRenderTree.<anonymous closure> (package:flutter/src/widgets/binding.dart:850:17)I/flutter (15177): #16 ????BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2253:19)I/flutter (15177): #17 ????RenderObjectToWidgetAdapter.attachToRenderTree (package:flutter/src/widgets/binding.dart:849:13)I/flutter (15177): #18 ????_WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.attachRootWidget (package:flutter/src/widgets/binding.dart:736:7)I/flutter (15177): #19 ????runApp (package:flutter/src/widgets/binding.dart:780:7)I/flutter (15177): #20 ????main (package:flutter_plugin_demo2_example/main.dart:8:16)I/flutter (15177): #21 ????_runMainZoned.<anonymous closure>.<anonymous closure> (dart:ui/hooks.dart:189:25)I/flutter (15177): #26 ????_runMainZoned.<anonymous closure> (dart:ui/hooks.dart:180:5)I/flutter (15177): #27 ????_startIsolate.<anonymous closure> (dart:isolate/runtime/libisolate_patch.dart:300:19)I/flutter (15177): #28 ????_RawReceivePortImpl._handleMessage (dart:isolate/runtime/libisolate_patch.dart:171:12)I/flutter (15177): (elided 8 frames from package dart:async)I/flutter (15177): ════════════════════════════════════════════════════════════════════════════════════════════════════
這個問題還是出現在安卓平臺上,因為安卓項目使用了kotlin支持,在寫kotlin代碼實現EventChannel.StreamHandler時
override fun onListen(o: Any?, sink: EventChannel.EventSink?) {
}
override fun onCancel(o: Any?) {
}
參數應該可空,因誤寫成不可空,導致報錯。
所以解決辦法就是加?就可以
3、在iOS項目podspec上配置騰訊云播放器TXLiteAVSDK_Player支持時,出現以下問題
Undefined symbols for architecture x86_64:?????"vtable for __cxxabiv1::__si_class_type_info", referenced from:?????????typeinfo for bssl::(anonymous namespace)::ECKeyShare in TXLiteAVSDK_Player(ssl_key_share.o)?????????typeinfo for bssl::(anonymous namespace)::X25519KeyShare in TXLiteAVSDK_Player(ssl_key_share.o)?????NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.?????"_sqlite3_column_text", referenced from:?????????_qcloud_ijktsdb_meta_select in TXLiteAVSDK_Player(ijktsdb.o)?????"_sqlite3_bind_blob", referenced from:?????????_qcloud_ijktsdb_insert in TXLiteAVSDK_Player(ijktsdb.o)?????"_sqlite3_bind_text", referenced from:?????????_qcloud_ijktsdb_select in TXLiteAVSDK_Player(ijktsdb.o)?????????_ijktsdb_check in TXLiteAVSDK_Player(ijktsdb.o)?????????_qcloud_ijktsdb_insert in TXLiteAVSDK_Player(ijktsdb.o)?????????_qcloud_ijktsdb_meta_select in TXLiteAVSDK_Player(ijktsdb.o)?????????_qcloud_ijktsdb_meta_insert in TXLiteAVSDK_Player(ijktsdb.o)?????"_sqlite3_column_bytes", referenced from:?????????_qcloud_ijktsdb_select in TXLiteAVSDK_Player(ijktsdb.o)?????????_ijktsdb_check in TXLiteAVSDK_Player(ijktsdb.o)?????"_sqlite3_column_blob", referenced from:?????????_qcloud_ijktsdb_select in TXLiteAVSDK_Player(ijktsdb.o)?????"_sqlite3_errcode", referenced from:?????????_databaseError in TXLiteAVSDK_Player(ijktsdb.o)?????"_sqlite3_close", referenced from:?????????_qcloud_ijktsdb_open in TXLiteAVSDK_Player(ijktsdb.o)?????????_qcloud_ijktsdb_close in TXLiteAVSDK_Player(ijktsdb.o)
使用framwork配置無論怎樣都配置不成功,如果有大佬知道怎么配置的,可以教教我
最后還是使用了pod:s.dependency 'TXLiteAVSDK_Player' 配置成功了。
參考資料:
https://guides.cocoapods.org/syntax/podspec.html#dependency
4、在開發過程中出現以下錯誤:
Exception: ideviceinfo returned an error:ERROR: Could not connect to lockdownd, error code -8#0 ?????IMobileDevice.getInfoForDevice (package:flutter_tools/src/ios/mac.dart:141:9)<asynchronous suspension>#1 ?????IOSDevice.getAttachedDevices (package:flutter_tools/src/ios/devices.dart:156:55)<asynchronous suspension>#2 ?????IOSDevices.pollingGetDevices (package:flutter_tools/src/ios/devices.dart:110:57)#3 ?????PollingDeviceDiscovery.devices (package:flutter_tools/src/device.dart:186:52)<asynchronous suspension>#4 ?????DeviceManager.getAllConnectedDevices (package:flutter_tools/src/device.dart:114:46)<asynchronous suspension>#5 ?????DeviceValidator.validate (package:flutter_tools/src/doctor.dart:705:54)<asynchronous suspension>#6 ?????Doctor.startValidatorTasks (package:flutter_tools/src/doctor.dart:129:52)#7 ?????Doctor.diagnose (package:flutter_tools/src/doctor.dart:200:41)#8 ?????_AsyncAwaitCompleter.start (dart:async-patch/async_patch.dart:49:6)#9 ?????Doctor.diagnose (package:flutter_tools/src/doctor.dart:190:24)#10 ????DoctorCommand.runCommand (package:flutter_tools/src/commands/doctor.dart:48:39)#11 ????_AsyncAwaitCompleter.start (dart:async-patch/async_patch.dart:49:6)#12 ????DoctorCommand.runCommand (package:flutter_tools/src/commands/doctor.dart:34:42)#13 ????FlutterCommand.verifyThenRunCommand (package:flutter_tools/src/runner/flutter_command.dart:559:18)#14 ????_asyncThenWrapperHelper.<anonymous closure> (dart:async-patch/async_patch.dart:77:64)#15 ????_rootRunUnary (dart:async/zone.dart:1132:38)#16 ????_CustomZone.runUnary (dart:async/zone.dart:1029:19)#17 ????_FutureListener.handleValue (dart:async/future_impl.dart:126:18)#18 ????Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:639:45)#19 ????Future._propagateToListeners (dart:async/future_impl.dart:668:32)#20 ????Future._complete (dart:async/future_impl.dart:473:7)#21 ????_SyncCompleter.complete (dart:async/future_impl.dart:51:12)#22 ????_AsyncAwaitCompleter.complete.<anonymous closure> (dart:async-patch/async_patch.dart:33:20)#23 ????_rootRun (dart:async/zone.dart:1124:13)#24 ????_CustomZone.run (dart:async/zone.dart:1021:19)#25 ????_CustomZone.bindCallback.<anonymous closure> (dart:async/zone.dart:947:23)#26 ????_microtaskLoop (dart:async/schedule_microtask.dart:41:21)#27 ????_startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)#28 ????_runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:115:13)#29 ????_RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:172:5)
執行命令: ideviceinfo -d 出現如下錯誤
idevice.c:295 idevice_connect(): ERROR: Connecting to usbmuxd failed: -9 (Bad file descriptor)13:18:45 lockdown.c:663 lockdownd_client_new(): could not connect to lockdownd (device 1a95bb66796dad5ebf6a99d1c87101b5c2214963)13:18:45 lockdown.c:698 lockdownd_client_new_with_handshake(): failed to create lockdownd client.ERROR: Could not connect to lockdownd, error code -8
關于”Could not connect to lockdownd”這個錯誤,網上出現了很多解決辦法,但每個人碰到的error code -8,錯誤碼都不一樣。有部分解決辦法就是修改權限,對于錯誤碼為 -8 的,一直沒有搜到相關解決辦法。折騰了一天,其實原因是,開發過程中,我碰到了手機,導致手機數據線松了,然后我更換了一個USB接口,總之是因為手機和電腦沒有連接好。如果有碰到這個問題,換個接口,然后撤銷iphone手機和電腦的信任,直到連接電腦時彈出信任授權對話框,才算是正常連接成功。一旦出現這個錯誤,連安卓設備都運行不了。
5、運行時出現
Assertion failed: (AMDeviceIsPaired(device)), function handle_device, file /tmp/ios-deploy-20181117-87168-1goz8ak/ios-deploy-1.9.4/src/ios-deploy/ios-deploy.m, line 1598.Could not install build/ios/iphoneos/Runner.app on 1a95bb66796dad5ebf6a99d1c87101b5c2214963.Try launching Xcode and selecting "Product > Run" to fix the problem:?open ios/Runner.xcworkspaceError launching application on iPhone (5).
出現這個錯誤,直接按提示使用Xcode運行一下項目即可。
6、還有最后一個嚴重的內存泄漏的問題
錯誤日志:Signal 11 was raised.
在iOS實現將畫面數據傳送到Flutter,使用到了CVPixelBufferRef數據。對于這塊目前不是很清楚,大概是因為線程安全的問題,在騰訊云播放器回調的數據,隨時可能會被釋放,而在Flutter回調中使用了已被釋放的數據,出現了問題。最后參考了ijk代碼,使用了OSAtomicCompareAndSwapPtrBarrier對數據進行驗證比較得以解決,對于這個OSAtomicCompareAndSwapPtrBarrier方法也不是很理解,如果有大佬了解的,可以教教我。
如果有錯誤的地方,希望大佬不吝賜教。
同時希望star一下。項目github地址:https://github.com/RandyWei/flt_video_player