Android Studio引用ijkplayer

"本文转载自:[wangxiuwen12]的Android集成ijkplayer做自己的播放器"

1.简介

  继上一篇文档《Ubuntu20.04编译android平台ijkplayer源码》ijkplayer编译成功后,在android/ijkplayer路径下会生成一些重要的文件夹:

build.gradle       gradlew          ijkplayer-armv5    ijkplayer-exo   ijkplayer-x86_64  tools
gradle             gradlew.bat      ijkplayer-armv7a   ijkplayer-java  local.properties
gradle.properties  ijkplayer-arm64  ijkplayer-example  ijkplayer-x86   settings.gradl

  其中ijkplayer-arm*和ijkplayer-x86*对应不同ABI平台的工程,其中包含了编译出来的so库。在实际开发过程中,只需要根据自己的andorid设备的cpu架构选择其中一个就可以,不用将所有的都加入进去。
  ijkplayer-example和ijkplayer-exo是官方给的封装好的播放器;ijkplayer-java这个moudle,顾名思义这个就是对于so库的native接口,我们直接调用里面的 IjkMediaPlayer类就可以了,用法和MediaPlayer一样。

  所以AS项目中引用ijkplayer的基本思路是:

(1)导入对应平台的so库;
(2)导入ijkplayer-java;
(3)调用ijkplayer-java模块里面IjkMediaPlayer类播放。

2.导入so库

  通过下面的命令确定android设备cpu的架构:

adb shell getprop ro.product.cpu.abi

  结果:

armeabi-v7a

  根据android设备将整个armeabi-v7a文件夹(里面包含三个so库)拷贝到Android Studio项目中,对应路径:app/libs。

123.png

3.导入ijkplayer-java

  在Android Studio项目中选择File -> New -> Import Moudle,然后选择ijkplayer-java,就会导入。然后需要改的就是Moudle里面的build.gradle 设置里面的SDK version,要和你当前的工程SDK版本一样,可能之前在Ubuntu上面编译的SDK不一样。还有一处会报错,那就是:

apply from: new File(rootProject.projectDir, "tools/gradle-on-demand.gradle");

这个明显就是没有找到tools这个文件夹,所以我们把tools文件夹复制到工程里面,这样就不会报错了。

4.配置参数

  在项目的 build.gradle 文件中,添加 ijkplayer 的依赖库。具体代码如下:

(1)ijkplayer-java/build.gradle

  由于ijkplayer-java是在ubuntu中编译出来,所以它的SDK的版本和当前AS项目的SDK不一样,需要修改成AS项目一致。

  • 需要修改的参数:
compileSdkVersion 33
buildToolsVersion "31.0.0"
minSdkVersion 27
targetSdkVersion 33
implementation fileTree(dir: 'libs', include: ['*.jar'])
  • 修改后完整的文件
apply plugin: 'com.android.library'

android {
    // http://tools.android.com/tech-docs/new-build-system/tips
    //noinspection GroovyAssignabilityCheck
    compileSdkVersion 33
    //noinspection GroovyAssignabilityCheck
    buildToolsVersion "31.0.0"

    lintOptions {
        abortOnError false
    }
    defaultConfig {
        minSdkVersion 27
        targetSdkVersion 33
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {{
    implementation fileTree(dir: 'libs', include: ['*.jar'])
}

apply from: new File(rootProject.projectDir, "tools/gradle-on-demand.gradle");

(2)app/build.gradle

  • 需要修改的参数:
   sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }

  --------------
   implementation fileTree(dir: 'libs', include: ['*.jar'])
   implementation project(path: ':ijkplayer-java')
  • 修改后完整的文件
plugins {
    id 'com.android.application'
}

android {
    namespace 'com.example.myijkplayer'
    compileSdk 33

    defaultConfig {
        applicationId "com.example.myijkplayer"
        minSdk 27
        targetSdk 33
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }
}

dependencies {
    implementation 'androidx.appcompat:appcompat:1.4.1'
    implementation 'com.google.android.material:material:1.5.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'

    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation project(path: ':ijkplayer-java')
}

(3)setting.gradle

  如果使用Import Moudle时会自动添加,如果是复制进项目的需要手动添加。

include ':ijkplayer-java'

5.demo

(1)AndroidMenifest.xml

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

(2)activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <SurfaceView
        android:layout_width="720dp"
        android:layout_height="500dp"
        android:id="@+id/video_test"/>

    <Button
        android:layout_width="100dp"
        android:layout_height="80dp"
        android:text="开始"
        android:id="@+id/start_view"/>

    <Button
        android:layout_width="100dp"
        android:layout_height="80dp"
        android:text="停止"
        android:id="@+id/stop_view"/>

</LinearLayout>

(3)MainActivity.java

package com.example.myijkplayer;

import androidx.appcompat.app.AppCompatActivity;

import android.content.res.AssetFileDescriptor;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;

import java.io.File;
import java.io.IOException;
import tv.danmaku.ijk.media.player.IjkMediaPlayer;

public class MainActivity extends AppCompatActivity {

    private SurfaceView surfaceView;
    private Button start_bofang;
    private Button stop_bofang;
    private IjkMediaPlayer ijkMediaPlayer;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        start_bofang = (Button)findViewById(R.id.start_view);
        stop_bofang = (Button)findViewById(R.id.stop_view);
        surfaceView =(SurfaceView)findViewById(R.id.video_test);

        surfaceView.getHolder().addCallback(callback);

        new newInit().start();
        start_bofang.setOnClickListener(onClickListener);
        stop_bofang.setOnClickListener(onClickListener);

    }

    private  View.OnClickListener onClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            switch (view.getId()){
                case R.id.start_view:
                    new myThread().start();
                    break;
                case R.id.stop_view:
                    ijkMediaPlayer.stop();
                    break;
                default:
                    break;
            }
        }
    };

    private void InitIjk(){
        IjkMediaPlayer.loadLibrariesOnce(null);
        IjkMediaPlayer.native_profileBegin("libijkplayer.so");
        IjkMediaPlayer.native_profileBegin("libijkffmpeg.so");
        IjkMediaPlayer.native_profileBegin("libijksdl.so");

        ijkMediaPlayer = new IjkMediaPlayer();
    }

    private SurfaceHolder.Callback callback = new SurfaceHolder.Callback() {
        @Override
        public void surfaceCreated(SurfaceHolder surfaceHolder) {
            ijkMediaPlayer.setDisplay(surfaceHolder);
        }

        @Override
        public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {

        }

        @Override
        public void surfaceDestroyed(SurfaceHolder surfaceHolder) {

        }
    };

    private  class  newInit extends  Thread{
        @Override
        public void run() {
            InitIjk();
            super.run();
        }
    }

    private class myThread extends Thread{
        @Override
        public void run() {
            try {
                ijkMediaPlayer.setDataSource("/sdcard/h264.mp4");
            } catch (IOException e) {
                e.printStackTrace();
            }

            ijkMediaPlayer.prepareAsync();
            ijkMediaPlayer.setDisplay(surfaceView.getHolder());  //将视频画面输出到surface上
            ijkMediaPlayer.start();                                //开始播放
            super.run();
        }
    }
}

注:其中视频文件h264.mp4需要将其拷贝到android设备的/sdcard路径下。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容