Skip to content

Commit

Permalink
Added a recycler
Browse files Browse the repository at this point in the history
Implemented a recycler view to display information like song name artist name and song cover and also a progress Bar to display visually download progress. Know issue: If you leave the app and reenter the app the application will crash working on a fix but it will probably be a while
  • Loading branch information
kostas214 committed Apr 12, 2023
1 parent 26b21c3 commit 32a7240
Show file tree
Hide file tree
Showing 13 changed files with 251 additions and 41 deletions.
12 changes: 6 additions & 6 deletions .idea/deploymentTargetDropDown.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ dependencies {


//YoutubeDl
implementation 'com.github.yausername.youtubedl-android:library:-SNAPSHOT'
implementation 'com.github.yausername.youtubedl-android:ffmpeg:-SNAPSHOT' // Optional
implementation "com.github.yausername.youtubedl-android:library:3a0252d88b4ae573068c63c3d08fc52c66102d55"
implementation "com.github.yausername.youtubedl-android:ffmpeg:3a0252d88b4ae573068c63c3d08fc52c66102d55"

//Coroutines
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'
Expand All @@ -105,6 +105,8 @@ dependencies {
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
implementation "androidx.navigation:navigation-dynamic-features-fragment:$nav_version"

implementation "io.coil-kt:coil:2.3.0"



}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,13 @@ class SpotifyDownloaderApplication : Application(){
YoutubeDL.getInstance().updateYoutubeDL(applicationContext)
}
} catch (e: Exception) {
Toast.makeText(applicationContext, "Download Library Initialization Failed", Toast.LENGTH_LONG).show()
withContext(Dispatchers.Main) {
Toast.makeText(
applicationContext,
"Download Library Initialization Failed",
Toast.LENGTH_LONG
).show()
}
}
if (!Python.isStarted()) {
Python.start(AndroidPlatform(this@SpotifyDownloaderApplication))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@ class MainActivity : AppCompatActivity() {

}







override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (toggle.onOptionsItemSelected(item)) {
return true
Expand Down
95 changes: 82 additions & 13 deletions app/src/main/java/com/example/spotifydownloader/downloadFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,23 @@ import androidx.activity.OnBackPressedCallback
import androidx.core.view.forEach
import androidx.documentfile.provider.DocumentFile
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.navigation.NavController
import androidx.navigation.Navigation
import androidx.navigation.fragment.navArgs
import androidx.recyclerview.widget.LinearLayoutManager
import com.chaquo.python.PyObject
import com.chaquo.python.Python
import com.chaquo.python.android.AndroidPlatform
import com.example.spotifydownloader.databinding.FragmentDownloadBinding
import com.example.spotifydownloader.model.recyclerViewAdaptor
import com.example.spotifydownloader.model.songItemData
import com.google.android.material.bottomnavigation.BottomNavigationView
import com.yausername.youtubedl_android.YoutubeDL
import com.yausername.youtubedl_android.YoutubeDLException
import com.yausername.youtubedl_android.YoutubeDLRequest
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.apache.commons.io.IOUtils
import java.io.File
import java.util.concurrent.Executors
Expand All @@ -41,7 +47,11 @@ class downloadFragment : Fragment(R.layout.fragment_download) {
private val args by navArgs<downloadFragmentArgs>()
private lateinit var module:PyObject
private var stop = false
private var songItems = mutableListOf<songItemData>()
private var completed = 0
private var index = 0

private val adapter = recyclerViewAdaptor(songItems)

override fun onDestroy() {
super.onDestroy()
Expand All @@ -51,13 +61,17 @@ class downloadFragment : Fragment(R.layout.fragment_download) {


override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
Log.d(tag,completed.toString())
binding = FragmentDownloadBinding.bind(view)


if (! Python.isStarted()) {
Python.start( AndroidPlatform(context as Activity))
}
binding.recyclerView.adapter = adapter
binding.recyclerView.layoutManager = LinearLayoutManager(context)


binding = FragmentDownloadBinding.bind(view)
navController =Navigation.findNavController(view)
val py = Python.getInstance()
module = py.getModule("main")
Expand All @@ -73,10 +87,15 @@ class downloadFragment : Fragment(R.layout.fragment_download) {
}


binding.cancelBtn.setOnClickListener {





binding.fabButton.setOnClickListener {
stop = true
Toast.makeText((context as Activity),"Stopping...",Toast.LENGTH_SHORT).show()
binding.cancelBtn.isEnabled = false
binding.fabButton.isEnabled = false


}
Expand All @@ -93,17 +112,16 @@ class downloadFragment : Fragment(R.layout.fragment_download) {




binding.progressBar.progress = 0

if (isDeviceOnline(context as Activity)){

val concurrentThreads = args.Data.concurrentDownloads
val executors = Executors.newFixedThreadPool(concurrentThreads)

val songNamesSize = args.Data.songNames.size

binding.progressBar.max = songNamesSize




for (i in args.Data.songNames as MutableList<PyObject>) {

Expand All @@ -119,8 +137,9 @@ class downloadFragment : Fragment(R.layout.fragment_download) {

when (download(songName, args.Data.folderURI)) {
0 -> {
Log.d(tag,"$completed")

if (songNamesSize == binding.progressBar.progress) {
if (songNamesSize == completed) {
runOnUiThread {
Toast.makeText(
context as Activity,
Expand Down Expand Up @@ -160,7 +179,8 @@ class downloadFragment : Fragment(R.layout.fragment_download) {
}
}
2 -> {
if (songNamesSize == binding.progressBar.progress) {
Log.d(tag,"Completed $completed")
if (songNamesSize == completed) {
runOnUiThread {
Toast.makeText(
context as Activity,
Expand Down Expand Up @@ -264,7 +284,22 @@ class downloadFragment : Fragment(R.layout.fragment_download) {

val filename = videoInfo[0].toString()
val ytLInk = videoInfo[1].toString()
val code = videoInfo[2].toInt()
val imgUrl = videoInfo[2].toString()
val code = videoInfo[3].toInt()
val artistName = videoInfo[4].toString()
val trackName = videoInfo[5].toString()

val songData = songItemData(imgUrl,trackName,artistName,0)
songItems.add(songData)
val position = index
runOnUiThread {
adapter.notifyItemInserted(index)
binding.recyclerView.scrollToPosition(position)
}
index += 1




if (code == 0) {
try {
Expand All @@ -283,11 +318,38 @@ class downloadFragment : Fragment(R.layout.fragment_download) {
val documentFIle: DocumentFile =
DocumentFile.fromTreeUri((context as Activity), data!!)!!
val dc: DocumentFile? = documentFIle.findFile(filename)









if (isDeviceOnline(context as Activity) && dc?.exists() == null) {
try {






YoutubeDL.getInstance().execute(
request
) { _: Float, _: Long, _: String? -> }
) { progress: Float, _: Long, _: String? ->
//Log.d(tag,"Progress is $progress and the song is $songName")
if (progress >0){
songItems[position].progress = progress.toInt()
runOnUiThread {
adapter.notifyItemChanged(position)
}

}



}

} catch (e: YoutubeDLException) {
Log.e(tag, e.message!!)
Expand Down Expand Up @@ -332,11 +394,18 @@ class downloadFragment : Fragment(R.layout.fragment_download) {
} else {
Log.d(tag, "Already exists skipping")
tmpFile.deleteRecursively()
binding.progressBar.incrementProgressBy(1)
songItems[position].progress = 100
runOnUiThread {
adapter.notifyItemChanged(position)
}
//binding.progressBar.incrementProgressBy(1)
completed += 1
return 2
}
Log.d(tag, "No errors")
binding.progressBar.incrementProgressBy(1)
//binding.progressBar.incrementProgressBy(1)
completed += 1

tmpFile.deleteRecursively()
return 0
} catch (e: java.lang.NullPointerException) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.example.spotifydownloader.model

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.ProgressBar
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import coil.load
import com.example.spotifydownloader.R

class recyclerViewAdaptor (private val songData: List<songItemData>)
:RecyclerView.Adapter<recyclerViewAdaptor.ViewHolder>() {




class ViewHolder(ItemView: View):RecyclerView.ViewHolder(ItemView){
val songCoverImage: ImageView = itemView.findViewById(R.id.songCoverImage)
val songTitle : TextView = itemView.findViewById(R.id.songTitle)
val artistName : TextView = itemView.findViewById(R.id.artistName)
val progressBar : ProgressBar = itemView.findViewById(R.id.progressBar)


}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.song_item,parent,false)
return ViewHolder(view)
}

override fun getItemCount(): Int {
return songData.size
}

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val recyclerViewAdaptor = songData[position]

holder.songCoverImage.load(recyclerViewAdaptor.imageUrl)


if (recyclerViewAdaptor.songName.length>19) {
holder.songTitle.text = recyclerViewAdaptor.songName.take(17).plus("...")
}
else{
holder.songTitle.text = recyclerViewAdaptor.songName
}
holder.artistName.text = recyclerViewAdaptor.artistName
holder.progressBar.progress = recyclerViewAdaptor.progress


}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.example.spotifydownloader.model

import android.graphics.Bitmap

data class songItemData(val imageUrl : String,
val songName: String,
val artistName:String,
var progress:Int)
17 changes: 14 additions & 3 deletions app/src/main/python/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,23 +101,34 @@ def songSearchSpotifyAlbum(albumLink):
def getDownloadPath(songs):
fileName = ""
songUrl=""
imgUrl=""
songName =""
artistName=""
albumUrl=""
songName=""


try:
tracks = sp.search(songs)
albumUrl = tracks['tracks']['items'][0]['album']['images'][1]['url']
songSearch = VideosSearch(songs, limit=1).result()
artistName = tracks['tracks']['items'][0]['artists'][0]['name']
songName = tracks['tracks']['items'][0]['name']


try:

songId = songSearch['result'][0]['id']
except(IndexError):
return fileName,songUrl,2
return fileName,songUrl,albumUrl,2,artistName,songName
songUrl= "https://youtu.be/"+songId
songTitle = songSearch['result'][0]['title']
translation_table = str.maketrans('', '', string.punctuation)
safeString = songTitle.translate(translation_table)
fileName = safeString.replace(" ", "") + ".mp3"
except(httpx.ConnectError, ChunkedEncodingError, ReadError):
return fileName,songUrl,1
return fileName,songUrl,0
return fileName,songUrl,albumUrl,1,songName,artistName,songName
return fileName,songUrl,albumUrl,0,artistName,songName


def insertMetaData(songs,fileLocation):
Expand Down
Loading

0 comments on commit 32a7240

Please sign in to comment.