diff --git a/settings.gradle b/settings.gradle index a677f30b..e7b4def4 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,2 +1 @@ include ':app' -include ':tv' diff --git a/tv/.gitignore b/tv/.gitignore deleted file mode 100644 index 42afabfd..00000000 --- a/tv/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/tv/build.gradle b/tv/build.gradle deleted file mode 100644 index 7df71998..00000000 --- a/tv/build.gradle +++ /dev/null @@ -1,34 +0,0 @@ -plugins { - id 'com.android.application' - id 'kotlin-android' -} - -android { - compileSdk 32 - - defaultConfig { - applicationId "com.metabrainz.android" - minSdk 21 - targetSdk 32 - versionCode 1 - versionName "1.0" - } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - - lintOptions{ - abortOnError false - } -} - -dependencies { - implementation 'androidx.core:core-ktx:1.7.0' - implementation 'androidx.leanback:leanback:1.0.0' - implementation 'androidx.appcompat:appcompat:1.4.0' - implementation 'com.github.bumptech.glide:glide:4.12.0' -} \ No newline at end of file diff --git a/tv/proguard-rules.pro b/tv/proguard-rules.pro deleted file mode 100644 index 481bb434..00000000 --- a/tv/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/tv/src/main/AndroidManifest.xml b/tv/src/main/AndroidManifest.xml deleted file mode 100644 index ac8fc37e..00000000 --- a/tv/src/main/AndroidManifest.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tv/src/main/ic_launcher-playstore.png b/tv/src/main/ic_launcher-playstore.png deleted file mode 100644 index f9a6a9c0..00000000 Binary files a/tv/src/main/ic_launcher-playstore.png and /dev/null differ diff --git a/tv/src/main/java/com/metabrainz/android/BrowseErrorActivity.kt b/tv/src/main/java/com/metabrainz/android/BrowseErrorActivity.kt deleted file mode 100644 index d6caf868..00000000 --- a/tv/src/main/java/com/metabrainz/android/BrowseErrorActivity.kt +++ /dev/null @@ -1,76 +0,0 @@ -package com.metabrainz.android - -import android.os.Bundle -import android.os.Handler -import android.view.Gravity -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.FrameLayout -import android.widget.ProgressBar -import androidx.fragment.app.Fragment -import androidx.fragment.app.FragmentActivity - -/** - * BrowseErrorActivity shows how to use ErrorFragment. - */ -class BrowseErrorActivity : FragmentActivity() { - - private lateinit var mErrorFragment: ErrorFragment - private lateinit var mSpinnerFragment: SpinnerFragment - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.activity_main) - if (savedInstanceState == null) { - getSupportFragmentManager().beginTransaction() - .replace(R.id.main_browse_fragment, MainFragment()) - .commitNow() - } - testError() - } - - private fun testError() { - mErrorFragment = ErrorFragment() - supportFragmentManager - .beginTransaction() - .add(R.id.main_browse_fragment, mErrorFragment) - .commit() - - mSpinnerFragment = SpinnerFragment() - supportFragmentManager - .beginTransaction() - .add(R.id.main_browse_fragment, mSpinnerFragment) - .commit() - - val handler = Handler() - handler.postDelayed({ - supportFragmentManager - .beginTransaction() - .remove(mSpinnerFragment) - .commit() - mErrorFragment.setErrorContent() - }, TIMER_DELAY) - } - - class SpinnerFragment : Fragment() { - override fun onCreateView( - inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle?, - ): View? { - val progressBar = ProgressBar(container?.context) - if (container is FrameLayout) { - val layoutParams = - FrameLayout.LayoutParams(SPINNER_WIDTH, SPINNER_HEIGHT, Gravity.CENTER) - progressBar.layoutParams = layoutParams - } - return progressBar - } - } - - companion object { - private val TIMER_DELAY = 3000L - private val SPINNER_WIDTH = 100 - private val SPINNER_HEIGHT = 100 - } -} \ No newline at end of file diff --git a/tv/src/main/java/com/metabrainz/android/CardPresenter.kt b/tv/src/main/java/com/metabrainz/android/CardPresenter.kt deleted file mode 100644 index 212c4651..00000000 --- a/tv/src/main/java/com/metabrainz/android/CardPresenter.kt +++ /dev/null @@ -1,82 +0,0 @@ -package com.metabrainz.android - -import android.graphics.drawable.Drawable -import androidx.leanback.widget.ImageCardView -import androidx.leanback.widget.Presenter -import androidx.core.content.ContextCompat -import android.util.Log -import android.view.ViewGroup - -import com.bumptech.glide.Glide -import kotlin.properties.Delegates - -/** - * A CardPresenter is used to generate Views and bind Objects to them on demand. - * It contains an ImageCardView. - */ -class CardPresenter : Presenter() { - private var mDefaultCardImage: Drawable? = null - private var sSelectedBackgroundColor: Int by Delegates.notNull() - private var sDefaultBackgroundColor: Int by Delegates.notNull() - - override fun onCreateViewHolder(parent: ViewGroup): Presenter.ViewHolder { - Log.d(TAG, "onCreateViewHolder") - - sDefaultBackgroundColor = ContextCompat.getColor(parent.context, R.color.default_background) - sSelectedBackgroundColor = - ContextCompat.getColor(parent.context, R.color.selected_background) - mDefaultCardImage = ContextCompat.getDrawable(parent.context, R.drawable.movie) - - val cardView = object : ImageCardView(parent.context) { - override fun setSelected(selected: Boolean) { - updateCardBackgroundColor(this, selected) - super.setSelected(selected) - } - } - - cardView.isFocusable = true - cardView.isFocusableInTouchMode = true - updateCardBackgroundColor(cardView, false) - return Presenter.ViewHolder(cardView) - } - - override fun onBindViewHolder(viewHolder: Presenter.ViewHolder, item: Any) { - val movie = item as Movie - val cardView = viewHolder.view as ImageCardView - - Log.d(TAG, "onBindViewHolder") - if (movie.cardImageUrl != null) { - cardView.titleText = movie.title - cardView.contentText = movie.studio - cardView.setMainImageDimensions(CARD_WIDTH, CARD_HEIGHT) - Glide.with(viewHolder.view.context) - .load(movie.cardImageUrl) - .centerCrop() - .error(mDefaultCardImage) - .into(cardView.mainImageView) - } - } - - override fun onUnbindViewHolder(viewHolder: Presenter.ViewHolder) { - Log.d(TAG, "onUnbindViewHolder") - val cardView = viewHolder.view as ImageCardView - // Remove references to images so that the garbage collector can free up memory - cardView.badgeImage = null - cardView.mainImage = null - } - - private fun updateCardBackgroundColor(view: ImageCardView, selected: Boolean) { - val color = if (selected) sSelectedBackgroundColor else sDefaultBackgroundColor - // Both background colors should be set because the view"s background is temporarily visible - // during animations. - view.setBackgroundColor(color) - view.setInfoAreaBackgroundColor(color) - } - - companion object { - private val TAG = "CardPresenter" - - private val CARD_WIDTH = 313 - private val CARD_HEIGHT = 176 - } -} \ No newline at end of file diff --git a/tv/src/main/java/com/metabrainz/android/DetailsActivity.kt b/tv/src/main/java/com/metabrainz/android/DetailsActivity.kt deleted file mode 100644 index ea0e2b64..00000000 --- a/tv/src/main/java/com/metabrainz/android/DetailsActivity.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.metabrainz.android - -import android.os.Bundle -import androidx.fragment.app.FragmentActivity - -/** - * Details activity class that loads [VideoDetailsFragment] class. - */ -class DetailsActivity : FragmentActivity() { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.activity_details) - if (savedInstanceState == null) { - supportFragmentManager.beginTransaction() - .replace(R.id.details_fragment, VideoDetailsFragment()) - .commitNow() - } - } - - companion object { - const val SHARED_ELEMENT_NAME = "hero" - const val MOVIE = "Movie" - } -} \ No newline at end of file diff --git a/tv/src/main/java/com/metabrainz/android/DetailsDescriptionPresenter.kt b/tv/src/main/java/com/metabrainz/android/DetailsDescriptionPresenter.kt deleted file mode 100644 index 721a122b..00000000 --- a/tv/src/main/java/com/metabrainz/android/DetailsDescriptionPresenter.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.metabrainz.android - -import androidx.leanback.widget.AbstractDetailsDescriptionPresenter - -class DetailsDescriptionPresenter : AbstractDetailsDescriptionPresenter() { - - override fun onBindDescription( - viewHolder: AbstractDetailsDescriptionPresenter.ViewHolder, - item: Any, - ) { - val movie = item as Movie - - viewHolder.title.text = movie.title - viewHolder.subtitle.text = movie.studio - viewHolder.body.text = movie.description - } -} \ No newline at end of file diff --git a/tv/src/main/java/com/metabrainz/android/ErrorFragment.kt b/tv/src/main/java/com/metabrainz/android/ErrorFragment.kt deleted file mode 100644 index 0e3a478a..00000000 --- a/tv/src/main/java/com/metabrainz/android/ErrorFragment.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.metabrainz.android - -import android.os.Bundle -import android.view.View - -import androidx.core.content.ContextCompat -import androidx.leanback.app.ErrorSupportFragment - -/** - * This class demonstrates how to extend [ErrorSupportFragment]. - */ -class ErrorFragment : ErrorSupportFragment() { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - title = resources.getString(R.string.app_name) - } - - internal fun setErrorContent() { - imageDrawable = - ContextCompat.getDrawable(requireActivity(), androidx.leanback.R.drawable.lb_ic_sad_cloud) - message = resources.getString(R.string.error_fragment_message) - setDefaultBackground(TRANSLUCENT) - - buttonText = resources.getString(R.string.dismiss_error) - buttonClickListener = View.OnClickListener { - requireFragmentManager().beginTransaction().remove(this@ErrorFragment).commit() - } - } - - companion object { - private val TRANSLUCENT = true - } -} \ No newline at end of file diff --git a/tv/src/main/java/com/metabrainz/android/MainActivity.kt b/tv/src/main/java/com/metabrainz/android/MainActivity.kt deleted file mode 100644 index 6735ba6c..00000000 --- a/tv/src/main/java/com/metabrainz/android/MainActivity.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.metabrainz.android - -import android.os.Bundle -import androidx.fragment.app.FragmentActivity - -/** - * Loads [MainFragment]. - */ -class MainActivity : FragmentActivity() { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.activity_main) - if (savedInstanceState == null) { - supportFragmentManager.beginTransaction() - .replace(R.id.main_browse_fragment, MainFragment()) - .commitNow() - } - } -} \ No newline at end of file diff --git a/tv/src/main/java/com/metabrainz/android/MainFragment.kt b/tv/src/main/java/com/metabrainz/android/MainFragment.kt deleted file mode 100644 index f71cb92e..00000000 --- a/tv/src/main/java/com/metabrainz/android/MainFragment.kt +++ /dev/null @@ -1,231 +0,0 @@ -package com.metabrainz.android - -import java.util.Collections -import java.util.Timer -import java.util.TimerTask - -import android.content.Intent -import android.graphics.Color -import android.graphics.drawable.Drawable -import android.os.Bundle -import android.os.Handler -import androidx.leanback.app.BackgroundManager -import androidx.leanback.app.BrowseSupportFragment -import androidx.leanback.widget.ArrayObjectAdapter -import androidx.leanback.widget.HeaderItem -import androidx.leanback.widget.ImageCardView -import androidx.leanback.widget.ListRow -import androidx.leanback.widget.ListRowPresenter -import androidx.leanback.widget.OnItemViewClickedListener -import androidx.leanback.widget.OnItemViewSelectedListener -import androidx.leanback.widget.Presenter -import androidx.leanback.widget.Row -import androidx.leanback.widget.RowPresenter -import androidx.core.app.ActivityOptionsCompat -import androidx.core.content.ContextCompat -import android.util.DisplayMetrics -import android.util.Log -import android.view.Gravity -import android.view.ViewGroup -import android.widget.TextView -import android.widget.Toast - -import com.bumptech.glide.Glide -import com.bumptech.glide.request.target.SimpleTarget -import com.bumptech.glide.request.transition.Transition - -/** - * Loads a grid of cards with movies to browse. - */ -class MainFragment : BrowseSupportFragment() { - - private val mHandler = Handler() - private lateinit var mBackgroundManager: BackgroundManager - private var mDefaultBackground: Drawable? = null - private lateinit var mMetrics: DisplayMetrics - private var mBackgroundTimer: Timer? = null - private var mBackgroundUri: String? = null - - override fun onActivityCreated(savedInstanceState: Bundle?) { - Log.i(TAG, "onCreate") - super.onActivityCreated(savedInstanceState) - - prepareBackgroundManager() - - setupUIElements() - - loadRows() - - setupEventListeners() - } - - override fun onDestroy() { - super.onDestroy() - Log.d(TAG, "onDestroy: " + mBackgroundTimer?.toString()) - mBackgroundTimer?.cancel() - } - - private fun prepareBackgroundManager() { - - mBackgroundManager = BackgroundManager.getInstance(activity) - mBackgroundManager.attach(requireActivity().window) - mDefaultBackground = ContextCompat.getDrawable(requireActivity(), R.drawable.default_background) - mMetrics = DisplayMetrics() - requireActivity().windowManager.defaultDisplay.getMetrics(mMetrics) - } - - private fun setupUIElements() { - title = getString(R.string.browse_title) - // over title - headersState = BrowseSupportFragment.HEADERS_ENABLED - isHeadersTransitionOnBackEnabled = true - - // set fastLane (or headers) background color - brandColor = ContextCompat.getColor(requireActivity(), R.color.fastlane_background) - // set search icon color - searchAffordanceColor = ContextCompat.getColor(requireActivity(), R.color.search_opaque) - } - - private fun loadRows() { - val list = MovieList.list - - val rowsAdapter = ArrayObjectAdapter(ListRowPresenter()) - val cardPresenter = CardPresenter() - - for (i in 0 until NUM_ROWS) { - if (i != 0) { - Collections.shuffle(list) - } - val listRowAdapter = ArrayObjectAdapter(cardPresenter) - for (j in 0 until NUM_COLS) { - listRowAdapter.add(list[j % 5]) - } - val header = HeaderItem(i.toLong(), MovieList.MOVIE_CATEGORY[i]) - rowsAdapter.add(ListRow(header, listRowAdapter)) - } - - val gridHeader = HeaderItem(NUM_ROWS.toLong(), "PREFERENCES") - - val mGridPresenter = GridItemPresenter() - val gridRowAdapter = ArrayObjectAdapter(mGridPresenter) - gridRowAdapter.add(resources.getString(R.string.grid_view)) - gridRowAdapter.add(getString(R.string.error_fragment)) - gridRowAdapter.add(resources.getString(R.string.personal_settings)) - rowsAdapter.add(ListRow(gridHeader, gridRowAdapter)) - - adapter = rowsAdapter - } - - private fun setupEventListeners() { - setOnSearchClickedListener { - Toast.makeText(requireActivity(), "Implement your own in-app search", Toast.LENGTH_LONG) - .show() - } - - onItemViewClickedListener = ItemViewClickedListener() - onItemViewSelectedListener = ItemViewSelectedListener() - } - - private inner class ItemViewClickedListener : OnItemViewClickedListener { - override fun onItemClicked( - itemViewHolder: Presenter.ViewHolder, - item: Any, - rowViewHolder: RowPresenter.ViewHolder, - row: Row, - ) { - - if (item is Movie) { - Log.d(TAG, "Item: " + item.toString()) - val intent = Intent(requireActivity(), DetailsActivity::class.java) - intent.putExtra(DetailsActivity.MOVIE, item) - - val bundle = ActivityOptionsCompat.makeSceneTransitionAnimation( - requireActivity(), - (itemViewHolder.view as ImageCardView).mainImageView, - DetailsActivity.SHARED_ELEMENT_NAME) - .toBundle() - startActivity(intent, bundle) - } else if (item is String) { - if (item.contains(getString(R.string.error_fragment))) { - val intent = Intent(requireActivity(), BrowseErrorActivity::class.java) - startActivity(intent) - } else { - Toast.makeText(requireActivity(), item, Toast.LENGTH_SHORT).show() - } - } - } - } - - private inner class ItemViewSelectedListener : OnItemViewSelectedListener { - override fun onItemSelected( - itemViewHolder: Presenter.ViewHolder?, item: Any?, - rowViewHolder: RowPresenter.ViewHolder, row: Row, - ) { - if (item is Movie) { - mBackgroundUri = item.backgroundImageUrl - startBackgroundTimer() - } - } - } - - private fun updateBackground(uri: String?) { - val width = mMetrics.widthPixels - val height = mMetrics.heightPixels - Glide.with(requireActivity()) - .load(uri) - .centerCrop() - .error(mDefaultBackground) - .into>( - object : SimpleTarget(width, height) { - override fun onResourceReady( - drawable: Drawable, - transition: Transition?, - ) { - mBackgroundManager.drawable = drawable - } - }) - mBackgroundTimer?.cancel() - } - - private fun startBackgroundTimer() { - mBackgroundTimer?.cancel() - mBackgroundTimer = Timer() - mBackgroundTimer?.schedule(UpdateBackgroundTask(), BACKGROUND_UPDATE_DELAY.toLong()) - } - - private inner class UpdateBackgroundTask : TimerTask() { - - override fun run() { - mHandler.post { updateBackground(mBackgroundUri) } - } - } - - private inner class GridItemPresenter : Presenter() { - override fun onCreateViewHolder(parent: ViewGroup): ViewHolder { - val view = TextView(parent.context) - view.layoutParams = ViewGroup.LayoutParams(GRID_ITEM_WIDTH, GRID_ITEM_HEIGHT) - view.isFocusable = true - view.isFocusableInTouchMode = true - view.setBackgroundColor(ContextCompat.getColor(requireActivity(), R.color.default_background)) - view.setTextColor(Color.WHITE) - view.gravity = Gravity.CENTER - return ViewHolder(view) - } - - override fun onBindViewHolder(viewHolder: ViewHolder, item: Any) { - (viewHolder.view as TextView).text = item as String - } - - override fun onUnbindViewHolder(viewHolder: ViewHolder) {} - } - - companion object { - private val TAG = "MainFragment" - - private val BACKGROUND_UPDATE_DELAY = 300 - private val GRID_ITEM_WIDTH = 200 - private val GRID_ITEM_HEIGHT = 200 - private val NUM_ROWS = 6 - private val NUM_COLS = 15 - } -} \ No newline at end of file diff --git a/tv/src/main/java/com/metabrainz/android/Movie.kt b/tv/src/main/java/com/metabrainz/android/Movie.kt deleted file mode 100644 index b1490e06..00000000 --- a/tv/src/main/java/com/metabrainz/android/Movie.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.metabrainz.android - -import java.io.Serializable - -/** - * Movie class represents video entity with title, description, image thumbs and video url. - */ -data class Movie( - var id: Long = 0, - var title: String? = null, - var description: String? = null, - var backgroundImageUrl: String? = null, - var cardImageUrl: String? = null, - var videoUrl: String? = null, - var studio: String? = null, -) : Serializable { - - override fun toString(): String { - return "Movie{" + - "id=" + id + - ", title='" + title + '\'' + - ", videoUrl='" + videoUrl + '\'' + - ", backgroundImageUrl='" + backgroundImageUrl + '\'' + - ", cardImageUrl='" + cardImageUrl + '\'' + - '}' - } - - companion object { - internal const val serialVersionUID = 727566175075960653L - } -} \ No newline at end of file diff --git a/tv/src/main/java/com/metabrainz/android/MovieList.kt b/tv/src/main/java/com/metabrainz/android/MovieList.kt deleted file mode 100644 index 8c2fdf40..00000000 --- a/tv/src/main/java/com/metabrainz/android/MovieList.kt +++ /dev/null @@ -1,87 +0,0 @@ -package com.metabrainz.android - -object MovieList { - val MOVIE_CATEGORY = arrayOf( - "Category Zero", - "Category One", - "Category Two", - "Category Three", - "Category Four", - "Category Five") - - val list: List by lazy { - setupMovies() - } - private var count: Long = 0 - - private fun setupMovies(): List { - val title = arrayOf( - "Zeitgeist 2010_ Year in Review", - "Google Demo Slam_ 20ft Search", - "Introducing Gmail Blue", - "Introducing Google Fiber to the Pole", - "Introducing Google Nose") - - val description = "Fusce id nisi turpis. Praesent viverra bibendum semper. " + - "Donec tristique, orci sed semper lacinia, quam erat rhoncus massa, non congue tellus est " + - "quis tellus. Sed mollis orci venenatis quam scelerisque accumsan. Curabitur a massa sit " + - "amet mi accumsan mollis sed et magna. Vivamus sed aliquam risus. Nulla eget dolor in elit " + - "facilisis mattis. Ut aliquet luctus lacus. Phasellus nec commodo erat. Praesent tempus id " + - "lectus ac scelerisque. Maecenas pretium cursus lectus id volutpat." - val studio = arrayOf( - "Studio Zero", - "Studio One", - "Studio Two", - "Studio Three", - "Studio Four") - val videoUrl = arrayOf( - "https://commondatastorage.googleapis.com/android-tv/Sample%20videos/Zeitgeist/Zeitgeist%202010_%20Year%20in%20Review.mp4", - "https://commondatastorage.googleapis.com/android-tv/Sample%20videos/Demo%20Slam/Google%20Demo%20Slam_%2020ft%20Search.mp4", - "https://commondatastorage.googleapis.com/android-tv/Sample%20videos/April%20Fool's%202013/Introducing%20Gmail%20Blue.mp4", - "https://commondatastorage.googleapis.com/android-tv/Sample%20videos/April%20Fool's%202013/Introducing%20Google%20Fiber%20to%20the%20Pole.mp4", - "https://commondatastorage.googleapis.com/android-tv/Sample%20videos/April%20Fool's%202013/Introducing%20Google%20Nose.mp4") - val bgImageUrl = arrayOf( - "https://commondatastorage.googleapis.com/android-tv/Sample%20videos/Zeitgeist/Zeitgeist%202010_%20Year%20in%20Review/bg.jpg", - "https://commondatastorage.googleapis.com/android-tv/Sample%20videos/Demo%20Slam/Google%20Demo%20Slam_%2020ft%20Search/bg.jpg", - "https://commondatastorage.googleapis.com/android-tv/Sample%20videos/April%20Fool's%202013/Introducing%20Gmail%20Blue/bg.jpg", - "https://commondatastorage.googleapis.com/android-tv/Sample%20videos/April%20Fool's%202013/Introducing%20Google%20Fiber%20to%20the%20Pole/bg.jpg", - "https://commondatastorage.googleapis.com/android-tv/Sample%20videos/April%20Fool's%202013/Introducing%20Google%20Nose/bg.jpg") - val cardImageUrl = arrayOf( - "https://commondatastorage.googleapis.com/android-tv/Sample%20videos/Zeitgeist/Zeitgeist%202010_%20Year%20in%20Review/card.jpg", - "https://commondatastorage.googleapis.com/android-tv/Sample%20videos/Demo%20Slam/Google%20Demo%20Slam_%2020ft%20Search/card.jpg", - "https://commondatastorage.googleapis.com/android-tv/Sample%20videos/April%20Fool's%202013/Introducing%20Gmail%20Blue/card.jpg", - "https://commondatastorage.googleapis.com/android-tv/Sample%20videos/April%20Fool's%202013/Introducing%20Google%20Fiber%20to%20the%20Pole/card.jpg", - "https://commondatastorage.googleapis.com/android-tv/Sample%20videos/April%20Fool's%202013/Introducing%20Google%20Nose/card.jpg") - - val list = title.indices.map { - buildMovieInfo( - title[it], - description, - studio[it], - videoUrl[it], - cardImageUrl[it], - bgImageUrl[it]) - } - - return list - } - - private fun buildMovieInfo( - title: String, - description: String, - studio: String, - videoUrl: String, - cardImageUrl: String, - backgroundImageUrl: String, - ): Movie { - val movie = Movie() - movie.id = count++ - movie.title = title - movie.description = description - movie.studio = studio - movie.cardImageUrl = cardImageUrl - movie.backgroundImageUrl = backgroundImageUrl - movie.videoUrl = videoUrl - return movie - } -} \ No newline at end of file diff --git a/tv/src/main/java/com/metabrainz/android/PlaybackActivity.kt b/tv/src/main/java/com/metabrainz/android/PlaybackActivity.kt deleted file mode 100644 index 1f61dd98..00000000 --- a/tv/src/main/java/com/metabrainz/android/PlaybackActivity.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.metabrainz.android - -import android.os.Bundle -import androidx.fragment.app.FragmentActivity - -/** Loads [PlaybackVideoFragment]. */ -class PlaybackActivity : FragmentActivity() { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - if (savedInstanceState == null) { - supportFragmentManager.beginTransaction() - .replace(android.R.id.content, PlaybackVideoFragment()) - .commit() - } - } -} \ No newline at end of file diff --git a/tv/src/main/java/com/metabrainz/android/PlaybackVideoFragment.kt b/tv/src/main/java/com/metabrainz/android/PlaybackVideoFragment.kt deleted file mode 100644 index fac6287d..00000000 --- a/tv/src/main/java/com/metabrainz/android/PlaybackVideoFragment.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.metabrainz.android - -import android.net.Uri -import android.os.Bundle -import androidx.leanback.app.VideoSupportFragment -import androidx.leanback.app.VideoSupportFragmentGlueHost -import androidx.leanback.media.MediaPlayerAdapter -import androidx.leanback.media.PlaybackTransportControlGlue -import androidx.leanback.widget.PlaybackControlsRow - -/** Handles video playback with media controls. */ -class PlaybackVideoFragment : VideoSupportFragment() { - - private lateinit var mTransportControlGlue: PlaybackTransportControlGlue - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - val (_, title, description, _, _, videoUrl) = - activity?.intent?.getSerializableExtra(DetailsActivity.MOVIE) as Movie - - val glueHost = VideoSupportFragmentGlueHost(this@PlaybackVideoFragment) - val playerAdapter = MediaPlayerAdapter(activity) - playerAdapter.setRepeatAction(PlaybackControlsRow.RepeatAction.INDEX_NONE) - - mTransportControlGlue = PlaybackTransportControlGlue(getActivity(), playerAdapter) - mTransportControlGlue.host = glueHost - mTransportControlGlue.title = title - mTransportControlGlue.subtitle = description - mTransportControlGlue.playWhenPrepared() - - playerAdapter.setDataSource(Uri.parse(videoUrl)) - } - - override fun onPause() { - super.onPause() - mTransportControlGlue.pause() - } -} \ No newline at end of file diff --git a/tv/src/main/java/com/metabrainz/android/VideoDetailsFragment.kt b/tv/src/main/java/com/metabrainz/android/VideoDetailsFragment.kt deleted file mode 100644 index e0450c6f..00000000 --- a/tv/src/main/java/com/metabrainz/android/VideoDetailsFragment.kt +++ /dev/null @@ -1,211 +0,0 @@ -package com.metabrainz.android - -import android.content.Context -import android.content.Intent -import android.graphics.Bitmap -import android.os.Bundle -import android.graphics.drawable.Drawable -import androidx.leanback.app.DetailsSupportFragment -import androidx.leanback.app.DetailsSupportFragmentBackgroundController -import androidx.leanback.widget.Action -import androidx.leanback.widget.ArrayObjectAdapter -import androidx.leanback.widget.ClassPresenterSelector -import androidx.leanback.widget.DetailsOverviewRow -import androidx.leanback.widget.FullWidthDetailsOverviewRowPresenter -import androidx.leanback.widget.FullWidthDetailsOverviewSharedElementHelper -import androidx.leanback.widget.HeaderItem -import androidx.leanback.widget.ImageCardView -import androidx.leanback.widget.ListRow -import androidx.leanback.widget.ListRowPresenter -import androidx.leanback.widget.OnActionClickedListener -import androidx.leanback.widget.OnItemViewClickedListener -import androidx.leanback.widget.Presenter -import androidx.leanback.widget.Row -import androidx.leanback.widget.RowPresenter -import androidx.core.app.ActivityOptionsCompat -import androidx.core.content.ContextCompat -import android.util.Log -import android.widget.Toast - -import com.bumptech.glide.Glide -import com.bumptech.glide.request.target.SimpleTarget -import com.bumptech.glide.request.transition.Transition - -import java.util.Collections - -/** - * A wrapper fragment for leanback details screens. - * It shows a detailed view of video and its metadata plus related videos. - */ -class VideoDetailsFragment : DetailsSupportFragment() { - - private var mSelectedMovie: Movie? = null - - private lateinit var mDetailsBackground: DetailsSupportFragmentBackgroundController - private lateinit var mPresenterSelector: ClassPresenterSelector - private lateinit var mAdapter: ArrayObjectAdapter - - override fun onCreate(savedInstanceState: Bundle?) { - Log.d(TAG, "onCreate DetailsFragment") - super.onCreate(savedInstanceState) - - mDetailsBackground = DetailsSupportFragmentBackgroundController(this) - - mSelectedMovie = requireActivity().intent.getSerializableExtra(DetailsActivity.MOVIE) as Movie - if (mSelectedMovie != null) { - mPresenterSelector = ClassPresenterSelector() - mAdapter = ArrayObjectAdapter(mPresenterSelector) - setupDetailsOverviewRow() - setupDetailsOverviewRowPresenter() - setupRelatedMovieListRow() - adapter = mAdapter - initializeBackground(mSelectedMovie) - onItemViewClickedListener = ItemViewClickedListener() - } else { - val intent = Intent(requireActivity(), MainActivity::class.java) - startActivity(intent) - } - } - - private fun initializeBackground(movie: Movie?) { - mDetailsBackground.enableParallax() - Glide.with(requireActivity()) - .asBitmap() - .centerCrop() - .error(R.drawable.default_background) - .load(movie?.backgroundImageUrl) - .into>(object : SimpleTarget() { - override fun onResourceReady( - bitmap: Bitmap, - transition: Transition?, - ) { - mDetailsBackground.coverBitmap = bitmap - mAdapter.notifyArrayItemRangeChanged(0, mAdapter.size()) - } - }) - } - - private fun setupDetailsOverviewRow() { - Log.d(TAG, "doInBackground: " + mSelectedMovie?.toString()) - val row = DetailsOverviewRow(mSelectedMovie) - row.imageDrawable = ContextCompat.getDrawable(requireActivity(), R.drawable.default_background) - val width = convertDpToPixel(requireActivity(), DETAIL_THUMB_WIDTH) - val height = convertDpToPixel(requireActivity(), DETAIL_THUMB_HEIGHT) - Glide.with(requireActivity()) - .load(mSelectedMovie?.cardImageUrl) - .centerCrop() - .error(R.drawable.default_background) - .into>(object : SimpleTarget(width, height) { - override fun onResourceReady( - drawable: Drawable, - transition: Transition?, - ) { - Log.d(TAG, "details overview card image url ready: " + drawable) - row.imageDrawable = drawable - mAdapter.notifyArrayItemRangeChanged(0, mAdapter.size()) - } - }) - - val actionAdapter = ArrayObjectAdapter() - - actionAdapter.add( - Action( - ACTION_WATCH_TRAILER, - resources.getString(R.string.watch_trailer_1), - resources.getString(R.string.watch_trailer_2))) - actionAdapter.add( - Action( - ACTION_RENT, - resources.getString(R.string.rent_1), - resources.getString(R.string.rent_2))) - actionAdapter.add( - Action( - ACTION_BUY, - resources.getString(R.string.buy_1), - resources.getString(R.string.buy_2))) - row.actionsAdapter = actionAdapter - - mAdapter.add(row) - } - - private fun setupDetailsOverviewRowPresenter() { - // Set detail background. - val detailsPresenter = FullWidthDetailsOverviewRowPresenter(DetailsDescriptionPresenter()) - detailsPresenter.backgroundColor = - ContextCompat.getColor(requireActivity(), R.color.selected_background) - - // Hook up transition element. - val sharedElementHelper = FullWidthDetailsOverviewSharedElementHelper() - sharedElementHelper.setSharedElementEnterTransition( - activity, DetailsActivity.SHARED_ELEMENT_NAME) - detailsPresenter.setListener(sharedElementHelper) - detailsPresenter.isParticipatingEntranceTransition = true - - detailsPresenter.onActionClickedListener = OnActionClickedListener { action -> - if (action.id == ACTION_WATCH_TRAILER) { - val intent = Intent(requireActivity(), PlaybackActivity::class.java) - intent.putExtra(DetailsActivity.MOVIE, mSelectedMovie) - startActivity(intent) - } else { - Toast.makeText(requireActivity(), action.toString(), Toast.LENGTH_SHORT).show() - } - } - mPresenterSelector.addClassPresenter(DetailsOverviewRow::class.java, detailsPresenter) - } - - private fun setupRelatedMovieListRow() { - val subcategories = arrayOf(getString(R.string.related_movies)) - val list = MovieList.list - - Collections.shuffle(list) - val listRowAdapter = ArrayObjectAdapter(CardPresenter()) - for (j in 0 until NUM_COLS) { - listRowAdapter.add(list[j % 5]) - } - - val header = HeaderItem(0, subcategories[0]) - mAdapter.add(ListRow(header, listRowAdapter)) - mPresenterSelector.addClassPresenter(ListRow::class.java, ListRowPresenter()) - } - - private fun convertDpToPixel(context: Context, dp: Int): Int { - val density = context.applicationContext.resources.displayMetrics.density - return Math.round(dp.toFloat() * density) - } - - private inner class ItemViewClickedListener : OnItemViewClickedListener { - override fun onItemClicked( - itemViewHolder: Presenter.ViewHolder?, - item: Any?, - rowViewHolder: RowPresenter.ViewHolder, - row: Row, - ) { - if (item is Movie) { - Log.d(TAG, "Item: " + item.toString()) - val intent = Intent(requireActivity(), DetailsActivity::class.java) - intent.putExtra(resources.getString(R.string.movie), mSelectedMovie) - - val bundle = - ActivityOptionsCompat.makeSceneTransitionAnimation( - requireActivity(), - (itemViewHolder?.view as ImageCardView).mainImageView, - DetailsActivity.SHARED_ELEMENT_NAME) - .toBundle() - startActivity(intent, bundle) - } - } - } - - companion object { - private val TAG = "VideoDetailsFragment" - - private val ACTION_WATCH_TRAILER = 1L - private val ACTION_RENT = 2L - private val ACTION_BUY = 3L - - private val DETAIL_THUMB_WIDTH = 274 - private val DETAIL_THUMB_HEIGHT = 274 - - private val NUM_COLS = 10 - } -} \ No newline at end of file diff --git a/tv/src/main/res/drawable/default_background.xml b/tv/src/main/res/drawable/default_background.xml deleted file mode 100644 index 82e51a2b..00000000 --- a/tv/src/main/res/drawable/default_background.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - \ No newline at end of file diff --git a/tv/src/main/res/drawable/ic_banner_foreground.xml b/tv/src/main/res/drawable/ic_banner_foreground.xml deleted file mode 100644 index 6b3ecc8c..00000000 --- a/tv/src/main/res/drawable/ic_banner_foreground.xml +++ /dev/null @@ -1,112 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tv/src/main/res/drawable/movie.png b/tv/src/main/res/drawable/movie.png deleted file mode 100644 index cb5cb6d3..00000000 Binary files a/tv/src/main/res/drawable/movie.png and /dev/null differ diff --git a/tv/src/main/res/layout/activity_details.xml b/tv/src/main/res/layout/activity_details.xml deleted file mode 100644 index 2aa3d828..00000000 --- a/tv/src/main/res/layout/activity_details.xml +++ /dev/null @@ -1,8 +0,0 @@ - - \ No newline at end of file diff --git a/tv/src/main/res/layout/activity_main.xml b/tv/src/main/res/layout/activity_main.xml deleted file mode 100644 index 86bbdaec..00000000 --- a/tv/src/main/res/layout/activity_main.xml +++ /dev/null @@ -1,9 +0,0 @@ - - \ No newline at end of file diff --git a/tv/src/main/res/mipmap-anydpi-v26/ic_banner.xml b/tv/src/main/res/mipmap-anydpi-v26/ic_banner.xml deleted file mode 100644 index a0a0dece..00000000 --- a/tv/src/main/res/mipmap-anydpi-v26/ic_banner.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/tv/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/tv/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 036d09bc..00000000 --- a/tv/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/tv/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/tv/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 036d09bc..00000000 --- a/tv/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/tv/src/main/res/mipmap-hdpi/ic_launcher.png b/tv/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index 572c5fb1..00000000 Binary files a/tv/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/tv/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/tv/src/main/res/mipmap-hdpi/ic_launcher_foreground.png deleted file mode 100644 index f925e897..00000000 Binary files a/tv/src/main/res/mipmap-hdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/tv/src/main/res/mipmap-hdpi/ic_launcher_round.png b/tv/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 41f9948d..00000000 Binary files a/tv/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/tv/src/main/res/mipmap-mdpi/ic_launcher.png b/tv/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 3471366b..00000000 Binary files a/tv/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/tv/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/tv/src/main/res/mipmap-mdpi/ic_launcher_foreground.png deleted file mode 100644 index 409beb44..00000000 Binary files a/tv/src/main/res/mipmap-mdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/tv/src/main/res/mipmap-mdpi/ic_launcher_round.png b/tv/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index c781cb4e..00000000 Binary files a/tv/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/tv/src/main/res/mipmap-xhdpi/ic_banner.png b/tv/src/main/res/mipmap-xhdpi/ic_banner.png deleted file mode 100644 index 722dd4cb..00000000 Binary files a/tv/src/main/res/mipmap-xhdpi/ic_banner.png and /dev/null differ diff --git a/tv/src/main/res/mipmap-xhdpi/ic_launcher.png b/tv/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index 729f470a..00000000 Binary files a/tv/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/tv/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/tv/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png deleted file mode 100644 index b816dbf3..00000000 Binary files a/tv/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/tv/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/tv/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index fd138788..00000000 Binary files a/tv/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/tv/src/main/res/mipmap-xxhdpi/ic_launcher.png b/tv/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 66503faa..00000000 Binary files a/tv/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/tv/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/tv/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png deleted file mode 100644 index a2058453..00000000 Binary files a/tv/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/tv/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/tv/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 0aafdc78..00000000 Binary files a/tv/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/tv/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/tv/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index 643eb604..00000000 Binary files a/tv/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/tv/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/tv/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png deleted file mode 100644 index 229daa00..00000000 Binary files a/tv/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/tv/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/tv/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index d6af4cc7..00000000 Binary files a/tv/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/tv/src/main/res/values/colors.xml b/tv/src/main/res/values/colors.xml deleted file mode 100644 index 733f3f53..00000000 --- a/tv/src/main/res/values/colors.xml +++ /dev/null @@ -1,8 +0,0 @@ - - #000000 - #DDDDDD - #0096a6 - #ffaa3f - #ffaa3f - #3d3d3d - \ No newline at end of file diff --git a/tv/src/main/res/values/ic_banner_background.xml b/tv/src/main/res/values/ic_banner_background.xml deleted file mode 100644 index d217ae9d..00000000 --- a/tv/src/main/res/values/ic_banner_background.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - #263238 - \ No newline at end of file diff --git a/tv/src/main/res/values/ic_launcher_background.xml b/tv/src/main/res/values/ic_launcher_background.xml deleted file mode 100644 index 801e235a..00000000 --- a/tv/src/main/res/values/ic_launcher_background.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - #263238 - \ No newline at end of file diff --git a/tv/src/main/res/values/strings.xml b/tv/src/main/res/values/strings.xml deleted file mode 100644 index baaa6b79..00000000 --- a/tv/src/main/res/values/strings.xml +++ /dev/null @@ -1,19 +0,0 @@ - - MusicBrainz - Videos by Your Company - Related Videos - Grid View - Error Fragment - Personal Settings - Watch trailer - FREE - Rent By Day - From $1.99 - Buy and Own - AT $9.99 - Movie - - - An error occurred - Dismiss - \ No newline at end of file diff --git a/tv/src/main/res/values/themes.xml b/tv/src/main/res/values/themes.xml deleted file mode 100644 index fba78f8b..00000000 --- a/tv/src/main/res/values/themes.xml +++ /dev/null @@ -1,4 +0,0 @@ - - -