Ijk.kt 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. package top.kikt.ijkplayer
  2. /// create 2019/3/7 by cai
  3. import android.util.Base64
  4. import io.flutter.plugin.common.MethodCall
  5. import io.flutter.plugin.common.MethodChannel
  6. import io.flutter.plugin.common.PluginRegistry
  7. import top.kikt.ijkplayer.entity.Info
  8. import tv.danmaku.ijk.media.player.IjkMediaPlayer
  9. import tv.danmaku.ijk.media.player.TextureMediaPlayer
  10. import java.io.File
  11. class Ijk(private val registry: PluginRegistry.Registrar) : MethodChannel.MethodCallHandler {
  12. private val textureEntry = registry.textures().createSurfaceTexture()
  13. val id: Long
  14. get() = textureEntry.id()
  15. val ijkPlayer: IjkMediaPlayer = IjkMediaPlayer()
  16. private val mediaPlayer: TextureMediaPlayer
  17. private val methodChannel: MethodChannel = MethodChannel(registry.messenger(), "top.kikt/ijkplayer/$id")
  18. private val notifyChannel: NotifyChannel = NotifyChannel(registry, id, this)
  19. init {
  20. mediaPlayer = TextureMediaPlayer(ijkPlayer)
  21. mediaPlayer.surfaceTexture = textureEntry.surfaceTexture()
  22. methodChannel.setMethodCallHandler(this)
  23. }
  24. override fun onMethodCall(call: MethodCall?, result: MethodChannel.Result?) {
  25. when (call?.method) {
  26. "setNetworkDataSource" -> {
  27. val uri = call.argument<String>("uri")
  28. if (uri == null) {
  29. handleSetUriResult(Exception("uri是必传参数"), result)
  30. return
  31. }
  32. setUri(uri) { throwable ->
  33. handleSetUriResult(throwable, result)
  34. }
  35. }
  36. "setAssetDataSource" -> {
  37. val name = call.argument<String>("name")
  38. val `package` = call.argument<String>("package")
  39. if (name != null) {
  40. setAssetUri(name, `package`) { throwable ->
  41. handleSetUriResult(throwable, result)
  42. }
  43. } else {
  44. handleSetUriResult(Exception("没有找到资源"), result)
  45. }
  46. }
  47. "setFileDataSource" -> {
  48. val path = call.argument<String>("path")
  49. if (path != null) {
  50. setUri("file://$path") { throwable ->
  51. handleSetUriResult(throwable, result)
  52. }
  53. }
  54. }
  55. "play" -> {
  56. play()
  57. result?.success(1)
  58. }
  59. "pause" -> {
  60. pause()
  61. }
  62. "stop" -> {
  63. stop()
  64. }
  65. "getInfo" -> {
  66. val info = getInfo()
  67. result?.success(info.toMap())
  68. }
  69. "seekTo" -> {
  70. val target = call.argument<Double>("target")
  71. if (target != null) {
  72. seekTo((target * 1000).toLong())
  73. }
  74. }
  75. else -> {
  76. result?.notImplemented()
  77. }
  78. }
  79. }
  80. fun getInfo(): Info {
  81. val duration = ijkPlayer.duration
  82. val currentPosition = ijkPlayer.currentPosition
  83. val width = ijkPlayer.videoWidth
  84. val height = ijkPlayer.videoHeight
  85. return Info(
  86. duration = duration.toDouble() / 1000,
  87. currentPosition = currentPosition.toDouble() / 1000,
  88. width = width,
  89. height = height,
  90. isPlaying = ijkPlayer.isPlaying
  91. )
  92. }
  93. private fun handleSetUriResult(throwable: Throwable?, result: MethodChannel.Result?) {
  94. if (throwable == null) {
  95. result?.success(null)
  96. } else {
  97. throwable.printStackTrace()
  98. result?.error("1", "设置资源失败", throwable)
  99. }
  100. }
  101. private fun setUri(uri: String, callback: (Throwable?) -> Unit) {
  102. try {
  103. ijkPlayer.setOnPreparedListener {
  104. callback(null)
  105. }
  106. ijkPlayer.dataSource = uri
  107. ijkPlayer.prepareAsync()
  108. } catch (e: Exception) {
  109. e.printStackTrace()
  110. callback(e)
  111. }
  112. }
  113. private fun setAssetUri(name: String, `package`: String?, callback: (Throwable?) -> Unit) {
  114. try {
  115. ijkPlayer.setOnPreparedListener {
  116. callback(null)
  117. }
  118. val asset =
  119. if (`package` == null) {
  120. registry.lookupKeyForAsset(name)
  121. } else {
  122. registry.lookupKeyForAsset(name, `package`)
  123. }
  124. val assetManager = registry.context().assets
  125. val fd = assetManager.openFd(asset)
  126. val cacheDir = registry.context().cacheDir.absoluteFile.path
  127. val fileName = Base64.encodeToString(asset.toByteArray(), Base64.DEFAULT)
  128. val file = File(cacheDir, fileName)
  129. fd.createInputStream().copyTo(file.outputStream())
  130. ijkPlayer.dataSource = file.path
  131. // ijkPlayer.setDataSource(fd.fileDescriptor) // can't use,
  132. ijkPlayer.prepareAsync()
  133. } catch (e: Exception) {
  134. e.printStackTrace()
  135. callback(e)
  136. }
  137. }
  138. fun dispose() {
  139. notifyChannel.dispose()
  140. methodChannel.setMethodCallHandler(null)
  141. mediaPlayer.stop()
  142. mediaPlayer.release()
  143. textureEntry.release()
  144. }
  145. private fun play() {
  146. try {
  147. ijkPlayer.start()
  148. } catch (e: Exception) {
  149. e.printStackTrace()
  150. }
  151. }
  152. private fun pause() {
  153. mediaPlayer.pause()
  154. }
  155. private fun stop() {
  156. mediaPlayer.stop()
  157. }
  158. fun seekTo(msec: Long) {
  159. mediaPlayer.seekTo(msec)
  160. }
  161. }