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路径下。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,635评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,628评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,971评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,986评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,006评论 6 394
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,784评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,475评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,364评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,860评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,008评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,152评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,829评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,490评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,035评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,156评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,428评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,127评论 2 356

推荐阅读更多精彩内容