diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 835a5de3..64d7de01 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -36,6 +36,10 @@ android:name="com.spotify.sdk.android.authentication.LoginActivity" android:theme="@android:style/Theme.Translucent.NoTitleBar" /> + + \ No newline at end of file diff --git a/app/src/main/java/com/shabinder/musicForEveryone/MainActivity.kt b/app/src/main/java/com/shabinder/musicForEveryone/MainActivity.kt index f08f5700..0789fe4b 100644 --- a/app/src/main/java/com/shabinder/musicForEveryone/MainActivity.kt +++ b/app/src/main/java/com/shabinder/musicForEveryone/MainActivity.kt @@ -104,8 +104,8 @@ class MainActivity : AppCompatActivity() ,DownloadHelper{ sharedViewModel.uiScope.launch { val me = spotifyExtra?.getMe()?.display_name - sharedViewModel.userName.value = me - Log.i("Network",me!!) + sharedViewModel.userName.value = "Logged in as: $me" + Log.i("Network","Hello, " + me!!) } sharedViewModel.userName.observe(this, Observer { diff --git a/app/src/main/java/com/shabinder/musicForEveryone/downloadHelper/DownloadHelper.kt b/app/src/main/java/com/shabinder/musicForEveryone/downloadHelper/DownloadHelper.kt index 49e7fee6..13126423 100644 --- a/app/src/main/java/com/shabinder/musicForEveryone/downloadHelper/DownloadHelper.kt +++ b/app/src/main/java/com/shabinder/musicForEveryone/downloadHelper/DownloadHelper.kt @@ -14,43 +14,49 @@ import kotlinx.coroutines.withContext import java.io.File interface DownloadHelper { - suspend fun downloadTrack(ytDownloader: YoutubeDownloader?, downloadManager: DownloadManager?, searchQuery:String){ + suspend fun downloadTrack( + ytDownloader: YoutubeDownloader?, + downloadManager: DownloadManager?, + searchQuery: String + ) { - withContext(Dispatchers.IO){ - val downloadIdList = mutableListOf() - val data = YoutubeInterface.search(searchQuery)?.get(0) - if (data==null){Log.i("DownloadHelper","Youtube Request Failed!")}else{ + withContext(Dispatchers.IO) { + val data = YoutubeInterface.search(searchQuery)?.get(0) + if (data == null) { + Log.i("DownloadHelper", "Youtube Request Failed!") + } else { val video = ytDownloader?.getVideo(data.id) //Fetching a Video Object. val details = video?.details() + try{ + val format: Format = + video?.findAudioWithQuality(AudioQuality.medium)?.get(0) as Format + val audioUrl = format.url() + Log.i("DHelper Link Found", audioUrl) + if (audioUrl != null) { + downloadFile(audioUrl, downloadManager, details!!.title()) + } else { + Log.i("YT audio url is null", format.toString()) + } + }catch (e:ArrayIndexOutOfBoundsException){ + Log.i("Catch",e.toString()) + } - val format:Format = video?.findAudioWithQuality(AudioQuality.low)?.get(0) as Format - - val audioUrl = format.url() - - if (audioUrl != null) { - downloadFile(audioUrl,downloadManager,details!!.title()) - Log.i("DHelper Start Download", audioUrl) - }else{Log.i("YT audio url is null", format.toString())} } - - -// Library Inbuilt function to Save File (Need Scoped Storage Implementation) -// val file: File = video.download( format , outputDir) } - //@data = 1st object from YT query. } /** * Downloading Using Android Download Manager * */ - suspend fun downloadFile(url: String, downloadManager: DownloadManager?,title:String){ - withContext(Dispatchers.IO){ + suspend fun downloadFile(url: String, downloadManager: DownloadManager?, title: String) { + withContext(Dispatchers.IO) { val audioUri = Uri.parse(url) - val outputDir = File.separator + "Spotify-Downloads" +File.separator + "${removeIllegalChars(title)}.mp3" + val outputDir = + File.separator + "Spotify-Downloads" + File.separator + "${removeIllegalChars(title)}.mp3" val request = DownloadManager.Request(audioUri) .setAllowedNetworkTypes( @@ -60,10 +66,10 @@ interface DownloadHelper { .setAllowedOverRoaming(false) .setTitle(title) .setDescription("Spotify Downloader Working Up here...") - .setDestinationInExternalPublicDir(Environment.DIRECTORY_MUSIC,outputDir) + .setDestinationInExternalPublicDir(Environment.DIRECTORY_MUSIC, outputDir) .setNotificationVisibility(VISIBILITY_VISIBLE_NOTIFY_COMPLETED) downloadManager?.enqueue(request) - Log.i("DownloadManager","Download Request Sent") + Log.i("DownloadManager", "Download Request Sent") } } diff --git a/app/src/main/java/com/shabinder/musicForEveryone/fragments/MainFragment.kt b/app/src/main/java/com/shabinder/musicForEveryone/fragments/MainFragment.kt index c31905d3..3fc56281 100644 --- a/app/src/main/java/com/shabinder/musicForEveryone/fragments/MainFragment.kt +++ b/app/src/main/java/com/shabinder/musicForEveryone/fragments/MainFragment.kt @@ -61,51 +61,56 @@ class MainFragment : Fragment(),DownloadHelper { adapter.trackList = trackList adapter.notifyDataSetChanged() Log.i("Adapter",trackList.size.toString()) + binding.btnDownloadAll.setOnClickListener { downloadAllTracks(trackList) } } } "album" -> { sharedViewModel.uiScope.launch{ - val albumObject = sharedViewModel.getAlbumDetails(link) + val albumObject = sharedViewModel.getAlbumDetails(link) +// binding.titleView.text = albumObject!!.name +// binding.titleView.visibility =View.VISIBLE + binding.imageView.visibility =View.VISIBLE + binding.btnDownloadAll.visibility =View.VISIBLE + val trackList = mutableListOf() + albumObject!!.tracks?.items?.forEach { trackList.add(it as Track) } + adapter.totalItems = trackList.size + adapter.trackList = trackList + adapter.notifyDataSetChanged() - binding.titleView.text = albumObject!!.name - binding.titleView.visibility =View.VISIBLE - binding.imageView.visibility =View.VISIBLE + Log.i("Adapter",trackList.size.toString()) - val trackList = mutableListOf() - albumObject.tracks?.items?.forEach { trackList.add(it as Track) } - adapter.totalItems = trackList.size - adapter.trackList = trackList - adapter.notifyDataSetChanged() + bindImage(binding.imageView, albumObject.images[0].url) + binding.btnDownloadAll.setOnClickListener { downloadAllTracks(trackList) } - Log.i("Adapter",trackList.size.toString()) - - bindImage(binding.imageView, albumObject.images[0].url) - } + } } "playlist" -> { sharedViewModel.uiScope.launch{ - val playlistObject = sharedViewModel.getPlaylistDetails(link) - - binding.titleView.text = "${if(playlistObject!!.name.length > 18){"${playlistObject.name.subSequence(0,17)}..."}else{playlistObject.name}}" - binding.titleView.visibility =View.VISIBLE - binding.imageView.visibility =View.VISIBLE - binding.playlistOwner.visibility =View.VISIBLE - binding.playlistOwner.text = "by: ${playlistObject.owner.display_name}" - val trackList = mutableListOf() - playlistObject.tracks?.items!!.forEach { trackList.add(it.track) } - adapter.trackList = trackList.toList() - adapter.totalItems = trackList.size - adapter.notifyDataSetChanged() - - Log.i("Adapter",trackList.size.toString()) + val playlistObject = sharedViewModel.getPlaylistDetails(link) + binding.btnDownloadAll.visibility =View.VISIBLE - bindImage(binding.imageView, playlistObject.images[0].url) + binding.imageView.visibility =View.VISIBLE +// binding.titleView.text = "${if(playlistObject!!.name.length > 18){"${playlistObject.name.subSequence(0,17)}..."}else{playlistObject.name}}" +// binding.titleView.visibility =View.VISIBLE +// binding.playlistOwner.visibility =View.VISIBLE +// binding.playlistOwner.text = "by: ${playlistObject.owner.display_name}" + val trackList = mutableListOf() + playlistObject!!.tracks?.items!!.forEach { trackList.add(it.track) } + adapter.trackList = trackList.toList() + adapter.totalItems = trackList.size + adapter.notifyDataSetChanged() + + Log.i("Adapter",trackList.size.toString()) + + bindImage(binding.imageView, playlistObject.images[0].url) + + binding.btnDownloadAll.setOnClickListener { downloadAllTracks(trackList) } } @@ -127,6 +132,12 @@ class MainFragment : Fragment(),DownloadHelper { return binding.root } + private fun downloadAllTracks(trackList : List) { + sharedViewModel.uiScope.launch { + trackList.forEach { downloadTrack(sharedViewModel.ytDownloader,sharedViewModel.downloadManager,"${it.name} ${it.artists[0].name?:""}") } + } + } + private fun showToast(message:String){ Toast.makeText(context,message,Toast.LENGTH_SHORT).show() } diff --git a/app/src/main/java/com/shabinder/musicForEveryone/utils/YoutubeInterface.kt b/app/src/main/java/com/shabinder/musicForEveryone/utils/YoutubeInterface.kt index 1c4c76e3..6fccea55 100644 --- a/app/src/main/java/com/shabinder/musicForEveryone/utils/YoutubeInterface.kt +++ b/app/src/main/java/com/shabinder/musicForEveryone/utils/YoutubeInterface.kt @@ -11,6 +11,8 @@ object YoutubeInterface { private var youtube: YouTube? = null private var query:YouTube.Search.List? = null var apiKey:String = "AIzaSyDuRmMA_2mF56BjlhhNpa0SIbjMgjjFaEI" + var apiKey2:String = "AIzaSyCotyqgqmz5qw4-IH0tiezIrIIDHLI2yNs" + var clientID : String = "1040727735015-er2mvvljt45cabkuqimsh3iabqvfpvms.apps.googleusercontent.com" fun youtubeConnector() { @@ -23,14 +25,14 @@ object YoutubeInterface { query?.maxResults = 1 query?.type = "video" query?.fields = - "items(id/kind,id/videoId,snippet/title,snippet/description,snippet/thumbnails/default/url)" + "items(id/videoId,snippet/title,snippet/thumbnails/default/url)" } catch (e: IOException) { - Log.i("YC", "Could not initialize: $e") + Log.i("YI", "Could not initialize: $e") } } fun search(keywords: String?): List? { - Log.i("YC searched for",keywords.toString()) + Log.i("YI searched for",keywords.toString()) if (youtube == null){youtubeConnector()} query!!.q= keywords return try { @@ -42,23 +44,25 @@ object YoutubeInterface { val item = VideoItem( id = result.id.videoId, title = result.snippet.title, - description = result.snippet.description, +// description = result.snippet.description, thumbnailUrl = result.snippet.thumbnails.default.url ) items.add(item) - Log.i("YC links received",item.id) + Log.i("YI links received",item.id) } items } catch (e: IOException) { - Log.d("YC", "Could not search: $e") - null + Log.d("YI", "Could not search: $e") + if(query?.key == apiKey2){return null} + query?.key = apiKey2 + search(keywords) } } data class VideoItem( val id:String, val title:String, - val description: String, +// val description: String, val thumbnailUrl:String ) diff --git a/app/src/main/res/layout/main_activity.xml b/app/src/main/res/layout/main_activity.xml index 6e5c311b..8752ec26 100644 --- a/app/src/main/res/layout/main_activity.xml +++ b/app/src/main/res/layout/main_activity.xml @@ -12,12 +12,12 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="2dp" - android:background="@drawable/text_background" + android:background="@drawable/text_background_accented" android:padding="5dp" android:paddingTop="6dp" - android:text="MainFragment" + android:text="Authentication Needed" android:textColor="@color/colorPrimary" - android:textSize="12dp" + android:textSize="10dp" android:textStyle="bold" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" diff --git a/app/src/main/res/layout/main_fragment.xml b/app/src/main/res/layout/main_fragment.xml index 81cba52f..32c42710 100644 --- a/app/src/main/res/layout/main_fragment.xml +++ b/app/src/main/res/layout/main_fragment.xml @@ -10,64 +10,96 @@ android:fitsSystemWindows="true" tools:context=".fragments.MainFragment"> + + + android:layout_height="280dp"> - - + android:layout_height="match_parent"> + + android:textSize="19sp" + app:layout_constraintBottom_toTopOf="@+id/image_view" + app:layout_constraintEnd_toStartOf="@+id/btn_search" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> -