3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ExoPlayerで音声のみ簡単に再生させる方法

Last updated at Posted at 2020-07-08

概要

ExoPlayerは動画・音声再生を便利にするライブラリです
動画プレイヤーを使って再生というサンプルやコード例は多いですが、ボタンを押して音声だけ再生させたいというシンプルな構造をExoPlayerで行うにはどうするかを載せます よりよい方法や間違い・指摘があれば是非ご教授ください
(MediaPlayerでも十分ですが良いライブラリはどんどん使っていきたい)

導入

build.gradle
// android 部分
compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}

kotlinOptions {
    jvmTarget = "1.8"
}
build.gradle
// dependencies 部分
def exoplayer_version = "2.11.6"
implementation "com.google.android.exoplayer:exoplayer:$exoplayer_version"

実装

XML

ただボタンを配置するだけです
ExoPlayerのサンプルのようにPlayerViewなどは使いません

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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">

    <ImageView
        android:id="@+id/audio"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:contentDescription="null"
        app:srcCompat="@drawable/ic_sound_24"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

View

MainActivity.kt
package com.example.exoplayersoundonly

import android.net.Uri
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import com.google.android.exoplayer2.*
import com.google.android.exoplayer2.source.MediaSource
import com.google.android.exoplayer2.source.ProgressiveMediaSource
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory
import com.google.android.exoplayer2.util.Util
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    private var audioPlayer: SimpleExoPlayer? = null

    private val playerEventListener = object : Player.EventListener {
        override fun onIsPlayingChanged(isPlaying: Boolean) {
        }

        override fun onPlayerError(error: ExoPlaybackException) {
        }

        override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) {
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        initPlayer(buildMediaSource())

        audio.setOnClickListener {
            audioPlayer?.playWhenReady = true
        }
    }

    private fun initPlayer(mediaSource: MediaSource?) {
        mediaSource ?: return
        val trackSelector = DefaultTrackSelector(this)
        val loadControl = DefaultLoadControl()
        audioPlayer = SimpleExoPlayer.Builder(this).setTrackSelector(trackSelector).setLoadControl(loadControl).build()
        audioPlayer?.prepare(mediaSource)
        audioPlayer?.addListener(playerEventListener)
        audioPlayer?.playWhenReady = false
    }

    private fun buildMediaSource(): MediaSource? {
        return try {
            val uri = Uri.parse(SAMPLE_MP3)
            val factory = DefaultDataSourceFactory(this, Util.getUserAgent(this, getString(R.string.app_name)))
            ProgressiveMediaSource.Factory(factory).createMediaSource(uri)
        } catch (e: Exception) {
            null
        }
    }

    private fun releasePlayer() {
        audioPlayer?.let {
            it.stop()
            it.release()
            audioPlayer = null
        }
    }

    override fun onPause() {
        releasePlayer()
        super.onPause()
    }

    companion object {
        private const val SAMPLE_MP3 = "http://www.ne.jp/asahi/music/myuu/wave/menuettm.mp3"
    }
}

やっていることはとてもシンプルです

  1. 音声のもとになるMediaSourceを作る
  2. そのMediaSourceを使ってExoPlayerインスタンスを生成する
  3. ボタンを押した時に音声が再生されるようにする
  4. 使わないときはreleaseする

だけです

MediaSource作成

ここではMP3のURLからMediaSourceを生成しています ただUri.parseしたものを渡すだけなのでとても簡単です
対応する形式に伴いMediaSourceを指定します 今回はmp3のためProgressiveMediaSourceになります

snippet.kt
private fun buildMediaSource(): MediaSource? {
    return try {
        val uri = Uri.parse(SAMPLE_MP3)
        val factory = DefaultDataSourceFactory(this, Util.getUserAgent(this, getString(R.string.app_name)))
        ProgressiveMediaSource.Factory(factory).createMediaSource(uri)
    } catch (e: Exception) {
        null
    }
}

ExoPlayerインスタンスの生成と初期化

snippet.kt
private fun initPlayer(mediaSource: MediaSource?) {
    mediaSource ?: return
    val trackSelector = DefaultTrackSelector(this)
    val loadControl = DefaultLoadControl()
    audioPlayer = SimpleExoPlayer.Builder(this).setTrackSelector(trackSelector).setLoadControl(loadControl).build()
    audioPlayer?.prepare(mediaSource)
    audioPlayer?.addListener(playerEventListener)
    audioPlayer?.playWhenReady = false
}

Builderで生成します
その後、

  • #prepareで対応するMediaSourceをセット
  • #addListenerで状態を検知するListenerをセット(任意)
  • playWhenReadyで再生・停止の状態を設定 (ここでは初期化のみのためfalseを指定しています)

とします

再生

onClickされた際にplayWhenReadytrueにします

snippet.kt
audio.setOnClickListener {
    audioPlayer?.playWhenReady = true
}

リリース

snippet.kt
private fun releasePlayer() {
    audioPlayer?.let {
        it.stop()
        it.release()
        audioPlayer = null
    }
}

使わなくなったら停止・リリースしましょう
onPauseonDestroyでよく使われます

おわりに

これで音声のみ簡単に再生させることができます

参考になれば幸いです

こちらのレポジトリから簡単にお試しできます

他初心者向けの参考

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?