mirror of
https://github.com/Shabinder/SpotiFlyer.git
synced 2024-11-24 18:04:33 +01:00
Download Functionality Added.
This commit is contained in:
parent
3d401744c0
commit
f57fffd6eb
@ -9,7 +9,7 @@
|
|||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
|
<!-- <uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />-->
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package com.shabinder.musicForEveryone
|
package com.shabinder.musicForEveryone
|
||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
|
import android.app.DownloadManager
|
||||||
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
@ -11,7 +13,7 @@ import androidx.databinding.DataBindingUtil
|
|||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import com.github.kiulian.downloader.YoutubeDownloader
|
import com.github.kiulian.downloader.YoutubeDownloader
|
||||||
import com.shabinder.musicForEveryone.databinding.MainActivityBinding
|
import com.shabinder.musicForEveryone.databinding.MainActivityBinding
|
||||||
import com.shabinder.musicForEveryone.utils.YoutubeConnector
|
import com.shabinder.musicForEveryone.utils.YoutubeInterface
|
||||||
import com.spotify.sdk.android.authentication.AuthenticationClient
|
import com.spotify.sdk.android.authentication.AuthenticationClient
|
||||||
import com.spotify.sdk.android.authentication.AuthenticationRequest
|
import com.spotify.sdk.android.authentication.AuthenticationRequest
|
||||||
import com.spotify.sdk.android.authentication.AuthenticationResponse
|
import com.spotify.sdk.android.authentication.AuthenticationResponse
|
||||||
@ -24,6 +26,7 @@ import retrofit.RestAdapter
|
|||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
private lateinit var binding: MainActivityBinding
|
private lateinit var binding: MainActivityBinding
|
||||||
var ytDownloader : YoutubeDownloader? = null
|
var ytDownloader : YoutubeDownloader? = null
|
||||||
|
var downloadManager : DownloadManager? = null
|
||||||
val REDIRECT_URI = "musicforeveryone://callback"
|
val REDIRECT_URI = "musicforeveryone://callback"
|
||||||
val CLIENT_ID:String = "694d8bf4f6ec420fa66ea7fb4c68f89d"
|
val CLIENT_ID:String = "694d8bf4f6ec420fa66ea7fb4c68f89d"
|
||||||
// val musicDirectory = File(this.filesDir?.absolutePath + "/Music/")
|
// val musicDirectory = File(this.filesDir?.absolutePath + "/Music/")
|
||||||
@ -49,8 +52,11 @@ class MainActivity : AppCompatActivity() {
|
|||||||
ytDownloader = YoutubeDownloader()
|
ytDownloader = YoutubeDownloader()
|
||||||
sharedViewModel.ytDownloader = ytDownloader
|
sharedViewModel.ytDownloader = ytDownloader
|
||||||
//Initialing Communication with Youtube
|
//Initialing Communication with Youtube
|
||||||
YoutubeConnector.youtubeConnector()
|
YoutubeInterface.youtubeConnector()
|
||||||
|
|
||||||
|
//Getting System Download Manager
|
||||||
|
downloadManager = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
|
||||||
|
sharedViewModel.downloadManager = downloadManager
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.shabinder.musicForEveryone
|
package com.shabinder.musicForEveryone
|
||||||
|
|
||||||
|
import android.app.DownloadManager
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import com.github.kiulian.downloader.YoutubeDownloader
|
import com.github.kiulian.downloader.YoutubeDownloader
|
||||||
@ -14,6 +15,8 @@ class SharedViewModel : ViewModel() {
|
|||||||
var spotify :SpotifyService? = null
|
var spotify :SpotifyService? = null
|
||||||
var spotifyExtra :SpotifyNewService? = null
|
var spotifyExtra :SpotifyNewService? = null
|
||||||
var ytDownloader : YoutubeDownloader? = null
|
var ytDownloader : YoutubeDownloader? = null
|
||||||
|
var downloadManager : DownloadManager? = null
|
||||||
|
|
||||||
|
|
||||||
fun getTrackDetails(trackLink:String): Track?{
|
fun getTrackDetails(trackLink:String): Track?{
|
||||||
return spotify?.getTrack(trackLink)
|
return spotify?.getTrack(trackLink)
|
||||||
|
@ -0,0 +1,88 @@
|
|||||||
|
package com.shabinder.musicForEveryone.downloadHelper
|
||||||
|
|
||||||
|
import android.app.DownloadManager
|
||||||
|
import android.app.DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Environment
|
||||||
|
import android.util.Log
|
||||||
|
import com.github.kiulian.downloader.YoutubeDownloader
|
||||||
|
import com.github.kiulian.downloader.model.formats.Format
|
||||||
|
import com.github.kiulian.downloader.model.quality.AudioQuality
|
||||||
|
import com.shabinder.musicForEveryone.utils.YoutubeInterface
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
interface DownloadHelper {
|
||||||
|
fun downloadTrack(ytDownloader: YoutubeDownloader?, downloadManager: DownloadManager?, searchQuery:String){
|
||||||
|
//@data = 1st object from YT query.
|
||||||
|
val data = YoutubeInterface.search(searchQuery)?.get(0)
|
||||||
|
if (data==null){Log.i("DownloadHelper","Youtube Request Failed!")}else{
|
||||||
|
|
||||||
|
//Fetching a Video Object.
|
||||||
|
val video = ytDownloader?.getVideo(data.id)
|
||||||
|
val details = video?.details()
|
||||||
|
|
||||||
|
val format:Format = video?.findAudioWithQuality(AudioQuality.low)?.get(0) as Format
|
||||||
|
|
||||||
|
val audioUrl = format.url()
|
||||||
|
|
||||||
|
if (audioUrl != null) {
|
||||||
|
downloadFile(audioUrl,downloadManager,details?.title()?:"Error")
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Downloading Using Android Download Manager
|
||||||
|
* */
|
||||||
|
fun downloadFile(url: String, downloadManager: DownloadManager?,title:String){
|
||||||
|
val audioUri = Uri.parse(url)
|
||||||
|
val outputDir = File.separator + "Spotify-Downloads" +File.separator + "${removeIllegalChars(title)}.mp3"
|
||||||
|
|
||||||
|
val request = DownloadManager.Request(audioUri)
|
||||||
|
.setAllowedNetworkTypes(
|
||||||
|
DownloadManager.Request.NETWORK_WIFI or
|
||||||
|
DownloadManager.Request.NETWORK_MOBILE
|
||||||
|
)
|
||||||
|
.setAllowedOverRoaming(false)
|
||||||
|
.setTitle(title)
|
||||||
|
.setDescription("Spotify Downloader Working Up here...")
|
||||||
|
.setDestinationInExternalPublicDir(Environment.DIRECTORY_MUSIC,outputDir)
|
||||||
|
.setNotificationVisibility(VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
|
||||||
|
downloadManager?.enqueue(request)
|
||||||
|
Log.i("DownloadManager","Download Request Sent")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removing Illegal Chars from File Name
|
||||||
|
* **/
|
||||||
|
fun removeIllegalChars(fileName: String): String? {
|
||||||
|
val illegalCharArray = charArrayOf(
|
||||||
|
'/',
|
||||||
|
'\n',
|
||||||
|
'\r',
|
||||||
|
'\t',
|
||||||
|
'\u0000',
|
||||||
|
'\u000C',
|
||||||
|
'`',
|
||||||
|
'?',
|
||||||
|
'*',
|
||||||
|
'\\',
|
||||||
|
'<',
|
||||||
|
'>',
|
||||||
|
'|',
|
||||||
|
'\"',
|
||||||
|
'.',
|
||||||
|
':'
|
||||||
|
)
|
||||||
|
var name = fileName
|
||||||
|
for (c in illegalCharArray) {
|
||||||
|
name = fileName.replace(c, '_')
|
||||||
|
}
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,6 @@
|
|||||||
package com.shabinder.musicForEveryone.fragments
|
package com.shabinder.musicForEveryone.fragments
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Environment
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
@ -11,23 +10,20 @@ import androidx.databinding.DataBindingUtil
|
|||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import com.github.kiulian.downloader.model.formats.Format
|
|
||||||
import com.github.kiulian.downloader.model.quality.AudioQuality
|
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import com.shabinder.musicForEveryone.R
|
import com.shabinder.musicForEveryone.R
|
||||||
import com.shabinder.musicForEveryone.SharedViewModel
|
import com.shabinder.musicForEveryone.SharedViewModel
|
||||||
import com.shabinder.musicForEveryone.bindImage
|
import com.shabinder.musicForEveryone.bindImage
|
||||||
import com.shabinder.musicForEveryone.databinding.MainFragmentBinding
|
import com.shabinder.musicForEveryone.databinding.MainFragmentBinding
|
||||||
import com.shabinder.musicForEveryone.utils.YoutubeConnector
|
import com.shabinder.musicForEveryone.downloadHelper.DownloadHelper
|
||||||
import kaaes.spotify.webapi.android.SpotifyService
|
import kaaes.spotify.webapi.android.SpotifyService
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
|
|
||||||
class MainFragment : Fragment() {
|
class MainFragment : Fragment(),DownloadHelper {
|
||||||
lateinit var binding:MainFragmentBinding
|
lateinit var binding:MainFragmentBinding
|
||||||
private lateinit var sharedViewModel: SharedViewModel
|
private lateinit var sharedViewModel: SharedViewModel
|
||||||
var spotify : SpotifyService? = null
|
var spotify : SpotifyService? = null
|
||||||
|
var type:String = ""
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater, container: ViewGroup?,
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
@ -45,9 +41,9 @@ class MainFragment : Fragment() {
|
|||||||
val spotifyLink = binding.spotifyLink.text.toString()
|
val spotifyLink = binding.spotifyLink.text.toString()
|
||||||
|
|
||||||
val link = spotifyLink.substringAfterLast('/' , "Error").substringBefore('?')
|
val link = spotifyLink.substringAfterLast('/' , "Error").substringBefore('?')
|
||||||
val type = spotifyLink.substringBeforeLast('/' , "Error").substringAfterLast('/')
|
type = spotifyLink.substringBeforeLast('/' , "Error").substringAfterLast('/')
|
||||||
|
|
||||||
Log.i("Fragment",link)
|
Log.i("Fragment", "$type : $link")
|
||||||
|
|
||||||
when(type){
|
when(type){
|
||||||
"track" -> {
|
"track" -> {
|
||||||
@ -100,29 +96,9 @@ class MainFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
binding.btnDownload.setOnClickListener {
|
binding.btnDownload.setOnClickListener {
|
||||||
val data = YoutubeConnector.search(
|
downloadTrack(sharedViewModel.ytDownloader,sharedViewModel.downloadManager,"${binding.name.text} ${if(binding.artist.text != "TextView" ){binding.artist.text}else{""}}")
|
||||||
"${binding.name.text} ${if(binding.artist.text != "TextView" ){binding.artist.text}else{""}}")
|
|
||||||
?.get(0)
|
|
||||||
if (data==null){showToast("Youtube Request Failed!")}else{
|
|
||||||
val ytDownloader = sharedViewModel.ytDownloader
|
|
||||||
val video = ytDownloader?.getVideo(data.id)
|
|
||||||
val details = video?.details()
|
|
||||||
|
|
||||||
val outputDir = File(Environment.getExternalStorageDirectory().toString() + File.separator + "MyAudio")
|
|
||||||
val format:Format = video?.findAudioWithQuality(AudioQuality.low)?.get(0) as Format
|
|
||||||
val audioUrl = format.url()
|
|
||||||
if (audioUrl != null) {
|
|
||||||
Log.i("ytDownloader", audioUrl)
|
|
||||||
}else{Log.i("YT audio url is null", format.toString())}
|
|
||||||
|
|
||||||
val file:File = video.download( format , outputDir)
|
|
||||||
|
|
||||||
Log.i("YT File Path=> ", file.path)
|
|
||||||
|
|
||||||
Log.i("ytDownloader", details?.title()?:"Error")
|
|
||||||
binding.name.text = details?.title()
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ import com.google.api.client.json.jackson2.JacksonFactory
|
|||||||
import com.google.api.services.youtube.YouTube
|
import com.google.api.services.youtube.YouTube
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
|
||||||
object YoutubeConnector {
|
object YoutubeInterface {
|
||||||
private var youtube: YouTube? = null
|
private var youtube: YouTube? = null
|
||||||
private var query:YouTube.Search.List? = null
|
private var query:YouTube.Search.List? = null
|
||||||
var apiKey:String = "AIzaSyDuRmMA_2mF56BjlhhNpa0SIbjMgjjFaEI"
|
var apiKey:String = "AIzaSyDuRmMA_2mF56BjlhhNpa0SIbjMgjjFaEI"
|
||||||
@ -15,8 +15,7 @@ object YoutubeConnector {
|
|||||||
|
|
||||||
fun youtubeConnector() {
|
fun youtubeConnector() {
|
||||||
youtube =
|
youtube =
|
||||||
YouTube.Builder(NetHttpTransport(), JacksonFactory(),
|
YouTube.Builder(NetHttpTransport(), JacksonFactory(), HttpRequestInitializer { })
|
||||||
HttpRequestInitializer { })
|
|
||||||
.setApplicationName("Music For Everyone").build()
|
.setApplicationName("Music For Everyone").build()
|
||||||
try {
|
try {
|
||||||
query = youtube?.search()?.list("id,snippet")
|
query = youtube?.search()?.list("id,snippet")
|
@ -10,7 +10,7 @@ buildscript {
|
|||||||
|
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath "com.android.tools.build:gradle:4.0.0"
|
classpath "com.android.tools.build:gradle:4.0.1"
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
//safe-Args
|
//safe-Args
|
||||||
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$navigationVersion"
|
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$navigationVersion"
|
||||||
|
Loading…
Reference in New Issue
Block a user