diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index 37d461f3..ac6b0aec 100755
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -12,11 +12,9 @@
-
-
diff --git a/.idea/misc.xml b/.idea/misc.xml
index d10a516c..c340fa86 100755
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -8,7 +8,7 @@
-
+
diff --git a/app/build.gradle b/app/build.gradle
index 86a31347..f92aa26b 100755
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -15,42 +15,33 @@
* along with this program. If not, see .
*/
-apply plugin: 'com.android.application'
-apply plugin: 'kotlin-android'
-apply plugin: 'kotlin-android-extensions'
-apply plugin: 'kotlin-kapt'
-apply plugin: "androidx.navigation.safeargs.kotlin"
-apply plugin: 'dagger.hilt.android.plugin'
-apply plugin: 'kotlinx-serialization'
+plugins {
+ id 'com.android.application'
+ id 'kotlin-android'
+ id 'kotlin-kapt'
+ id 'kotlin-android-extensions'
+ id 'androidx.navigation.safeargs.kotlin'
+ id 'dagger.hilt.android.plugin'
+ id 'kotlinx-serialization'
+}
android {
- compileSdkVersion 29
+ compileSdkVersion 30
buildToolsVersion "30.0.2"
buildFeatures{
- //dataBinding = true
viewBinding = true
}
defaultConfig {
applicationId 'com.shabinder.spotiflyer'
minSdkVersion 22
- targetSdkVersion 29
+ targetSdkVersion 30
versionCode 8
versionName "1.6"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
- packagingOptions {
- exclude 'META-INF/DEPENDENCIES'
- exclude 'META-INF/LICENSE'
- exclude 'META-INF/LICENSE.txt'
- exclude 'META-INF/license.txt'
- exclude 'META-INF/NOTICE'
- exclude 'META-INF/NOTICE.txt'
- exclude 'META-INF/notice.txt'
- exclude 'META-INF/ASL2.0'
- exclude("META-INF/*.kotlin_module")
- }
+
buildTypes {
release {
minifyEnabled false
@@ -62,26 +53,42 @@ android {
targetCompatibility JavaVersion.VERSION_1_8
sourceCompatibility JavaVersion.VERSION_1_8
}
+
kotlinOptions {
jvmTarget = "1.8"
}
+
lintOptions {
abortOnError false
}
+
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8.toString()
}
+
+ packagingOptions {
+ exclude 'META-INF/DEPENDENCIES'
+ exclude 'META-INF/LICENSE'
+ exclude 'META-INF/LICENSE.txt'
+ exclude 'META-INF/license.txt'
+ exclude 'META-INF/NOTICE'
+ exclude 'META-INF/NOTICE.txt'
+ exclude 'META-INF/notice.txt'
+ exclude 'META-INF/ASL2.0'
+ exclude("META-INF/*.kotlin_module")
+ }
}
dependencies {
- implementation fileTree(dir: 'libs', include:['*.jar'])
+ //Android
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.4.10"
implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.browser:browser:1.2.0'
implementation 'androidx.webkit:webkit:1.3.0'
+ implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
@@ -89,46 +96,49 @@ dependencies {
implementation 'androidx.navigation:navigation-ui-ktx:2.3.1'
implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'com.google.android.material:material:1.2.1'
- implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.0'
- implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.0'
+ implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.1'
+ implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1'
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.1"
+ //FFmpeg
+ implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs')
+
+ //Room: Local SQL-lite Database
implementation "androidx.room:room-runtime:2.2.5"
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0'
kapt "androidx.room:room-compiler:2.2.5"
implementation "androidx.room:room-ktx:2.2.5"
+
+ //Hilt: Dependency Injection
implementation "com.google.dagger:hilt-android:$hilt_version"
kapt "com.google.dagger:hilt-android-compiler:$hilt_version"
implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha02'
kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha02'
- implementation project(path: ':mobile-ffmpeg')
- implementation 'androidx.legacy:legacy-support-v4:1.0.0'
- implementation ("com.github.bumptech.glide:recyclerview-integration:4.11.0") {
- transitive = true
- }
- kapt ("com.github.bumptech.glide:recyclerview-integration:4.11.0") {
- transitive = true
- }
+ //Glide-Image Loading
+ implementation ("com.github.bumptech.glide:recyclerview-integration:4.11.0") {transitive = true}
+ kapt ("com.github.bumptech.glide:recyclerview-integration:4.11.0") {transitive = true}
+ //HTTP
implementation 'com.squareup.okhttp3:okhttp:4.9.0'
-
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
+
+ //Json
implementation 'com.squareup.moshi:moshi:1.11.0'
implementation 'com.squareup.moshi:moshi-kotlin:1.11.0'
implementation "com.squareup.retrofit2:converter-moshi:2.9.0"
implementation "com.squareup.retrofit2:converter-scalars:2.9.0"
implementation 'com.beust:klaxon:5.4'
- implementation 'me.xdrop:fuzzywuzzy:1.3.1'
+ //Extras
+ implementation 'me.xdrop:fuzzywuzzy:1.3.1'
implementation 'com.mpatric:mp3agic:0.9.1'
implementation 'com.shreyaspatil:EasyUpiPayment:3.0.0'
- implementation 'com.github.sealedtx:java-youtube-downloader:2.4.4'
- implementation "androidx.tonyodev.fetch2:xfetch2:3.1.5"
implementation 'com.github.javiersantos:AppUpdater:2.7'
+ implementation "androidx.tonyodev.fetch2:xfetch2:3.1.5"
+ implementation 'com.github.sealedtx:java-youtube-downloader:2.4.4'
- implementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava'
testImplementation 'junit:junit:4.13.1'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
diff --git a/app/libs/mobile-ffmpeg.aar b/app/libs/mobile-ffmpeg.aar
new file mode 100755
index 00000000..ba7575f6
Binary files /dev/null and b/app/libs/mobile-ffmpeg.aar differ
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index a0b844e7..540f8fed 100755
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -24,8 +24,10 @@
-
+
+
@@ -38,9 +40,11 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:forceDarkAllowed="true"
- android:requestLegacyExternalStorage="true"
android:theme="@style/AppTheme"
+ android:requestLegacyExternalStorage="true"
+ tools:ignore="AllowBackup"
tools:targetApi="q">
+
diff --git a/app/src/main/java/com/shabinder/spotiflyer/MainActivity.kt b/app/src/main/java/com/shabinder/spotiflyer/MainActivity.kt
index fe42798c..6b377c39 100755
--- a/app/src/main/java/com/shabinder/spotiflyer/MainActivity.kt
+++ b/app/src/main/java/com/shabinder/spotiflyer/MainActivity.kt
@@ -39,7 +39,10 @@ import com.shabinder.spotiflyer.databinding.MainActivityBinding
import com.shabinder.spotiflyer.downloadHelper.DownloadHelper
import com.shabinder.spotiflyer.networking.SpotifyService
import com.shabinder.spotiflyer.networking.SpotifyServiceTokenRequest
-import com.shabinder.spotiflyer.utils.*
+import com.shabinder.spotiflyer.utils.NetworkInterceptor
+import com.shabinder.spotiflyer.utils.createDirectories
+import com.shabinder.spotiflyer.utils.showMessage
+import com.shabinder.spotiflyer.utils.startService
import com.squareup.moshi.Moshi
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
@@ -53,7 +56,6 @@ import javax.inject.Inject
/*
* This is App's God Activity
* */
-@Suppress("DEPRECATION")
@AndroidEntryPoint
class MainActivity : AppCompatActivity(){
private var spotifyService : SpotifyService? = null
@@ -75,15 +77,15 @@ class MainActivity : AppCompatActivity(){
snackBarAnchor = binding.snackBarPosition
DownloadHelper.youtubeMusicApi = sharedViewModel.youtubeMusicApi
+ //starting Notification and Downloader Service!
+ startService(this)
+
authenticateSpotify()
requestPermission()
disableDozeMode()
checkIfLatestVersion()
createDirectories()
- Log.i("Connection Status", isOnline().toString())
- //starting Notification and Downloader Service!
- startService(this)
handleIntentFromExternalActivity()
}
diff --git a/app/src/main/java/com/shabinder/spotiflyer/downloadHelper/DownloadHelper.kt b/app/src/main/java/com/shabinder/spotiflyer/downloadHelper/DownloadHelper.kt
index 33c8973f..ed250f45 100755
--- a/app/src/main/java/com/shabinder/spotiflyer/downloadHelper/DownloadHelper.kt
+++ b/app/src/main/java/com/shabinder/spotiflyer/downloadHelper/DownloadHelper.kt
@@ -18,7 +18,6 @@
package com.shabinder.spotiflyer.downloadHelper
import android.annotation.SuppressLint
-import android.os.Environment
import android.os.Handler
import android.util.Log
import android.view.View
@@ -99,7 +98,6 @@ object DownloadHelper {
if(videoId.isNullOrBlank()) {notFound++ ; updateStatusBar()}
else {//Found Youtube Video ID
val outputFile: String =
- Environment.getExternalStorageDirectory().toString() + File.separator +
defaultDir +
removeIllegalChars(type) + File.separator +
(if (subFolder == null) { "" }
diff --git a/app/src/main/java/com/shabinder/spotiflyer/downloadHelper/YTDownloadHelper.kt b/app/src/main/java/com/shabinder/spotiflyer/downloadHelper/YTDownloadHelper.kt
index 2e6637fa..4c075b61 100755
--- a/app/src/main/java/com/shabinder/spotiflyer/downloadHelper/YTDownloadHelper.kt
+++ b/app/src/main/java/com/shabinder/spotiflyer/downloadHelper/YTDownloadHelper.kt
@@ -17,7 +17,6 @@
package com.shabinder.spotiflyer.downloadHelper
-import android.os.Environment
import android.util.Log
import android.widget.Toast
import com.shabinder.spotiflyer.models.DownloadObject
@@ -44,9 +43,7 @@ object YTDownloadHelper {
showNoConnectionAlert()
return
}
- val outputFile: String =
- Environment.getExternalStorageDirectory().toString() + File.separator +
- defaultDir +
+ val outputFile: String = defaultDir +
removeIllegalChars(type) + File.separator +
(if (subFolder == null) { "" }
else { removeIllegalChars(subFolder) + File.separator }
diff --git a/app/src/main/java/com/shabinder/spotiflyer/models/gaana/GaanaPlaylist.kt b/app/src/main/java/com/shabinder/spotiflyer/models/gaana/GaanaPlaylist.kt
index 38dc43ec..b64ca02e 100644
--- a/app/src/main/java/com/shabinder/spotiflyer/models/gaana/GaanaPlaylist.kt
+++ b/app/src/main/java/com/shabinder/spotiflyer/models/gaana/GaanaPlaylist.kt
@@ -18,7 +18,6 @@
package com.shabinder.spotiflyer.models.gaana
data class GaanaPlaylist (
- val tags : String?,
val modified_on : String,
val count : Int,
val created_on : String,
diff --git a/app/src/main/java/com/shabinder/spotiflyer/ui/gaana/GaanaViewModel.kt b/app/src/main/java/com/shabinder/spotiflyer/ui/gaana/GaanaViewModel.kt
index 3e80eb24..c7d5f57c 100644
--- a/app/src/main/java/com/shabinder/spotiflyer/ui/gaana/GaanaViewModel.kt
+++ b/app/src/main/java/com/shabinder/spotiflyer/ui/gaana/GaanaViewModel.kt
@@ -17,7 +17,6 @@
package com.shabinder.spotiflyer.ui.gaana
-import android.os.Environment
import androidx.hilt.lifecycle.ViewModelInject
import com.shabinder.spotiflyer.database.DatabaseDAO
import com.shabinder.spotiflyer.database.DownloadRecord
@@ -165,8 +164,7 @@ class GaanaViewModel @ViewModelInject constructor(
artists = it.artist.map { artist -> artist?.name.toString() },
durationSec = it.duration,
albumArt = File(
- Environment.getExternalStorageDirectory(),
- Provider.defaultDir +".Images/" + (it.artworkLink.substringBeforeLast('/').substringAfterLast('/')) + ".jpeg"),
+ Provider.imageDir + (it.artworkLink.substringBeforeLast('/').substringAfterLast('/')) + ".jpeg"),
albumName = it.album_title,
year = it.release_date,
comment = "Genres:${it.genre?.map { genre -> genre?.name }?.reduceOrNull { acc, s -> acc + s }}",
diff --git a/app/src/main/java/com/shabinder/spotiflyer/ui/spotify/SpotifyViewModel.kt b/app/src/main/java/com/shabinder/spotiflyer/ui/spotify/SpotifyViewModel.kt
index ae0f7222..d63a9c6e 100755
--- a/app/src/main/java/com/shabinder/spotiflyer/ui/spotify/SpotifyViewModel.kt
+++ b/app/src/main/java/com/shabinder/spotiflyer/ui/spotify/SpotifyViewModel.kt
@@ -17,7 +17,6 @@
package com.shabinder.spotiflyer.ui.spotify
-import android.os.Environment
import android.util.Log
import androidx.hilt.lifecycle.ViewModelInject
import com.shabinder.spotiflyer.database.DatabaseDAO
@@ -29,7 +28,7 @@ import com.shabinder.spotiflyer.models.spotify.Image
import com.shabinder.spotiflyer.models.spotify.Source
import com.shabinder.spotiflyer.models.spotify.Track
import com.shabinder.spotiflyer.networking.SpotifyService
-import com.shabinder.spotiflyer.utils.Provider
+import com.shabinder.spotiflyer.utils.Provider.imageDir
import com.shabinder.spotiflyer.utils.TrackListViewModel
import com.shabinder.spotiflyer.utils.finalOutputDir
import kotlinx.coroutines.Dispatchers
@@ -200,8 +199,7 @@ class SpotifyViewModel @ViewModelInject constructor(
artists = it.artists?.map { artist -> artist?.name.toString() } ?: listOf(),
durationSec = (it.duration_ms/1000).toInt(),
albumArt = File(
- Environment.getExternalStorageDirectory(),
- Provider.defaultDir +".Images/" + (it.album?.images?.elementAtOrNull(1)?.url ?: it.album?.images?.firstOrNull()?.url.toString()).substringAfterLast('/') + ".jpeg"),
+ imageDir + (it.album?.images?.elementAtOrNull(1)?.url ?: it.album?.images?.firstOrNull()?.url.toString()).substringAfterLast('/') + ".jpeg"),
albumName = it.album?.name,
year = it.album?.release_date,
comment = "Genres:${it.album?.genres?.joinToString()}",
diff --git a/app/src/main/java/com/shabinder/spotiflyer/ui/youtube/YoutubeFragment.kt b/app/src/main/java/com/shabinder/spotiflyer/ui/youtube/YoutubeFragment.kt
index bc0637c5..fe71231b 100755
--- a/app/src/main/java/com/shabinder/spotiflyer/ui/youtube/YoutubeFragment.kt
+++ b/app/src/main/java/com/shabinder/spotiflyer/ui/youtube/YoutubeFragment.kt
@@ -68,7 +68,7 @@ class YoutubeFragment : TrackListFragment(
if(link.contains(sampleDomain1,true) ){
searchId = link.substringAfterLast("=","error")
}
- if(link.contains(sampleDomain2,true) && !link.contains("playlist",true) ){
+ if(link.contains(sampleDomain2,true) ){
searchId = link.substringAfterLast("/","error")
}
if(searchId != "error") {
diff --git a/app/src/main/java/com/shabinder/spotiflyer/ui/youtube/YoutubeViewModel.kt b/app/src/main/java/com/shabinder/spotiflyer/ui/youtube/YoutubeViewModel.kt
index fa28b80e..b740ef7d 100755
--- a/app/src/main/java/com/shabinder/spotiflyer/ui/youtube/YoutubeViewModel.kt
+++ b/app/src/main/java/com/shabinder/spotiflyer/ui/youtube/YoutubeViewModel.kt
@@ -18,7 +18,6 @@
package com.shabinder.spotiflyer.ui.youtube
import android.annotation.SuppressLint
-import android.os.Environment
import android.util.Log
import androidx.hilt.lifecycle.ViewModelInject
import com.github.kiulian.downloader.YoutubeDownloader
@@ -28,7 +27,7 @@ import com.shabinder.spotiflyer.models.DownloadStatus
import com.shabinder.spotiflyer.models.TrackDetails
import com.shabinder.spotiflyer.models.spotify.Source
import com.shabinder.spotiflyer.utils.*
-import com.shabinder.spotiflyer.utils.Provider.defaultDir
+import com.shabinder.spotiflyer.utils.Provider.imageDir
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@@ -36,7 +35,7 @@ import java.io.File
class YoutubeViewModel @ViewModelInject constructor(
val databaseDAO: DatabaseDAO,
- val ytDownloader: YoutubeDownloader
+ private val ytDownloader: YoutubeDownloader
) : TrackListViewModel(){
/*
* YT Album Art Schema
@@ -67,8 +66,7 @@ class YoutubeViewModel @ViewModelInject constructor(
artists = listOf(it.author().toString()),
durationSec = it.lengthSeconds(),
albumArt = File(
- Environment.getExternalStorageDirectory(),
- defaultDir + ".Images/" + it.videoId() + ".jpeg"
+ imageDir + it.videoId() + ".jpeg"
),
source = Source.YouTube,
albumArtURL = "https://i.ytimg.com/vi/${it.videoId()}/hqdefault.jpg",
@@ -121,10 +119,7 @@ class YoutubeViewModel @ViewModelInject constructor(
title = name,
artists = listOf(detail?.author().toString()),
durationSec = detail?.lengthSeconds()?:0,
- albumArt = File(
- Environment.getExternalStorageDirectory(),
- "$defaultDir.Images/$searchId.jpeg"
- ),
+ albumArt = File(imageDir,"$searchId.jpeg"),
source = Source.YouTube,
albumArtURL = "https://i.ytimg.com/vi/$searchId/hqdefault.jpg"
)
diff --git a/app/src/main/java/com/shabinder/spotiflyer/utils/Provider.kt b/app/src/main/java/com/shabinder/spotiflyer/utils/Provider.kt
index f64378b8..ba84a06e 100755
--- a/app/src/main/java/com/shabinder/spotiflyer/utils/Provider.kt
+++ b/app/src/main/java/com/shabinder/spotiflyer/utils/Provider.kt
@@ -49,13 +49,21 @@ import javax.inject.Singleton
@Module
object Provider {
- /*
- * mainActivity Instance to use whereEver Needed , as Its God Activity.
- * (i.e, Active Through out App' Lifecycle )
- * */
+ // mainActivity Instance to use whereEver Needed , as Its God Activity.
+ // (i.e, Active Through out App' Lifecycle )
val mainActivity: MainActivity = MainActivity.getInstance()
- val defaultDir = Environment.DIRECTORY_MUSIC + File.separator + "SpotiFlyer" + File.separator
+
+ //Default Directory to save Media in their Own Categorized Folders
+ @Suppress("DEPRECATION")// We Do Have Media Access (But Just Media in Media Directory,Not Anything Else)
+ val defaultDir = Environment.getExternalStorageDirectory().toString() + File.separator +
+ Environment.DIRECTORY_MUSIC + File.separator +
+ "SpotiFlyer"+ File.separator
+
+ //Default Cache Directory to save Album Art to use them for writing in Media Later
+ val imageDir:String
+ get() = mainActivity.externalCacheDir?.absolutePath + File.separator +
+ ".Images" + File.separator
@Provides
diff --git a/app/src/main/java/com/shabinder/spotiflyer/utils/TrackListFragment.kt b/app/src/main/java/com/shabinder/spotiflyer/utils/TrackListFragment.kt
index 5e9f5719..62fb3197 100644
--- a/app/src/main/java/com/shabinder/spotiflyer/utils/TrackListFragment.kt
+++ b/app/src/main/java/com/shabinder/spotiflyer/utils/TrackListFragment.kt
@@ -22,6 +22,7 @@ import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Bundle
+import android.os.Handler
import android.util.Log
import android.view.LayoutInflater
import android.view.View
@@ -57,6 +58,7 @@ abstract class TrackListFragment : Frag
showNoConnectionAlert()
mainActivity.navController.popBackStack()
}
+ Handler()
sharedViewModel = ViewModelProvider(this.requireActivity()).get(SharedViewModel::class.java)
}
diff --git a/app/src/main/java/com/shabinder/spotiflyer/utils/Utils.kt b/app/src/main/java/com/shabinder/spotiflyer/utils/Utils.kt
index ca125bd9..9240ef3b 100755
--- a/app/src/main/java/com/shabinder/spotiflyer/utils/Utils.kt
+++ b/app/src/main/java/com/shabinder/spotiflyer/utils/Utils.kt
@@ -22,7 +22,6 @@ import android.content.Intent
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.os.Build
-import android.os.Environment
import android.util.Log
import android.view.View
import android.view.animation.Animation
@@ -42,6 +41,7 @@ import com.shabinder.spotiflyer.R
import com.shabinder.spotiflyer.models.DownloadObject
import com.shabinder.spotiflyer.models.spotify.Source
import com.shabinder.spotiflyer.utils.Provider.defaultDir
+import com.shabinder.spotiflyer.utils.Provider.imageDir
import com.shabinder.spotiflyer.utils.Provider.mainActivity
import com.shabinder.spotiflyer.worker.ForegroundService
import kotlinx.coroutines.CoroutineScope
@@ -63,8 +63,7 @@ fun startService(context:Context?,objects:ArrayList? = null ) {
}
fun finalOutputDir(itemName:String? = null,type:String, subFolder:String?=null,extension:String? = ".mp3"): String{
- return Environment.getExternalStorageDirectory().toString() + File.separator +
- defaultDir + removeIllegalChars(type) + File.separator +
+ return defaultDir + removeIllegalChars(type) + File.separator +
(if(subFolder == null){""}else{ removeIllegalChars(subFolder) + File.separator}
+ itemName?.let { removeIllegalChars(it) + extension})
}
@@ -121,7 +120,7 @@ fun rotateAnim(view: View){
0F, 360F,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f
)
- rotate.duration = 1000
+ rotate.duration = 2000
rotate.repeatCount = Animation.INFINITE
rotate.repeatMode = Animation.INFINITE
rotate.interpolator = LinearInterpolator()
@@ -172,26 +171,22 @@ fun bindImage(imgView: ImageView, imgUrl: String?,source: Source?) {
val file = when(source){
Source.Spotify->{
File(
- Environment.getExternalStorageDirectory(),
- defaultDir+".Images/" + imgUrl.substringAfterLast('/',imgUrl) + ".jpeg"
+ imageDir + imgUrl.substringAfterLast('/',imgUrl) + ".jpeg"
)
}
Source.YouTube->{
//Url Format: https://i.ytimg.com/vi/$searchId/maxresdefault.jpg"
// We Are Naming using "$searchId"
File(
- Environment.getExternalStorageDirectory(),
- defaultDir+".Images/" + imgUrl.substringBeforeLast('/',imgUrl).substringAfterLast('/',imgUrl) + ".jpeg"
+ imageDir + imgUrl.substringBeforeLast('/',imgUrl).substringAfterLast('/',imgUrl) + ".jpeg"
)
}
Source.Gaana -> {
File(
- Environment.getExternalStorageDirectory(),
- Provider.defaultDir +".Images/" + (imgUrl.substringBeforeLast('/').substringAfterLast('/')) + ".jpeg")
+ imageDir + (imgUrl.substringBeforeLast('/').substringAfterLast('/')) + ".jpeg")
}
else -> File(
- Environment.getExternalStorageDirectory(),
- defaultDir+".Images/" + imgUrl.substringAfterLast('/',imgUrl) + ".jpeg"
+ imageDir + imgUrl.substringAfterLast('/',imgUrl) + ".jpeg"
)
}
// the File to save , append increasing numeric counter to prevent files from getting overwritten.
@@ -221,18 +216,17 @@ fun File.copyTo(file: File) {
}
}
fun createDirectory(dir:String){
- val yourAppDir = File(Environment.getExternalStorageDirectory(),
- dir)
+ val yourAppDir = File(dir)
if(!yourAppDir.exists() && !yourAppDir.isDirectory)
{ // create empty directory
if (yourAppDir.mkdirs())
- {Log.i("CreateDir","App dir created")}
+ {Log.i("CreateDir","$dir created")}
else
- {Log.w("CreateDir","Unable to create app dir!")}
+ {Log.w("CreateDir","Unable to create Dir: $dir!")}
}
else
- {Log.i("CreateDir","App dir already exists")}
+ {Log.i("CreateDir","$dir already exists")}
}
/**
* Removing Illegal Chars from File Name
@@ -277,7 +271,7 @@ fun removeIllegalChars(fileName: String): String? {
fun createDirectories() {
createDirectory(defaultDir)
- createDirectory(defaultDir + ".Images/")
+ createDirectory(imageDir)
createDirectory(defaultDir + "Tracks/")
createDirectory(defaultDir + "Albums/")
createDirectory(defaultDir + "Playlists/")
@@ -285,20 +279,4 @@ fun createDirectories() {
}
fun getEmojiByUnicode(unicode: Int): String? {
return String(Character.toChars(unicode))
-}
-
-/*
-internal val nullOnEmptyConverterFactory = object : Converter.Factory() {
- fun converterFactory() = this
- override fun responseBodyConverter(
- type: Type,
- annotations: Array,
- retrofit: Retrofit
- ) = object : Converter {
- val nextResponseBodyConverter =
- retrofit.nextResponseBodyConverter(converterFactory(), type, annotations)
-
- override fun convert(value: ResponseBody) =
- if (value.contentLength() != 0L) nextResponseBodyConverter.convert(value) else null
- }
-}*/
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/shabinder/spotiflyer/worker/ForegroundService.kt b/app/src/main/java/com/shabinder/spotiflyer/worker/ForegroundService.kt
index f6829393..db71ffcf 100755
--- a/app/src/main/java/com/shabinder/spotiflyer/worker/ForegroundService.kt
+++ b/app/src/main/java/com/shabinder/spotiflyer/worker/ForegroundService.kt
@@ -25,7 +25,10 @@ import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.Uri
-import android.os.*
+import android.os.Build
+import android.os.Handler
+import android.os.IBinder
+import android.os.PowerManager
import android.util.Log
import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat
@@ -50,6 +53,7 @@ import com.shabinder.spotiflyer.R
import com.shabinder.spotiflyer.models.DownloadObject
import com.shabinder.spotiflyer.models.TrackDetails
import com.shabinder.spotiflyer.utils.Provider
+import com.shabinder.spotiflyer.utils.Provider.imageDir
import com.shabinder.spotiflyer.utils.copyTo
import com.tonyodev.fetch2.*
import com.tonyodev.fetch2core.DownloadBlock
@@ -59,7 +63,6 @@ import java.io.FileInputStream
import java.io.IOException
import java.util.*
-@Suppress("DEPRECATION")
class ForegroundService : Service(){
private val tag = "Foreground Service"
private val channelId = "ForegroundDownloaderService"
@@ -73,19 +76,13 @@ class ForegroundService : Service(){
private var serviceJob = Job()
private val serviceScope = CoroutineScope(Dispatchers.IO + serviceJob)
private val requestMap = mutableMapOf()
- private var speed :Long = 0
- private var defaultDir = Environment.DIRECTORY_MUSIC + File.separator + "SpotiFlyer" + File.separator
- private val parentDirectory = File(Environment.getExternalStorageDirectory(),
- defaultDir +File.separator
- )
+ private var defaultDir = Provider.defaultDir
private var wakeLock: PowerManager.WakeLock? = null
private var isServiceStarted = false
var notificationLine = 0
val messageList = mutableListOf("","","","")
private var pendingIntent:PendingIntent? = null
-
-
override fun onBind(intent: Intent): IBinder? {
return null
}
@@ -201,7 +198,7 @@ class ForegroundService : Service(){
if(converted == total){
Handler().postDelayed({
Log.i(tag,"Service destroyed.")
- deleteFile(parentDirectory)
+ cleanFiles(File(defaultDir))
releaseWakeLock()
stopForeground(true)
},2000)
@@ -212,7 +209,7 @@ class ForegroundService : Service(){
super.onTaskRemoved(rootIntent)
if(converted == total ){
Log.i(tag,"Service Removed.")
- deleteFile(parentDirectory)
+ cleanFiles(File(defaultDir))
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
stopForeground(true)
} else {
@@ -303,8 +300,6 @@ class ForegroundService : Service(){
requestMap.remove(download.request)
}
}
- speed = 0
-// updateNotification()
}
override fun onDeleted(download: Download) {
@@ -342,7 +337,6 @@ class ForegroundService : Service(){
) {
val track = requestMap[download.request]
Log.i(tag,"${track?.title} ETA: ${etaInMilliSeconds/1000} sec")
- speed = (downloadedBytesPerSecond/1000)
// updateNotification()
}
@@ -361,9 +355,7 @@ class ForegroundService : Service(){
.setAllowedOverRoaming(false)
.setTitle(track.title)
.setDescription("Spotify Downloader Working Up here...")
- .setDestinationInExternalPublicDir(Environment.DIRECTORY_MUSIC, outputDir.removePrefix(
- Environment.getExternalStorageDirectory().toString() + Environment.DIRECTORY_MUSIC + File.separator
- ))
+ .setDestinationUri(File(outputDir).toUri())
.setNotificationVisibility(VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
//Start Download
val downloadID = downloadManager.enqueue(request)
@@ -562,18 +554,18 @@ class ForegroundService : Service(){
}
/**
- * Deleting All Residual Files except Mp3 Files
+ * Cleaning All Residual Files except Mp3 Files
**/
- private fun deleteFile(dir:File) {
- Log.i(tag,"Starting Deletions in ${dir.path} ")
+ private fun cleanFiles(dir:File) {
+ Log.i(tag,"Starting Cleaning in ${dir.path} ")
val fList = dir.listFiles()
fList?.let {
for (file in fList) {
if (file.isDirectory) {
- deleteFile(file)
+ cleanFiles(file)
} else if(file.isFile) {
if(file.path.toString().substringAfterLast(".") != "mp3"){
- Log.i(tag,"deleting ${file.path}")
+ Log.i(tag,"Cleaning ${file.path}")
file.delete()
}
}
@@ -618,25 +610,16 @@ class ForegroundService : Service(){
try {
val file = when(source){
"spotify" ->{
- File(
- Environment.getExternalStorageDirectory(),
- defaultDir +".Images/" + url.substringAfterLast('/') + ".jpeg"
- )
+ File(imageDir, url.substringAfterLast('/') + ".jpeg")
}
"youtube" ->{
- File(
- Environment.getExternalStorageDirectory(),
- defaultDir +".Images/" + url.substringBeforeLast('/',url).substringAfterLast('/',url) + ".jpeg"
- )
+ File(imageDir, url.substringBeforeLast('/',url).substringAfterLast('/',url) + ".jpeg")
}
"gaana" -> {
- File(
- Environment.getExternalStorageDirectory(),
- Provider.defaultDir +".Images/" + (url.substringBeforeLast('/').substringAfterLast('/')) + ".jpeg")
+ File(imageDir, (url.substringBeforeLast('/').substringAfterLast('/')) + ".jpeg")
}
- else -> File(
- Environment.getExternalStorageDirectory(),
- defaultDir +".Images/" + url.substringAfterLast('/') + ".jpeg")
+
+ else -> File(imageDir, url.substringAfterLast('/') + ".jpeg")
}
resource?.copyTo(file)
} catch (e: IOException) {
diff --git a/app/src/main/res/drawable/circular_background.xml b/app/src/main/res/drawable/circular_background.xml
new file mode 100644
index 00000000..64b65daa
--- /dev/null
+++ b/app/src/main/res/drawable/circular_background.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_arrow.xml b/app/src/main/res/drawable/ic_arrow.xml
index 72dd206c..2c26c5e8 100755
--- a/app/src/main/res/drawable/ic_arrow.xml
+++ b/app/src/main/res/drawable/ic_arrow.xml
@@ -15,8 +15,8 @@
~ along with this program. If not, see .
-->
-
+
diff --git a/app/src/main/res/layout/splash_screen.xml b/app/src/main/res/layout/splash_screen.xml
index 3325c9c9..291f984a 100755
--- a/app/src/main/res/layout/splash_screen.xml
+++ b/app/src/main/res/layout/splash_screen.xml
@@ -41,10 +41,9 @@
android:layout_height="wrap_content"
android:layout_marginBottom="48dp"
android:background="@drawable/text_background_accented"
- android:fontFamily="@font/raleway_semibold"
android:foreground="@drawable/rounded_gradient"
android:padding="7dp"
- android:text="Developer: Shabinder Singh"
+ android:text=" Developer: Shabinder Singh "
android:textColor="@color/white"
android:textSize="16sp"
android:visibility="visible"
diff --git a/app/src/main/res/layout/track_list_item.xml b/app/src/main/res/layout/track_list_item.xml
index 649e2fe9..96e3c72c 100755
--- a/app/src/main/res/layout/track_list_item.xml
+++ b/app/src/main/res/layout/track_list_item.xml
@@ -19,14 +19,14 @@
.
*/
-include ':mobile-ffmpeg'
-
include ':app'
rootProject.name = "spotiflyer"