You are on page 1of 12

[ 2CEIT509: MOBILE APPLICATION DEVELOPMENT ]

Assignment: 2

Submitted By: Rupam Bende


Enrollment number: 19012011127

Department of Computer
Engineering/Information Technology

19012011127_RupamBende MAD-5
Assignment-2
Assignment-2
Aim: Create Android Application by using Kotlin language.

Code:

activity_main.xml File:
<?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:fitsSystemWindows="false"
android:layout_height="match_parent"
tools:context=".Activity_Player">

<com.google.android.exoplayer2.ui.PlayerView
android:id="@+id/playerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

AndroidManifest.xml File:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.technic.exoplayer">

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

<application
android:allowBackup="true"
android:icon="@drawable/mylogo"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".Activity_Player"
android:theme="@style/AppThemeFullscreen" />
<activity android:name=".Activity_Videos">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />


</intent-filter>
</activity>

19012011127_RupamBende MAD-5
</application>

</manifest>

Activity_player.xml File:
<?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:fitsSystemWindows="false"
android:layout_height="match_parent"
tools:context=".Activity_Player">

<com.google.android.exoplayer2.ui.PlayerView
android:id="@+id/playerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Activity_videos.xml File:
<?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"
android:background="@color/black"
tools:context=".Activity_Videos">

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView_videos"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingEnd="16dp"
android:paddingRight="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Row_video.xml File:
<?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"

19012011127_RupamBende MAD-5
android:layout_width="match_parent"
android:layout_height="wrap_content">

<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="5dp"
android:layout_marginTop="16dp"
android:layout_marginLeft="16dp"
app:cardBackgroundColor="@color/grey"
android:layout_marginStart="16dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent">

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">

<ImageView
android:id="@+id/imageView_thumbnail"
android:layout_width="0dp"
android:layout_height="0dp"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginLeft="10dp"
android:text="Title"
android:layout_marginTop="10dp"
android:textSize="14sp"
android:textColor="@color/white"
app:layout_constraintHorizontal_bias="0"
android:ellipsize="end"
android:maxLines="1"
android:layout_marginRight="10dp"
app:layout_constraintRight_toRightOf="parent"
android:fontFamily="sans-serif-black"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView_thumbnail" />

<TextView
android:id="@+id/tv_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="00:00:00"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="16dp"
android:textSize="12sp"
android:textColor="@color/white"
android:fontFamily="sans-serif"
app:layout_constraintTop_toBottomOf="@+id/tv_title"
app:layout_constraintLeft_toLeftOf="@+id/tv_title"/>

19012011127_RupamBende MAD-5
</androidx.constraintlayout.widget.ConstraintLayout>

</androidx.cardview.widget.CardView>

</androidx.constraintlayout.widget.ConstraintLayout>

styles.xml File:
<resources>

<!-- Base application theme. -->


<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>

<style name="AppThemeFullscreen" parent="Theme.AppCompat.Light.NoActionBar">


<item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="android:fitsSystemWindows">false</item>
<item name="android:windowFullscreen">true</item>
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>

</resources>

strings.xml File:
<resources>
<string name="app_name">Smart Video Player</string>
</resources>

colors.xml File:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#000000</color>
<color name="colorPrimaryDark">#000000</color>
<color name="colorAccent">#FF9800</color>

<color name="white">#FFFFFF</color>
<color name="black">#000000</color>
<color name="grey">#353535</color>
</resources>

Activity_Player.kt File:
package com.technic.exoplayer

import androidx.appcompat.app.AppCompatActivity
import com.google.android.exoplayer2.ui.PlayerView
import com.google.android.exoplayer2.SimpleExoPlayer
import android.os.Bundle
import com.technic.exoplayer.R
import android.content.ContentUris
import android.net.Uri

19012011127_RupamBende MAD-5
import android.provider.MediaStore
import com.google.android.exoplayer2.source.MediaSource
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory
import com.google.android.exoplayer2.source.ProgressiveMediaSource
import com.google.android.exoplayer2.upstream.DataSource
import com.google.android.exoplayer2.util.Util

class Activity_Player : AppCompatActivity() {


var videoId: Long = 0
private var playerView: PlayerView? = null
private var player: SimpleExoPlayer? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_player)
initializeViews()
videoId = intent.extras!!.getLong("videoId")
}

private fun initializeViews() {


playerView = findViewById(R.id.playerView)
}

private fun initializePlayer() {


player = SimpleExoPlayer.Builder(this).build()
playerView!!.player = player
val videoUri =
ContentUris.withAppendedId(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
videoId)
val mediaSource = buildMediaSource(videoUri)
player!!.prepare(mediaSource)
player!!.playWhenReady = true
}

private fun buildMediaSource(uri: Uri): MediaSource {


val dataSourceFactory: DataSource.Factory =
DefaultDataSourceFactory(this, getString(R.string.app_name))
return
ProgressiveMediaSource.Factory(dataSourceFactory).createMediaSource(uri)
}

private fun releasePlayer() {


if (player != null) {
player!!.release()
player = null
}
}

override fun onStart() {


super.onStart()
if (Util.SDK_INT >= 24) {
initializePlayer()
}
}

override fun onResume() {


super.onResume()
if (Util.SDK_INT < 24 || player == null) {
initializePlayer()
}
}

override fun onPause() {

19012011127_RupamBende MAD-5
if (Util.SDK_INT < 24) {
releasePlayer()
}
super.onPause()
}

override fun onStop() {


if (Util.SDK_INT >= 24) {
releasePlayer()
}
super.onStop()
}
}

Activity_Videos.kt File:
package com.technic.exoplayer

import android.Manifest
import androidx.appcompat.app.AppCompatActivity
import com.technic.exoplayer.ModelVideo
import com.technic.exoplayer.AdapterVideoList
import android.os.Bundle
import com.technic.exoplayer.R
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.GridLayoutManager
import android.os.Build
import androidx.core.content.ContextCompat
import android.content.pm.PackageManager
import android.widget.Toast
import android.provider.MediaStore
import android.content.ContentUris
import java.util.*

class Activity_Videos : AppCompativity() {


private val videosList = ArrayList<ModelVideo>()
private var adapterVideoList: AdapterVideoList? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_videos)
initializeViews()
checkPermissions()
}

private fun initializeViews() {


val recyclerView = findViewById<RecyclerView>(R.id.recyclerView_videos)
recyclerView.layoutManager = GridLayoutManager(this, 3) //3 = column count
adapterVideoList = AdapterVideoList(this, videosList)
recyclerView.adapter = adapterVideoList
}

private fun checkPermissions() {


if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(
this,
Manifest.permission.READ_EXTERNAL_STORAGE
) != PackageManager.PERMISSION_GRANTED
) {
requestPermissions(arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE),
123)
} else {
loadVideos()
}

19012011127_RupamBende MAD-5
} else {
loadVideos()
}
}

override fun onRequestPermissionsResult(


requestCode: Int,
permissions: Array<String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == 123) {
if (grantResults.size > 0 && grantResults[0] ==
PackageManager.PERMISSION_GRANTED) {
loadVideos()
} else {
Toast.makeText(this, "Permission was not granted",
Toast.LENGTH_SHORT).show()
}
}
}

private fun loadVideos() {


object : Thread() {
override fun run() {
super.run()
val projection = arrayOf(
MediaStore.Video.Media._ID,
MediaStore.Video.Media.DISPLAY_NAME,
MediaStore.Video.Media.DURATION
)
val sortOrder = MediaStore.Video.Media.DATE_ADDED + " DESC"
val cursor = application.contentResolver.query(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
projection,
null,
null,
sortOrder
)
if (cursor != null) {
val idColumn =
cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID)
val titleColumn =

cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DISPLAY_NAME)
val durationColumn =
cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATION)
while (cursor.moveToNext()) {
val id = cursor.getLong(idColumn)
val title = cursor.getString(titleColumn)
val duration = cursor.getInt(durationColumn)
val data = ContentUris.withAppendedId(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
id
)
var duration_formatted: String
val sec = duration / 1000 % 60
val min = duration / (1000 * 60) % 60
val hrs = duration / (1000 * 60 * 60)
duration_formatted = if (hrs == 0) {
min.toString() + ":" + String.format(Locale.UK, "%02d",
sec)

19012011127_RupamBende MAD-5
} else {
"$hrs:" + String.format(
Locale.UK,
"%02d",
min
) + ":" + String.format(Locale.UK, "%02d", sec)
}
videosList.add(ModelVideo(id, data, title,
duration_formatted))
runOnUiThread {
adapterVideoList!!.notifyItemInserted(videosList.size - 1) }
}
}
}
}.start()
}
}

AdapterVideoList.kt File:
package com.technic.exoplayer

import android.content.Context
import com.technic.exoplayer.ModelVideo
import androidx.recyclerview.widget.RecyclerView
import com.technic.exoplayer.AdapterVideoList.MyViewHolder
import android.view.ViewGroup
import android.view.LayoutInflater
import com.technic.exoplayer.R
import com.bumptech.glide.Glide
import android.content.Intent
import android.view.View
import android.widget.ImageView
import com.technic.exoplayer.Activity_Player
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import android.widget.TextView
import java.util.ArrayList

class AdapterVideoList internal constructor(


var context: Context,
videosList: ArrayList<ModelVideo>
) : RecyclerView.Adapter<MyViewHolder>() {
var videosList = ArrayList<ModelVideo>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val itemView =
LayoutInflater.from(parent.context).inflate(R.layout.row_video, parent,
false)
return MyViewHolder(itemView)
}

override fun onBindViewHolder(holder: MyViewHolder, position: Int) {


val item = videosList[position]
holder.tv_title.text = item.title
holder.tv_duration.text = item.duration
Glide.with(context).load(item.data).into(holder.imgView_thumbnail)
holder.itemView.setOnClickListener { v ->
val intent = Intent(v.context, Activity_Player::class.java)
intent.putExtra("videoId", item.id)
v.context.startActivity(intent)
}
}

19012011127_RupamBende MAD-5
override fun getItemCount(): Int {
return videosList.size
}

internal class MyViewHolder(itemView: View) : ViewHolder(itemView) {


var imgView_thumbnail: ImageView
var tv_title: TextView
var tv_duration: TextView

init {
tv_title = itemView.findViewById(R.id.tv_title)
tv_duration = itemView.findViewById(R.id.tv_duration)
imgView_thumbnail = itemView.findViewById(R.id.imageView_thumbnail)
}
}

init {
this.videosList = videosList
}
}

ModelVideo.kt File:
/**
* Automatically generated file. DO NOT MODIFY
*/
package com.technic.exoplayer

import java.lang.Boolean

object BuildConfig {
val DEBUG = Boolean.parseBoolean("true")
const val APPLICATION_ID = "com.technic.exoplayer"
const val BUILD_TYPE = "debug"
const val VERSION_CODE = 1
const val VERSION_NAME = "1.0"
}

19012011127_RupamBende MAD-5
Output:

19012011127_RupamBende MAD-5
19012011127_RupamBende MAD-5

You might also like