Download Functionality Added.

This commit is contained in:
shabinder 2020-07-21 09:43:58 +05:30
parent 3d401744c0
commit f57fffd6eb
7 changed files with 110 additions and 38 deletions

View File

@ -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"

View File

@ -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
} }

View File

@ -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)

View File

@ -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
}
}

View File

@ -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
} }

View File

@ -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")

View File

@ -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"