Skip to content

Commit

Permalink
#1076 - Video playback support
Browse files Browse the repository at this point in the history
  • Loading branch information
moezbhatti committed Jun 6, 2018
1 parent d6fa04f commit b2b4e14
Show file tree
Hide file tree
Showing 12 changed files with 102 additions and 25 deletions.
2 changes: 2 additions & 0 deletions build.gradle
Expand Up @@ -4,6 +4,7 @@ buildscript {
ext.autodispose_version = '0.5.1'
ext.constraintlayout_version = '1.1.0-beta5'
ext.dagger_version = "2.16"
ext.exoplayer_version = "2.8.1"
ext.glide_version = "4.3.0"
ext.kotlin_version = '1.2.31'
ext.ktx_version = "0.2"
Expand Down Expand Up @@ -36,6 +37,7 @@ buildscript {

allprojects {
repositories {
google()
jcenter()
maven { url "https://jitpack.io" }
maven { url 'https://maven.google.com' }
Expand Down
4 changes: 4 additions & 0 deletions data/src/main/java/repository/MessageRepositoryImpl.kt
Expand Up @@ -222,7 +222,11 @@ class MessageRepositoryImpl @Inject constructor(
return Realm.getDefaultInstance()
.where(MmsPart::class.java)
.equalTo("messages.threadId", threadId)
.beginGroup()
.contains("type", "image/")
.or()
.contains("type", "video/")
.endGroup()
.sort("id", Sort.DESCENDING)
.findAllAsync()
}
Expand Down
4 changes: 4 additions & 0 deletions presentation/build.gradle
Expand Up @@ -92,6 +92,10 @@ dependencies {
implementation "com.github.bumptech.glide:glide:$glide_version"
kapt "com.github.bumptech.glide:compiler:$glide_version"

// exoplayer
implementation "com.google.android.exoplayer:exoplayer-core:$exoplayer_version"
implementation "com.google.android.exoplayer:exoplayer-ui:$exoplayer_version"

// rxbinding
implementation "com.jakewharton.rxbinding2:rxbinding-kotlin:$rxbinding_version"
implementation "com.jakewharton.rxbinding2:rxbinding-support-v4-kotlin:$rxbinding_version"
Expand Down
9 changes: 1 addition & 8 deletions presentation/src/main/java/common/Navigator.kt
Expand Up @@ -97,19 +97,12 @@ class Navigator @Inject constructor(private val context: Context, private val no
startActivity(intent)
}

fun showImage(partId: Long) {
fun showMedia(partId: Long) {
val intent = Intent(context, GalleryActivity::class.java)
intent.putExtra("partId", partId)
startActivity(intent)
}

fun showVideo(uri: Uri, type: String) {
val intent = Intent(Intent.ACTION_VIEW, uri)
.setDataAndType(uri, type)

startActivityExternal(intent)
}

/**
* Shows the attachment full-screen
* The transitionName for the view should be the id of the image being displayed
Expand Down
Expand Up @@ -272,10 +272,7 @@ class MessagesAdapter @Inject constructor(
mediaView.video.setVisible(part.isVideo())
mediaView.forwardTouches(view)
mediaView.clicks().subscribe {
when {
part.isImage() -> navigator.showImage(part.id)
part.isVideo() -> navigator.showVideo(part.getUri(), part.type)
}
if (part.isImage() || part.isVideo()) navigator.showMedia(part.id)
}

val canMediaGroupWithPrevious = canGroup(message, previous) || index > 0
Expand Down
Expand Up @@ -24,17 +24,22 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.moez.QKSMS.R
import common.Navigator
import common.base.QkRealmAdapter
import common.base.QkViewHolder
import common.util.GlideApp
import common.util.extensions.setVisible
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.subjects.PublishSubject
import kotlinx.android.synthetic.main.conversation_media_list_item.view.*
import model.MmsPart
import util.extensions.isImage
import util.extensions.isVideo
import javax.inject.Inject

class ConversationMediaAdapter @Inject constructor(
private val context: Context
private val context: Context,
private val navigator: Navigator
) : QkRealmAdapter<MmsPart>() {

val thumbnailClicks: PublishSubject<View> = PublishSubject.create()
Expand All @@ -55,8 +60,11 @@ class ConversationMediaAdapter @Inject constructor(
.fitCenter()
.into(view.thumbnail)

view.video.setVisible(part.isVideo())
view.thumbnail.transitionName = part.id.toString()
view.thumbnail.setOnClickListener { thumbnailClicks.onNext(it) }
view.thumbnail.setOnClickListener {
if (part.isImage()) thumbnailClicks.onNext(it) else navigator.showMedia(part.id)
}
}

override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
Expand Down
50 changes: 49 additions & 1 deletion presentation/src/main/java/feature/gallery/GalleryActivity.kt
Expand Up @@ -20,12 +20,21 @@ package feature.gallery

import android.arch.lifecycle.ViewModelProvider
import android.arch.lifecycle.ViewModelProviders
import android.net.Uri
import android.os.Bundle
import android.transition.ChangeBounds
import android.transition.ChangeImageTransform
import android.transition.TransitionSet
import android.view.Menu
import android.view.MenuItem
import com.google.android.exoplayer2.ExoPlayerFactory
import com.google.android.exoplayer2.SimpleExoPlayer
import com.google.android.exoplayer2.source.ExtractorMediaSource
import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory
import com.google.android.exoplayer2.util.Util
import com.google.android.mms.ContentType
import com.jakewharton.rxbinding2.view.clicks
import com.moez.QKSMS.R
import common.GlideCompletionListener
Expand All @@ -38,6 +47,7 @@ import io.reactivex.subjects.Subject
import kotlinx.android.synthetic.main.gallery_activity.*
import javax.inject.Inject


class GalleryActivity : QkActivity(), GalleryView {

@Inject lateinit var viewModelFactory: ViewModelProvider.Factory
Expand All @@ -47,6 +57,8 @@ class GalleryActivity : QkActivity(), GalleryView {

private val viewModel by lazy { ViewModelProviders.of(this, viewModelFactory)[GalleryViewModel::class.java] }

private var exoPlayer: SimpleExoPlayer? = null

override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
Expand Down Expand Up @@ -91,9 +103,19 @@ class GalleryActivity : QkActivity(), GalleryView {

title = state.title

when {
ContentType.isImageType(state.type) -> showImage(state.uri)
ContentType.isVideoType(state.type) -> showVideo(state.uri)
else -> hideMedia()
}
}

private fun showImage(uri: Uri?) {
image.setVisible(true)
video.setVisible(false)
if (image.drawable == null) {
GlideApp.with(this)
.load(state.imageUri)
.load(uri)
.dontAnimate()
.listener(GlideCompletionListener {
startPostponedEnterTransition()
Expand All @@ -102,6 +124,27 @@ class GalleryActivity : QkActivity(), GalleryView {
}
}

private fun showVideo(uri: Uri?) {
image.setVisible(false)
video.setVisible(true)

if (video.player == null) {
val videoTrackSelectionFactory = AdaptiveTrackSelection.Factory(null)
val trackSelector = DefaultTrackSelector(videoTrackSelectionFactory)
exoPlayer = ExoPlayerFactory.newSimpleInstance(this, trackSelector)
video.player = exoPlayer

val dataSourceFactory = DefaultDataSourceFactory(this, Util.getUserAgent(this, "QKSMS"))
val videoSource = ExtractorMediaSource.Factory(dataSourceFactory).createMediaSource(uri)
exoPlayer?.prepare(videoSource)
}
}

private fun hideMedia() {
image.setVisible(false)
video.setVisible(false)
}

override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.gallery, menu)
return super.onCreateOptionsMenu(menu)
Expand All @@ -115,4 +158,9 @@ class GalleryActivity : QkActivity(), GalleryView {
return true
}

override fun onDestroy() {
super.onDestroy()
exoPlayer?.release()
}

}
3 changes: 2 additions & 1 deletion presentation/src/main/java/feature/gallery/GalleryState.kt
Expand Up @@ -23,5 +23,6 @@ import android.net.Uri
data class GalleryState(
val navigationVisible: Boolean = true,
val title: String = "",
val imageUri: Uri? = null
val uri: Uri? = null,
val type: String = ""
)
Expand Up @@ -47,8 +47,7 @@ class GalleryViewModel @Inject constructor(
init {
disposables += partIdFlowable
.mapNotNull { partId -> messageRepo.getPart(partId) }
.mapNotNull { part -> part.getUri() }
.subscribe { uri -> newState { copy(imageUri = uri) } }
.subscribe { part -> newState { copy(uri = part.getUri(), type = part.type) } }

disposables += partIdFlowable
.mapNotNull { partId -> messageRepo.getMessageForPart(partId) }
Expand Down
26 changes: 21 additions & 5 deletions presentation/src/main/res/layout/conversation_media_list_item.xml
Expand Up @@ -17,11 +17,27 @@
~ You should have received a copy of the GNU General Public License
~ along with QKSMS. If not, see <http://www.gnu.org/licenses/>.
-->
<common.widget.SquareImageView android:id="@+id/thumbnail"
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/divider"
android:scaleType="centerCrop"
tools:src="@tools:sample/backgrounds/scenic" />
android:layout_height="wrap_content">

<common.widget.SquareImageView android:id="@+id/thumbnail"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/divider"
android:scaleType="centerCrop"
tools:src="@tools:sample/backgrounds/scenic" />

<ImageView
android:id="@+id/video"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="top|end"
android:layout_margin="16dp"
android:src="@drawable/ic_play_circle_filled_white_24dp" />

</FrameLayout>
5 changes: 5 additions & 0 deletions presentation/src/main/res/layout/gallery_activity.xml
Expand Up @@ -30,6 +30,11 @@
android:layout_width="match_parent"
android:layout_height="match_parent" />

<com.google.android.exoplayer2.ui.PlayerView
android:id="@+id/video"
android:layout_width="match_parent"
android:layout_height="match_parent" />

<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
Expand Down
4 changes: 2 additions & 2 deletions presentation/src/main/res/values/strings.xml
Expand Up @@ -34,7 +34,7 @@

<string name="menu_call">Call</string>
<string name="menu_info">Details</string>
<string name="menu_save">Save image</string>
<string name="menu_save">Save to gallery</string>

<string name="main_title_selected">%d selected</string>
<string name="main_menu_clear">Clear</string>
Expand Down Expand Up @@ -111,7 +111,7 @@
<string name="info_unblock">Unblock</string>
<string name="info_delete">Delete conversation</string>

<string name="gallery_toast_saved">Saved image</string>
<string name="gallery_toast_saved">Saved to gallery</string>

<string name="settings_category_appearance">Appearance</string>
<string name="settings_category_general">General</string>
Expand Down

0 comments on commit b2b4e14

Please sign in to comment.