根据bilibili官方文档跑代码遇到的问题
1.build前安装的几个系统插件
# install homebrew, git, yasm
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
brew install git
brew install yasm
# add these lines to your ~/.bash_profile or ~/.profile
# export ANDROID_SDK=<your sdk path>
# export ANDROID_NDK=<your ndk path>
# on Cygwin (unmaintained)
# install git, make, yasm
复制代码
2.解决 clone IJKPlayer库 很慢甚至断线的问题。
大家都知道,gitHub国内访问很慢,所以此处需要设置终端代理来进行clone工程,切记此处需要自己电脑有代理才行。
export https_proxy=http://127.0.0.1:7890 http_proxy=http://127.0.0.1:7890 all_proxy=socks5://127.0.0.1:7890
复制代码
3.clone工程,并checkout最新版本
git clone https://github.com/Bilibili/ijkplayer.git ijkplayer-android
cd ijkplayer-android
git checkout -B latest k0.8.8
复制代码
4.执行预处理 (根据要编译的包的精简程度)
- 1.简单的
cd config
rm module.sh
ln -s module-lite.sh module.sh
cd android/contrib
# cd ios
sh compile-ffmpeg.sh clean
复制代码
- 2.简单带hevc
cd config
rm module.sh
ln -s module-lite-hevc.sh module.sh
cd android/contrib
# cd ios
sh compile-ffmpeg.sh clean
复制代码
- 3.复杂的支持多种格式的
cd config
rm module.sh
ln -s module-default.sh module.sh
cd android/contrib
# cd ios
sh compile-ffmpeg.sh clean
复制代码
5.执行./init-android.sh
此步骤会去github下载FFmpeg相关资源
./init-android.sh
复制代码
6. 编译ffmpeg
cd android/contrib
./compile-ffmpeg.sh clean
./compile-ffmpeg.sh all
复制代码
- (1)You need the NDKr10e or later 问题
既然它需要这个版本的NDK,那么我们就下载一个,然后设置到环境变量里就行了,下载地址见下面:
https://dl.google.com/android/repository/android-ndk-r10e-darwin-x86_64.zip?hl=zh_cn
复制代码
下载,解压,配置环境变量。一气呵成。接下来我们继续跑
- (2)fatal error: linux/perf_event.h: No such file or directory
看module.sh文件最后有没有这句话:
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-linux-perf"
没有的话就加上!
复制代码
编译ijk
cd ..
./compile-ijk.sh all
复制代码
OK,编译完成!
RUN IJKPlayerDemo
- 无法build问题 下面是我的配置。
1.修改buildscript和allprojects如下。
repositories {
//********国内配置 start ************//
maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'https://maven.aliyun.com/repository/jcenter' }
maven { url 'https://maven.aliyun.com/nexus/content/groups/public' }
//========国内配置 end =============//
}
复制代码
2.修改classpath
classpath 'com.android.tools.build:gradle:3.3.0'
复制代码
3.修改gradle wrapper
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-bin.zip
复制代码
4.flavors配置问题
//注释productFlavors
//注释all32Compile 相关
//把minSdkVersion改到21 我自己不需要21以下的^^!
复制代码
5.不能正确加载目录问题
把程序内默认的 "/" 改成 Environment.getExternalStorageDirectory().toString()
复制代码
另外程序原本代码有点问题,总是识别到“/”目录,此时我们把程序改成如下即可、
String path = Environment.getExternalStorageDirectory().toString();
doOpenDirectory(path, false);
复制代码
OK,完成!我们此时就编译好了ijkplayer播放器,并能正确运行此播放器demo了。
使用编译好的资源构建新播放器工程
-
- ijkplayer-armv7a/src/main/libs下的文件拷贝到新的工程的libs下。
-
- 然后把ijkplayer-java/build/outputs/aar/ijkplayer-java-release.aar复制到新工程的libs下
注意:高版本的androidStudio并不会在demo运行时主动生成aar,此时需要我们在工程根目录(MacOs下)执行./gradlew assembleRelease才能生成。
- 3.最后就是修改build.gradle,把so和aar文件依赖添加上去
//dependencies->增加
implementation fileTree(dir: 'libs', include: ['*.jar','*.aar'])
//android->defaultConfig->增加
ndk{ abiFilters "armeabi","armeabi-v7a","arm64-v8a","x86","x86_64" }
此处需要跟你你想要支持的cpu平台而定
//android->增加
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
//最外层->增加
repositories {
flatDir {
dir 'libs'
}
}
复制代码
此时aar和so库的配置就ok了
自制播放器简单Demo
- 播放器的自定义view
IjkVideoView.kt
package com.example.ijkplayerdemo
import android.content.Context
import android.text.TextUtils
import android.util.AttributeSet
import android.view.Gravity
import android.view.SurfaceHolder
import android.view.SurfaceView
import android.widget.FrameLayout
import androidx.annotation.Nullable
import tv.danmaku.ijk.media.player.IMediaPlayer
import tv.danmaku.ijk.media.player.IjkMediaPlayer
import java.io.IOException
class IjkVideoView : FrameLayout {
private var mContext: Context? = null
private var mMediaPlayer: IMediaPlayer? = null //视频控制类
private var mVideoPlayerListener : VideoPlayerListener? = null//自定义监听器
private var mSurfaceView : SurfaceView? = null//播放视图
private var mPath = "" //视频文件地址
constructor(context: Context) : super(context) {
initVideoView(context)
}
constructor(context: Context, @Nullable attrs: AttributeSet?) : super(context, attrs) {
initVideoView(context)
}
constructor(
context: Context,
@Nullable attrs: AttributeSet?,
defStyleAttr: Int
) : super(context, attrs, defStyleAttr) {
initVideoView(context)
}
constructor(
context: Context,
@Nullable attrs: AttributeSet?,
defStyleAttr: Int,
defStyleRes: Int
) : super(context, attrs, defStyleAttr, defStyleRes) {
}
abstract class VideoPlayerListener : IMediaPlayer.OnPreparedListener,
IMediaPlayer.OnCompletionListener, IMediaPlayer.OnErrorListener
private fun initVideoView(context: Context) {
mContext = context
isFocusable = true
}
fun setPath(path: String) {
if (TextUtils.equals("", mPath)) {
mPath = path
initSurfaceView()
} else {
mPath = path
loadVideo()
}
}
private fun initSurfaceView() {
mSurfaceView = SurfaceView(mContext)
mSurfaceView?.holder?.addCallback(LmnSurfaceCallback())
val layoutParams =LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, Gravity.CENTER)
mSurfaceView?.layoutParams = layoutParams
this.addView(mSurfaceView)
}
//surfaceView的监听器
private inner class LmnSurfaceCallback : SurfaceHolder.Callback {
override fun surfaceCreated(holder: SurfaceHolder) {}
override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {
loadVideo()
}
override fun surfaceDestroyed(holder: SurfaceHolder) {}
}
//加载视频
private fun loadVideo() {
if (mMediaPlayer != null) {
mMediaPlayer?.stop()
mMediaPlayer?.release()
}
val ijkMediaPlayer = IjkMediaPlayer()
mMediaPlayer = ijkMediaPlayer
if (mVideoPlayerListener != null) {
mMediaPlayer?.setOnPreparedListener(mVideoPlayerListener)
mMediaPlayer?.setOnErrorListener(mVideoPlayerListener)
}
try {
mMediaPlayer?.dataSource = mPath
} catch (e: IOException) {
e.printStackTrace()
}
mMediaPlayer?.setDisplay(mSurfaceView?.holder)
mMediaPlayer?.prepareAsync()
}
fun setListener(listener: VideoPlayerListener?) {
mVideoPlayerListener = listener
if (mMediaPlayer != null) {
mMediaPlayer?.setOnPreparedListener(listener)
}
}
val isPlaying: Boolean
get() = if (mMediaPlayer != null) {
mMediaPlayer?.isPlaying?:false
} else false
fun start() {
if (mMediaPlayer != null) {
mMediaPlayer?.start()
}
}
fun pause() {
if (mMediaPlayer != null) {
mMediaPlayer?.pause()
}
}
fun stop() {
if (mMediaPlayer != null) {
mMediaPlayer?.stop()
}
}
fun reset() {
if (mMediaPlayer != null) {
mMediaPlayer?.reset()
}
}
fun release() {
if (mMediaPlayer != null) {
mMediaPlayer?.reset()
mMediaPlayer?.release()
mMediaPlayer = null
}
}
}
复制代码
- Activity调用
MainActivity.kt
package com.example.ijkplayerdemo
import android.os.Bundle
import android.os.Environment
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import tv.danmaku.ijk.media.player.IMediaPlayer
import tv.danmaku.ijk.media.player.IjkMediaPlayer
import java.io.File
class MainActivity : AppCompatActivity() {
var ijkVideoView:IjkVideoView?=null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Environment.getStorageDirectory().absolutePath
// init player
IjkMediaPlayer.loadLibrariesOnce(null)
IjkMediaPlayer.native_profileBegin("libijkplayer.so")
ijkVideoView = findViewById(R.id.player)
ijkVideoView?.setListener(object: IjkVideoView.VideoPlayerListener() {
override fun onPrepared(p: IMediaPlayer?) {
//播放成功处理
p?.start()
}
override fun onCompletion(p0: IMediaPlayer?) {
Toast.makeText(this@MainActivity,"播放完成",Toast.LENGTH_LONG).show()
}
override fun onError(p0: IMediaPlayer?, p1: Int, p2: Int): Boolean {
Toast.makeText(this@MainActivity,"播放失败",Toast.LENGTH_LONG).show()
return false
}
})
//路径
ijkVideoView?.setPath("http://tanzi27niu.cdsb.mobi/wps/wp-content/uploads/2017/05/2017-05-17_17-33-30.mp4");
ijkVideoView?.start();
}
}
复制代码
- 布局文件
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.example.ijkplayerdemo.IjkVideoView
android:id="@+id/player"
android:layout_width="match_parent"
android:layout_height="250dp"/>
</RelativeLayout>
复制代码
- 添加网络和存储权限声明(不要忘记自己在程序中申请存储权限哦!)
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END