mirror of
https://github.com/Shabinder/SpotiFlyer.git
synced 2024-11-24 18:04:33 +01:00
ffmpeg aar and Build Gradle Files Cleaned.
Targets sdk 30. Respects Scoped Storage.
This commit is contained in:
parent
04b6f13b22
commit
d80821f759
@ -12,11 +12,9 @@
|
|||||||
<set>
|
<set>
|
||||||
<option value="$PROJECT_DIR$" />
|
<option value="$PROJECT_DIR$" />
|
||||||
<option value="$PROJECT_DIR$/app" />
|
<option value="$PROJECT_DIR$/app" />
|
||||||
<option value="$PROJECT_DIR$/mobile-ffmpeg" />
|
|
||||||
</set>
|
</set>
|
||||||
</option>
|
</option>
|
||||||
<option name="resolveModulePerSourceSet" value="false" />
|
<option name="resolveModulePerSourceSet" value="false" />
|
||||||
<option name="useQualifiedModuleNames" value="true" />
|
|
||||||
</GradleProjectSettings>
|
</GradleProjectSettings>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
<component name="ProjectPlainTextFileTypeManager">
|
<component name="ProjectPlainTextFileTypeManager">
|
||||||
<file url="file://$PROJECT_DIR$/app/src/main/java/com/shabinder/spotiflyer/testing/YoutubeInterface.kt.backup" />
|
<file url="file://$PROJECT_DIR$/app/src/main/java/com/shabinder/spotiflyer/testing/YoutubeInterface.kt.backup" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="false" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectType">
|
<component name="ProjectType">
|
||||||
|
@ -15,42 +15,33 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
apply plugin: 'com.android.application'
|
plugins {
|
||||||
apply plugin: 'kotlin-android'
|
id 'com.android.application'
|
||||||
apply plugin: 'kotlin-android-extensions'
|
id 'kotlin-android'
|
||||||
apply plugin: 'kotlin-kapt'
|
id 'kotlin-kapt'
|
||||||
apply plugin: "androidx.navigation.safeargs.kotlin"
|
id 'kotlin-android-extensions'
|
||||||
apply plugin: 'dagger.hilt.android.plugin'
|
id 'androidx.navigation.safeargs.kotlin'
|
||||||
apply plugin: 'kotlinx-serialization'
|
id 'dagger.hilt.android.plugin'
|
||||||
|
id 'kotlinx-serialization'
|
||||||
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 29
|
compileSdkVersion 30
|
||||||
buildToolsVersion "30.0.2"
|
buildToolsVersion "30.0.2"
|
||||||
|
|
||||||
buildFeatures{
|
buildFeatures{
|
||||||
//dataBinding = true
|
|
||||||
viewBinding = true
|
viewBinding = true
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId 'com.shabinder.spotiflyer'
|
applicationId 'com.shabinder.spotiflyer'
|
||||||
minSdkVersion 22
|
minSdkVersion 22
|
||||||
targetSdkVersion 29
|
targetSdkVersion 30
|
||||||
versionCode 8
|
versionCode 8
|
||||||
versionName "1.6"
|
versionName "1.6"
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
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 {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
minifyEnabled false
|
minifyEnabled false
|
||||||
@ -62,26 +53,42 @@ android {
|
|||||||
targetCompatibility JavaVersion.VERSION_1_8
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
sourceCompatibility JavaVersion.VERSION_1_8
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = "1.8"
|
jvmTarget = "1.8"
|
||||||
}
|
}
|
||||||
|
|
||||||
lintOptions {
|
lintOptions {
|
||||||
abortOnError false
|
abortOnError false
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = JavaVersion.VERSION_1_8.toString()
|
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 {
|
dependencies {
|
||||||
implementation fileTree(dir: 'libs', include:['*.jar'])
|
//Android
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.4.10"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.4.10"
|
||||||
implementation 'androidx.core:core-ktx:1.3.2'
|
implementation 'androidx.core:core-ktx:1.3.2'
|
||||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||||
implementation 'androidx.browser:browser:1.2.0'
|
implementation 'androidx.browser:browser:1.2.0'
|
||||||
implementation 'androidx.webkit:webkit:1.3.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.constraintlayout:constraintlayout:2.0.4'
|
||||||
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
|
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
|
||||||
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx: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.navigation:navigation-ui-ktx:2.3.1'
|
||||||
implementation 'androidx.recyclerview:recyclerview:1.1.0'
|
implementation 'androidx.recyclerview:recyclerview:1.1.0'
|
||||||
implementation 'com.google.android.material:material:1.2.1'
|
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-core:1.4.1'
|
||||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.0'
|
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1'
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.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.room:room-runtime:2.2.5"
|
||||||
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0'
|
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0'
|
||||||
kapt "androidx.room:room-compiler:2.2.5"
|
kapt "androidx.room:room-compiler:2.2.5"
|
||||||
implementation "androidx.room:room-ktx:2.2.5"
|
implementation "androidx.room:room-ktx:2.2.5"
|
||||||
|
|
||||||
|
//Hilt: Dependency Injection
|
||||||
implementation "com.google.dagger:hilt-android:$hilt_version"
|
implementation "com.google.dagger:hilt-android:$hilt_version"
|
||||||
kapt "com.google.dagger:hilt-android-compiler:$hilt_version"
|
kapt "com.google.dagger:hilt-android-compiler:$hilt_version"
|
||||||
implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha02'
|
implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha02'
|
||||||
kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha02'
|
kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha02'
|
||||||
|
|
||||||
|
|
||||||
implementation project(path: ':mobile-ffmpeg')
|
//Glide-Image Loading
|
||||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
implementation ("com.github.bumptech.glide:recyclerview-integration:4.11.0") {transitive = true}
|
||||||
implementation ("com.github.bumptech.glide:recyclerview-integration:4.11.0") {
|
kapt ("com.github.bumptech.glide:recyclerview-integration:4.11.0") {transitive = true}
|
||||||
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.okhttp3:okhttp:4.9.0'
|
||||||
|
|
||||||
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
||||||
|
|
||||||
|
//Json
|
||||||
implementation 'com.squareup.moshi:moshi:1.11.0'
|
implementation 'com.squareup.moshi:moshi:1.11.0'
|
||||||
implementation 'com.squareup.moshi:moshi-kotlin: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-moshi:2.9.0"
|
||||||
implementation "com.squareup.retrofit2:converter-scalars:2.9.0"
|
implementation "com.squareup.retrofit2:converter-scalars:2.9.0"
|
||||||
implementation 'com.beust:klaxon:5.4'
|
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.mpatric:mp3agic:0.9.1'
|
||||||
implementation 'com.shreyaspatil:EasyUpiPayment:3.0.0'
|
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 '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'
|
testImplementation 'junit:junit:4.13.1'
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
||||||
|
BIN
app/libs/mobile-ffmpeg.aar
Executable file
BIN
app/libs/mobile-ffmpeg.aar
Executable file
Binary file not shown.
@ -24,8 +24,10 @@
|
|||||||
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
|
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||||
<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.WRITE_EXTERNAL_STORAGE"
|
||||||
|
android:maxSdkVersion="28" />
|
||||||
|
<uses-permission android:name="android.permission.READ_STORAGE_PERMISSION" />
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
|
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
|
||||||
@ -38,9 +40,11 @@
|
|||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:forceDarkAllowed="true"
|
android:forceDarkAllowed="true"
|
||||||
android:requestLegacyExternalStorage="true"
|
|
||||||
android:theme="@style/AppTheme"
|
android:theme="@style/AppTheme"
|
||||||
|
android:requestLegacyExternalStorage="true"
|
||||||
|
tools:ignore="AllowBackup"
|
||||||
tools:targetApi="q">
|
tools:targetApi="q">
|
||||||
|
<!--android:requestLegacyExternalStorage="true" For SDK 28-->
|
||||||
|
|
||||||
<activity android:name="com.shabinder.spotiflyer.MainActivity"
|
<activity android:name="com.shabinder.spotiflyer.MainActivity"
|
||||||
android:launchMode="singleTask">
|
android:launchMode="singleTask">
|
||||||
|
@ -39,7 +39,10 @@ import com.shabinder.spotiflyer.databinding.MainActivityBinding
|
|||||||
import com.shabinder.spotiflyer.downloadHelper.DownloadHelper
|
import com.shabinder.spotiflyer.downloadHelper.DownloadHelper
|
||||||
import com.shabinder.spotiflyer.networking.SpotifyService
|
import com.shabinder.spotiflyer.networking.SpotifyService
|
||||||
import com.shabinder.spotiflyer.networking.SpotifyServiceTokenRequest
|
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 com.squareup.moshi.Moshi
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -53,7 +56,6 @@ import javax.inject.Inject
|
|||||||
/*
|
/*
|
||||||
* This is App's God Activity
|
* This is App's God Activity
|
||||||
* */
|
* */
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class MainActivity : AppCompatActivity(){
|
class MainActivity : AppCompatActivity(){
|
||||||
private var spotifyService : SpotifyService? = null
|
private var spotifyService : SpotifyService? = null
|
||||||
@ -75,15 +77,15 @@ class MainActivity : AppCompatActivity(){
|
|||||||
snackBarAnchor = binding.snackBarPosition
|
snackBarAnchor = binding.snackBarPosition
|
||||||
DownloadHelper.youtubeMusicApi = sharedViewModel.youtubeMusicApi
|
DownloadHelper.youtubeMusicApi = sharedViewModel.youtubeMusicApi
|
||||||
|
|
||||||
|
//starting Notification and Downloader Service!
|
||||||
|
startService(this)
|
||||||
|
|
||||||
authenticateSpotify()
|
authenticateSpotify()
|
||||||
|
|
||||||
requestPermission()
|
requestPermission()
|
||||||
disableDozeMode()
|
disableDozeMode()
|
||||||
checkIfLatestVersion()
|
checkIfLatestVersion()
|
||||||
createDirectories()
|
createDirectories()
|
||||||
Log.i("Connection Status", isOnline().toString())
|
|
||||||
//starting Notification and Downloader Service!
|
|
||||||
startService(this)
|
|
||||||
|
|
||||||
handleIntentFromExternalActivity()
|
handleIntentFromExternalActivity()
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
package com.shabinder.spotiflyer.downloadHelper
|
package com.shabinder.spotiflyer.downloadHelper
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.os.Environment
|
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.View
|
import android.view.View
|
||||||
@ -99,7 +98,6 @@ object DownloadHelper {
|
|||||||
if(videoId.isNullOrBlank()) {notFound++ ; updateStatusBar()}
|
if(videoId.isNullOrBlank()) {notFound++ ; updateStatusBar()}
|
||||||
else {//Found Youtube Video ID
|
else {//Found Youtube Video ID
|
||||||
val outputFile: String =
|
val outputFile: String =
|
||||||
Environment.getExternalStorageDirectory().toString() + File.separator +
|
|
||||||
defaultDir +
|
defaultDir +
|
||||||
removeIllegalChars(type) + File.separator +
|
removeIllegalChars(type) + File.separator +
|
||||||
(if (subFolder == null) { "" }
|
(if (subFolder == null) { "" }
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
|
|
||||||
package com.shabinder.spotiflyer.downloadHelper
|
package com.shabinder.spotiflyer.downloadHelper
|
||||||
|
|
||||||
import android.os.Environment
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import com.shabinder.spotiflyer.models.DownloadObject
|
import com.shabinder.spotiflyer.models.DownloadObject
|
||||||
@ -44,9 +43,7 @@ object YTDownloadHelper {
|
|||||||
showNoConnectionAlert()
|
showNoConnectionAlert()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val outputFile: String =
|
val outputFile: String = defaultDir +
|
||||||
Environment.getExternalStorageDirectory().toString() + File.separator +
|
|
||||||
defaultDir +
|
|
||||||
removeIllegalChars(type) + File.separator +
|
removeIllegalChars(type) + File.separator +
|
||||||
(if (subFolder == null) { "" }
|
(if (subFolder == null) { "" }
|
||||||
else { removeIllegalChars(subFolder) + File.separator }
|
else { removeIllegalChars(subFolder) + File.separator }
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
package com.shabinder.spotiflyer.models.gaana
|
package com.shabinder.spotiflyer.models.gaana
|
||||||
|
|
||||||
data class GaanaPlaylist (
|
data class GaanaPlaylist (
|
||||||
val tags : String?,
|
|
||||||
val modified_on : String,
|
val modified_on : String,
|
||||||
val count : Int,
|
val count : Int,
|
||||||
val created_on : String,
|
val created_on : String,
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
|
|
||||||
package com.shabinder.spotiflyer.ui.gaana
|
package com.shabinder.spotiflyer.ui.gaana
|
||||||
|
|
||||||
import android.os.Environment
|
|
||||||
import androidx.hilt.lifecycle.ViewModelInject
|
import androidx.hilt.lifecycle.ViewModelInject
|
||||||
import com.shabinder.spotiflyer.database.DatabaseDAO
|
import com.shabinder.spotiflyer.database.DatabaseDAO
|
||||||
import com.shabinder.spotiflyer.database.DownloadRecord
|
import com.shabinder.spotiflyer.database.DownloadRecord
|
||||||
@ -165,8 +164,7 @@ class GaanaViewModel @ViewModelInject constructor(
|
|||||||
artists = it.artist.map { artist -> artist?.name.toString() },
|
artists = it.artist.map { artist -> artist?.name.toString() },
|
||||||
durationSec = it.duration,
|
durationSec = it.duration,
|
||||||
albumArt = File(
|
albumArt = File(
|
||||||
Environment.getExternalStorageDirectory(),
|
Provider.imageDir + (it.artworkLink.substringBeforeLast('/').substringAfterLast('/')) + ".jpeg"),
|
||||||
Provider.defaultDir +".Images/" + (it.artworkLink.substringBeforeLast('/').substringAfterLast('/')) + ".jpeg"),
|
|
||||||
albumName = it.album_title,
|
albumName = it.album_title,
|
||||||
year = it.release_date,
|
year = it.release_date,
|
||||||
comment = "Genres:${it.genre?.map { genre -> genre?.name }?.reduceOrNull { acc, s -> acc + s }}",
|
comment = "Genres:${it.genre?.map { genre -> genre?.name }?.reduceOrNull { acc, s -> acc + s }}",
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
|
|
||||||
package com.shabinder.spotiflyer.ui.spotify
|
package com.shabinder.spotiflyer.ui.spotify
|
||||||
|
|
||||||
import android.os.Environment
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.hilt.lifecycle.ViewModelInject
|
import androidx.hilt.lifecycle.ViewModelInject
|
||||||
import com.shabinder.spotiflyer.database.DatabaseDAO
|
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.Source
|
||||||
import com.shabinder.spotiflyer.models.spotify.Track
|
import com.shabinder.spotiflyer.models.spotify.Track
|
||||||
import com.shabinder.spotiflyer.networking.SpotifyService
|
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.TrackListViewModel
|
||||||
import com.shabinder.spotiflyer.utils.finalOutputDir
|
import com.shabinder.spotiflyer.utils.finalOutputDir
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@ -200,8 +199,7 @@ class SpotifyViewModel @ViewModelInject constructor(
|
|||||||
artists = it.artists?.map { artist -> artist?.name.toString() } ?: listOf(),
|
artists = it.artists?.map { artist -> artist?.name.toString() } ?: listOf(),
|
||||||
durationSec = (it.duration_ms/1000).toInt(),
|
durationSec = (it.duration_ms/1000).toInt(),
|
||||||
albumArt = File(
|
albumArt = File(
|
||||||
Environment.getExternalStorageDirectory(),
|
imageDir + (it.album?.images?.elementAtOrNull(1)?.url ?: it.album?.images?.firstOrNull()?.url.toString()).substringAfterLast('/') + ".jpeg"),
|
||||||
Provider.defaultDir +".Images/" + (it.album?.images?.elementAtOrNull(1)?.url ?: it.album?.images?.firstOrNull()?.url.toString()).substringAfterLast('/') + ".jpeg"),
|
|
||||||
albumName = it.album?.name,
|
albumName = it.album?.name,
|
||||||
year = it.album?.release_date,
|
year = it.album?.release_date,
|
||||||
comment = "Genres:${it.album?.genres?.joinToString()}",
|
comment = "Genres:${it.album?.genres?.joinToString()}",
|
||||||
|
@ -68,7 +68,7 @@ class YoutubeFragment : TrackListFragment<YoutubeViewModel,YoutubeFragmentArgs>(
|
|||||||
if(link.contains(sampleDomain1,true) ){
|
if(link.contains(sampleDomain1,true) ){
|
||||||
searchId = link.substringAfterLast("=","error")
|
searchId = link.substringAfterLast("=","error")
|
||||||
}
|
}
|
||||||
if(link.contains(sampleDomain2,true) && !link.contains("playlist",true) ){
|
if(link.contains(sampleDomain2,true) ){
|
||||||
searchId = link.substringAfterLast("/","error")
|
searchId = link.substringAfterLast("/","error")
|
||||||
}
|
}
|
||||||
if(searchId != "error") {
|
if(searchId != "error") {
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
package com.shabinder.spotiflyer.ui.youtube
|
package com.shabinder.spotiflyer.ui.youtube
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.os.Environment
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.hilt.lifecycle.ViewModelInject
|
import androidx.hilt.lifecycle.ViewModelInject
|
||||||
import com.github.kiulian.downloader.YoutubeDownloader
|
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.TrackDetails
|
||||||
import com.shabinder.spotiflyer.models.spotify.Source
|
import com.shabinder.spotiflyer.models.spotify.Source
|
||||||
import com.shabinder.spotiflyer.utils.*
|
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.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
@ -36,7 +35,7 @@ import java.io.File
|
|||||||
|
|
||||||
class YoutubeViewModel @ViewModelInject constructor(
|
class YoutubeViewModel @ViewModelInject constructor(
|
||||||
val databaseDAO: DatabaseDAO,
|
val databaseDAO: DatabaseDAO,
|
||||||
val ytDownloader: YoutubeDownloader
|
private val ytDownloader: YoutubeDownloader
|
||||||
) : TrackListViewModel(){
|
) : TrackListViewModel(){
|
||||||
/*
|
/*
|
||||||
* YT Album Art Schema
|
* YT Album Art Schema
|
||||||
@ -67,8 +66,7 @@ class YoutubeViewModel @ViewModelInject constructor(
|
|||||||
artists = listOf(it.author().toString()),
|
artists = listOf(it.author().toString()),
|
||||||
durationSec = it.lengthSeconds(),
|
durationSec = it.lengthSeconds(),
|
||||||
albumArt = File(
|
albumArt = File(
|
||||||
Environment.getExternalStorageDirectory(),
|
imageDir + it.videoId() + ".jpeg"
|
||||||
defaultDir + ".Images/" + it.videoId() + ".jpeg"
|
|
||||||
),
|
),
|
||||||
source = Source.YouTube,
|
source = Source.YouTube,
|
||||||
albumArtURL = "https://i.ytimg.com/vi/${it.videoId()}/hqdefault.jpg",
|
albumArtURL = "https://i.ytimg.com/vi/${it.videoId()}/hqdefault.jpg",
|
||||||
@ -121,10 +119,7 @@ class YoutubeViewModel @ViewModelInject constructor(
|
|||||||
title = name,
|
title = name,
|
||||||
artists = listOf(detail?.author().toString()),
|
artists = listOf(detail?.author().toString()),
|
||||||
durationSec = detail?.lengthSeconds()?:0,
|
durationSec = detail?.lengthSeconds()?:0,
|
||||||
albumArt = File(
|
albumArt = File(imageDir,"$searchId.jpeg"),
|
||||||
Environment.getExternalStorageDirectory(),
|
|
||||||
"$defaultDir.Images/$searchId.jpeg"
|
|
||||||
),
|
|
||||||
source = Source.YouTube,
|
source = Source.YouTube,
|
||||||
albumArtURL = "https://i.ytimg.com/vi/$searchId/hqdefault.jpg"
|
albumArtURL = "https://i.ytimg.com/vi/$searchId/hqdefault.jpg"
|
||||||
)
|
)
|
||||||
|
@ -49,13 +49,21 @@ import javax.inject.Singleton
|
|||||||
@Module
|
@Module
|
||||||
object Provider {
|
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 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
|
@Provides
|
||||||
|
@ -22,6 +22,7 @@ import android.content.Context
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.IntentFilter
|
import android.content.IntentFilter
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.os.Handler
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
@ -57,6 +58,7 @@ abstract class TrackListFragment<VM : TrackListViewModel , args: NavArgs> : Frag
|
|||||||
showNoConnectionAlert()
|
showNoConnectionAlert()
|
||||||
mainActivity.navController.popBackStack()
|
mainActivity.navController.popBackStack()
|
||||||
}
|
}
|
||||||
|
Handler()
|
||||||
sharedViewModel = ViewModelProvider(this.requireActivity()).get(SharedViewModel::class.java)
|
sharedViewModel = ViewModelProvider(this.requireActivity()).get(SharedViewModel::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,6 @@ import android.content.Intent
|
|||||||
import android.net.ConnectivityManager
|
import android.net.ConnectivityManager
|
||||||
import android.net.NetworkCapabilities
|
import android.net.NetworkCapabilities
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Environment
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.animation.Animation
|
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.DownloadObject
|
||||||
import com.shabinder.spotiflyer.models.spotify.Source
|
import com.shabinder.spotiflyer.models.spotify.Source
|
||||||
import com.shabinder.spotiflyer.utils.Provider.defaultDir
|
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.utils.Provider.mainActivity
|
||||||
import com.shabinder.spotiflyer.worker.ForegroundService
|
import com.shabinder.spotiflyer.worker.ForegroundService
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
@ -63,8 +63,7 @@ fun startService(context:Context?,objects:ArrayList<DownloadObject>? = null ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun finalOutputDir(itemName:String? = null,type:String, subFolder:String?=null,extension:String? = ".mp3"): String{
|
fun finalOutputDir(itemName:String? = null,type:String, subFolder:String?=null,extension:String? = ".mp3"): String{
|
||||||
return Environment.getExternalStorageDirectory().toString() + File.separator +
|
return defaultDir + removeIllegalChars(type) + File.separator +
|
||||||
defaultDir + removeIllegalChars(type) + File.separator +
|
|
||||||
(if(subFolder == null){""}else{ removeIllegalChars(subFolder) + File.separator}
|
(if(subFolder == null){""}else{ removeIllegalChars(subFolder) + File.separator}
|
||||||
+ itemName?.let { removeIllegalChars(it) + extension})
|
+ itemName?.let { removeIllegalChars(it) + extension})
|
||||||
}
|
}
|
||||||
@ -121,7 +120,7 @@ fun rotateAnim(view: View){
|
|||||||
0F, 360F,
|
0F, 360F,
|
||||||
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f
|
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f
|
||||||
)
|
)
|
||||||
rotate.duration = 1000
|
rotate.duration = 2000
|
||||||
rotate.repeatCount = Animation.INFINITE
|
rotate.repeatCount = Animation.INFINITE
|
||||||
rotate.repeatMode = Animation.INFINITE
|
rotate.repeatMode = Animation.INFINITE
|
||||||
rotate.interpolator = LinearInterpolator()
|
rotate.interpolator = LinearInterpolator()
|
||||||
@ -172,26 +171,22 @@ fun bindImage(imgView: ImageView, imgUrl: String?,source: Source?) {
|
|||||||
val file = when(source){
|
val file = when(source){
|
||||||
Source.Spotify->{
|
Source.Spotify->{
|
||||||
File(
|
File(
|
||||||
Environment.getExternalStorageDirectory(),
|
imageDir + imgUrl.substringAfterLast('/',imgUrl) + ".jpeg"
|
||||||
defaultDir+".Images/" + imgUrl.substringAfterLast('/',imgUrl) + ".jpeg"
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Source.YouTube->{
|
Source.YouTube->{
|
||||||
//Url Format: https://i.ytimg.com/vi/$searchId/maxresdefault.jpg"
|
//Url Format: https://i.ytimg.com/vi/$searchId/maxresdefault.jpg"
|
||||||
// We Are Naming using "$searchId"
|
// We Are Naming using "$searchId"
|
||||||
File(
|
File(
|
||||||
Environment.getExternalStorageDirectory(),
|
imageDir + imgUrl.substringBeforeLast('/',imgUrl).substringAfterLast('/',imgUrl) + ".jpeg"
|
||||||
defaultDir+".Images/" + imgUrl.substringBeforeLast('/',imgUrl).substringAfterLast('/',imgUrl) + ".jpeg"
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Source.Gaana -> {
|
Source.Gaana -> {
|
||||||
File(
|
File(
|
||||||
Environment.getExternalStorageDirectory(),
|
imageDir + (imgUrl.substringBeforeLast('/').substringAfterLast('/')) + ".jpeg")
|
||||||
Provider.defaultDir +".Images/" + (imgUrl.substringBeforeLast('/').substringAfterLast('/')) + ".jpeg")
|
|
||||||
}
|
}
|
||||||
else -> File(
|
else -> File(
|
||||||
Environment.getExternalStorageDirectory(),
|
imageDir + imgUrl.substringAfterLast('/',imgUrl) + ".jpeg"
|
||||||
defaultDir+".Images/" + imgUrl.substringAfterLast('/',imgUrl) + ".jpeg"
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
// the File to save , append increasing numeric counter to prevent files from getting overwritten.
|
// 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){
|
fun createDirectory(dir:String){
|
||||||
val yourAppDir = File(Environment.getExternalStorageDirectory(),
|
val yourAppDir = File(dir)
|
||||||
dir)
|
|
||||||
|
|
||||||
if(!yourAppDir.exists() && !yourAppDir.isDirectory)
|
if(!yourAppDir.exists() && !yourAppDir.isDirectory)
|
||||||
{ // create empty directory
|
{ // create empty directory
|
||||||
if (yourAppDir.mkdirs())
|
if (yourAppDir.mkdirs())
|
||||||
{Log.i("CreateDir","App dir created")}
|
{Log.i("CreateDir","$dir created")}
|
||||||
else
|
else
|
||||||
{Log.w("CreateDir","Unable to create app dir!")}
|
{Log.w("CreateDir","Unable to create Dir: $dir!")}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{Log.i("CreateDir","App dir already exists")}
|
{Log.i("CreateDir","$dir already exists")}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Removing Illegal Chars from File Name
|
* Removing Illegal Chars from File Name
|
||||||
@ -277,7 +271,7 @@ fun removeIllegalChars(fileName: String): String? {
|
|||||||
|
|
||||||
fun createDirectories() {
|
fun createDirectories() {
|
||||||
createDirectory(defaultDir)
|
createDirectory(defaultDir)
|
||||||
createDirectory(defaultDir + ".Images/")
|
createDirectory(imageDir)
|
||||||
createDirectory(defaultDir + "Tracks/")
|
createDirectory(defaultDir + "Tracks/")
|
||||||
createDirectory(defaultDir + "Albums/")
|
createDirectory(defaultDir + "Albums/")
|
||||||
createDirectory(defaultDir + "Playlists/")
|
createDirectory(defaultDir + "Playlists/")
|
||||||
@ -285,20 +279,4 @@ fun createDirectories() {
|
|||||||
}
|
}
|
||||||
fun getEmojiByUnicode(unicode: Int): String? {
|
fun getEmojiByUnicode(unicode: Int): String? {
|
||||||
return String(Character.toChars(unicode))
|
return String(Character.toChars(unicode))
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
internal val nullOnEmptyConverterFactory = object : Converter.Factory() {
|
|
||||||
fun converterFactory() = this
|
|
||||||
override fun responseBodyConverter(
|
|
||||||
type: Type,
|
|
||||||
annotations: Array<out Annotation>,
|
|
||||||
retrofit: Retrofit
|
|
||||||
) = object : Converter<ResponseBody, Any?> {
|
|
||||||
val nextResponseBodyConverter =
|
|
||||||
retrofit.nextResponseBodyConverter<Any?>(converterFactory(), type, annotations)
|
|
||||||
|
|
||||||
override fun convert(value: ResponseBody) =
|
|
||||||
if (value.contentLength() != 0L) nextResponseBodyConverter.convert(value) else null
|
|
||||||
}
|
|
||||||
}*/
|
|
@ -25,7 +25,10 @@ import android.content.Context
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.IntentFilter
|
import android.content.IntentFilter
|
||||||
import android.net.Uri
|
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 android.util.Log
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.core.app.NotificationCompat
|
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.DownloadObject
|
||||||
import com.shabinder.spotiflyer.models.TrackDetails
|
import com.shabinder.spotiflyer.models.TrackDetails
|
||||||
import com.shabinder.spotiflyer.utils.Provider
|
import com.shabinder.spotiflyer.utils.Provider
|
||||||
|
import com.shabinder.spotiflyer.utils.Provider.imageDir
|
||||||
import com.shabinder.spotiflyer.utils.copyTo
|
import com.shabinder.spotiflyer.utils.copyTo
|
||||||
import com.tonyodev.fetch2.*
|
import com.tonyodev.fetch2.*
|
||||||
import com.tonyodev.fetch2core.DownloadBlock
|
import com.tonyodev.fetch2core.DownloadBlock
|
||||||
@ -59,7 +63,6 @@ import java.io.FileInputStream
|
|||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
class ForegroundService : Service(){
|
class ForegroundService : Service(){
|
||||||
private val tag = "Foreground Service"
|
private val tag = "Foreground Service"
|
||||||
private val channelId = "ForegroundDownloaderService"
|
private val channelId = "ForegroundDownloaderService"
|
||||||
@ -73,19 +76,13 @@ class ForegroundService : Service(){
|
|||||||
private var serviceJob = Job()
|
private var serviceJob = Job()
|
||||||
private val serviceScope = CoroutineScope(Dispatchers.IO + serviceJob)
|
private val serviceScope = CoroutineScope(Dispatchers.IO + serviceJob)
|
||||||
private val requestMap = mutableMapOf<Request, TrackDetails>()
|
private val requestMap = mutableMapOf<Request, TrackDetails>()
|
||||||
private var speed :Long = 0
|
private var defaultDir = Provider.defaultDir
|
||||||
private var defaultDir = Environment.DIRECTORY_MUSIC + File.separator + "SpotiFlyer" + File.separator
|
|
||||||
private val parentDirectory = File(Environment.getExternalStorageDirectory(),
|
|
||||||
defaultDir +File.separator
|
|
||||||
)
|
|
||||||
private var wakeLock: PowerManager.WakeLock? = null
|
private var wakeLock: PowerManager.WakeLock? = null
|
||||||
private var isServiceStarted = false
|
private var isServiceStarted = false
|
||||||
var notificationLine = 0
|
var notificationLine = 0
|
||||||
val messageList = mutableListOf("","","","")
|
val messageList = mutableListOf("","","","")
|
||||||
private var pendingIntent:PendingIntent? = null
|
private var pendingIntent:PendingIntent? = null
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
override fun onBind(intent: Intent): IBinder? {
|
override fun onBind(intent: Intent): IBinder? {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@ -201,7 +198,7 @@ class ForegroundService : Service(){
|
|||||||
if(converted == total){
|
if(converted == total){
|
||||||
Handler().postDelayed({
|
Handler().postDelayed({
|
||||||
Log.i(tag,"Service destroyed.")
|
Log.i(tag,"Service destroyed.")
|
||||||
deleteFile(parentDirectory)
|
cleanFiles(File(defaultDir))
|
||||||
releaseWakeLock()
|
releaseWakeLock()
|
||||||
stopForeground(true)
|
stopForeground(true)
|
||||||
},2000)
|
},2000)
|
||||||
@ -212,7 +209,7 @@ class ForegroundService : Service(){
|
|||||||
super.onTaskRemoved(rootIntent)
|
super.onTaskRemoved(rootIntent)
|
||||||
if(converted == total ){
|
if(converted == total ){
|
||||||
Log.i(tag,"Service Removed.")
|
Log.i(tag,"Service Removed.")
|
||||||
deleteFile(parentDirectory)
|
cleanFiles(File(defaultDir))
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
stopForeground(true)
|
stopForeground(true)
|
||||||
} else {
|
} else {
|
||||||
@ -303,8 +300,6 @@ class ForegroundService : Service(){
|
|||||||
requestMap.remove(download.request)
|
requestMap.remove(download.request)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
speed = 0
|
|
||||||
// updateNotification()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDeleted(download: Download) {
|
override fun onDeleted(download: Download) {
|
||||||
@ -342,7 +337,6 @@ class ForegroundService : Service(){
|
|||||||
) {
|
) {
|
||||||
val track = requestMap[download.request]
|
val track = requestMap[download.request]
|
||||||
Log.i(tag,"${track?.title} ETA: ${etaInMilliSeconds/1000} sec")
|
Log.i(tag,"${track?.title} ETA: ${etaInMilliSeconds/1000} sec")
|
||||||
speed = (downloadedBytesPerSecond/1000)
|
|
||||||
// updateNotification()
|
// updateNotification()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -361,9 +355,7 @@ class ForegroundService : Service(){
|
|||||||
.setAllowedOverRoaming(false)
|
.setAllowedOverRoaming(false)
|
||||||
.setTitle(track.title)
|
.setTitle(track.title)
|
||||||
.setDescription("Spotify Downloader Working Up here...")
|
.setDescription("Spotify Downloader Working Up here...")
|
||||||
.setDestinationInExternalPublicDir(Environment.DIRECTORY_MUSIC, outputDir.removePrefix(
|
.setDestinationUri(File(outputDir).toUri())
|
||||||
Environment.getExternalStorageDirectory().toString() + Environment.DIRECTORY_MUSIC + File.separator
|
|
||||||
))
|
|
||||||
.setNotificationVisibility(VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
|
.setNotificationVisibility(VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
|
||||||
//Start Download
|
//Start Download
|
||||||
val downloadID = downloadManager.enqueue(request)
|
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) {
|
private fun cleanFiles(dir:File) {
|
||||||
Log.i(tag,"Starting Deletions in ${dir.path} ")
|
Log.i(tag,"Starting Cleaning in ${dir.path} ")
|
||||||
val fList = dir.listFiles()
|
val fList = dir.listFiles()
|
||||||
fList?.let {
|
fList?.let {
|
||||||
for (file in fList) {
|
for (file in fList) {
|
||||||
if (file.isDirectory) {
|
if (file.isDirectory) {
|
||||||
deleteFile(file)
|
cleanFiles(file)
|
||||||
} else if(file.isFile) {
|
} else if(file.isFile) {
|
||||||
if(file.path.toString().substringAfterLast(".") != "mp3"){
|
if(file.path.toString().substringAfterLast(".") != "mp3"){
|
||||||
Log.i(tag,"deleting ${file.path}")
|
Log.i(tag,"Cleaning ${file.path}")
|
||||||
file.delete()
|
file.delete()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -618,25 +610,16 @@ class ForegroundService : Service(){
|
|||||||
try {
|
try {
|
||||||
val file = when(source){
|
val file = when(source){
|
||||||
"spotify" ->{
|
"spotify" ->{
|
||||||
File(
|
File(imageDir, url.substringAfterLast('/') + ".jpeg")
|
||||||
Environment.getExternalStorageDirectory(),
|
|
||||||
defaultDir +".Images/" + url.substringAfterLast('/') + ".jpeg"
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
"youtube" ->{
|
"youtube" ->{
|
||||||
File(
|
File(imageDir, url.substringBeforeLast('/',url).substringAfterLast('/',url) + ".jpeg")
|
||||||
Environment.getExternalStorageDirectory(),
|
|
||||||
defaultDir +".Images/" + url.substringBeforeLast('/',url).substringAfterLast('/',url) + ".jpeg"
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
"gaana" -> {
|
"gaana" -> {
|
||||||
File(
|
File(imageDir, (url.substringBeforeLast('/').substringAfterLast('/')) + ".jpeg")
|
||||||
Environment.getExternalStorageDirectory(),
|
|
||||||
Provider.defaultDir +".Images/" + (url.substringBeforeLast('/').substringAfterLast('/')) + ".jpeg")
|
|
||||||
}
|
}
|
||||||
else -> File(
|
|
||||||
Environment.getExternalStorageDirectory(),
|
else -> File(imageDir, url.substringAfterLast('/') + ".jpeg")
|
||||||
defaultDir +".Images/" + url.substringAfterLast('/') + ".jpeg")
|
|
||||||
}
|
}
|
||||||
resource?.copyTo(file)
|
resource?.copyTo(file)
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
|
28
app/src/main/res/drawable/circular_background.xml
Normal file
28
app/src/main/res/drawable/circular_background.xml
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
~ Copyright (C) 2020 Shabinder Singh
|
||||||
|
~
|
||||||
|
~ This program is free software: you can redistribute it and/or modify
|
||||||
|
~ it under the terms of the GNU General Public License as published by
|
||||||
|
~ the Free Software Foundation, either version 3 of the License, or
|
||||||
|
~ (at your option) any later version.
|
||||||
|
~
|
||||||
|
~ This program is distributed in the hope that it will be useful,
|
||||||
|
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
~ GNU General Public License for more details.
|
||||||
|
~
|
||||||
|
~ You should have received a copy of the GNU General Public License
|
||||||
|
~ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
<shape
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:innerRadiusRatio="2.5"
|
||||||
|
android:shape="ring"
|
||||||
|
android:thickness="4dp"
|
||||||
|
android:useLevel="false">
|
||||||
|
|
||||||
|
<solid android:color="@color/colorPrimary"/>
|
||||||
|
|
||||||
|
</shape>
|
||||||
|
|
||||||
|
|
@ -15,8 +15,8 @@
|
|||||||
~ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
~ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="26dp"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="36dp"
|
||||||
android:height="22dp" android:viewportWidth="512" android:viewportHeight="512">
|
android:height="32dp" android:viewportWidth="512" android:viewportHeight="512">
|
||||||
<path android:fillColor="#516AEC" android:pathData="m296,288 l60,-60c7.73,-7.73 17.86,-11.6 28,-11.6 10.055,0 20.101,3.806 27.806,11.407 15.612,15.402 15.207,41.18 -0.3,56.687l-134.293,134.293c-11.716,11.716 -30.711,11.716 -42.426,0l-134.787,-134.787c-7.73,-7.73 -11.6,-17.86 -11.6,-28 0,-10.055 3.806,-20.101 11.407,-27.806 15.402,-15.612 41.18,-15.207 56.687,0.3l59.506,59.506v-232c0,-22.091 17.909,-40 40,-40 22.091,0 40,17.909 40,40z"/>
|
<path android:fillColor="#516AEC" android:pathData="m296,288 l60,-60c7.73,-7.73 17.86,-11.6 28,-11.6 10.055,0 20.101,3.806 27.806,11.407 15.612,15.402 15.207,41.18 -0.3,56.687l-134.293,134.293c-11.716,11.716 -30.711,11.716 -42.426,0l-134.787,-134.787c-7.73,-7.73 -11.6,-17.86 -11.6,-28 0,-10.055 3.806,-20.101 11.407,-27.806 15.402,-15.612 41.18,-15.207 56.687,0.3l59.506,59.506v-232c0,-22.091 17.909,-40 40,-40 22.091,0 40,17.909 40,40z"/>
|
||||||
<path android:fillColor="#EC7EBA" android:pathData="m411.51,284.49 l-134.3,134.3c-11.71,11.71 -30.71,11.71 -42.42,0l-12.74,-12.74c10.69,4.06 23.23,1.77 31.84,-6.84l134.29,-134.29c12.51,-12.51 15.19,-31.7 7.57,-46.74 5.86,1.81 11.39,5.03 16.06,9.63 15.61,15.4 15.2,41.18 -0.3,56.68z"/>
|
<path android:fillColor="#EC7EBA" android:pathData="m411.51,284.49 l-134.3,134.3c-11.71,11.71 -30.71,11.71 -42.42,0l-12.74,-12.74c10.69,4.06 23.23,1.77 31.84,-6.84l134.29,-134.29c12.51,-12.51 15.19,-31.7 7.57,-46.74 5.86,1.81 11.39,5.03 16.06,9.63 15.61,15.4 15.2,41.18 -0.3,56.68z"/>
|
||||||
<path android:fillColor="#EC7EBA" android:pathData="m251.88,27.72c-3.46,-3.46 -7.55,-6.29 -12.08,-8.3 4.95,-2.2 10.43,-3.42 16.2,-3.42 11.04,0 21.04,4.48 28.28,11.72s11.72,17.24 11.72,28.28v232l-15.329,15.329c-6.3,6.3 -17.071,1.838 -17.071,-7.071v-240.258c0,-11.04 -4.48,-21.04 -11.72,-28.28z"/>
|
<path android:fillColor="#EC7EBA" android:pathData="m251.88,27.72c-3.46,-3.46 -7.55,-6.29 -12.08,-8.3 4.95,-2.2 10.43,-3.42 16.2,-3.42 11.04,0 21.04,4.48 28.28,11.72s11.72,17.24 11.72,28.28v232l-15.329,15.329c-6.3,6.3 -17.071,1.838 -17.071,-7.071v-240.258c0,-11.04 -4.48,-21.04 -11.72,-28.28z"/>
|
||||||
|
@ -41,10 +41,9 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="48dp"
|
android:layout_marginBottom="48dp"
|
||||||
android:background="@drawable/text_background_accented"
|
android:background="@drawable/text_background_accented"
|
||||||
android:fontFamily="@font/raleway_semibold"
|
|
||||||
android:foreground="@drawable/rounded_gradient"
|
android:foreground="@drawable/rounded_gradient"
|
||||||
android:padding="7dp"
|
android:padding="7dp"
|
||||||
android:text="Developer: Shabinder Singh"
|
android:text=" Developer: Shabinder Singh "
|
||||||
android:textColor="@color/white"
|
android:textColor="@color/white"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:visibility="visible"
|
android:visibility="visible"
|
||||||
|
@ -19,14 +19,14 @@
|
|||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="80dp"
|
android:layout_height="70dp"
|
||||||
android:layout_marginBottom="12dp"
|
android:layout_marginBottom="12dp"
|
||||||
android:background="#000000">
|
android:background="#000000">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/imageUrl"
|
android:id="@+id/imageUrl"
|
||||||
android:layout_width="100dp"
|
android:layout_width="90dp"
|
||||||
android:layout_height="80dp"
|
android:layout_height="70dp"
|
||||||
android:contentDescription="Track Image"
|
android:contentDescription="Track Image"
|
||||||
android:scaleType="centerInside"
|
android:scaleType="centerInside"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
@ -41,6 +41,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:layout_marginTop="14dp"
|
android:layout_marginTop="14dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
android:fontFamily="@font/raleway_semibold"
|
android:fontFamily="@font/raleway_semibold"
|
||||||
android:letterSpacing="0.04"
|
android:letterSpacing="0.04"
|
||||||
android:lines="1"
|
android:lines="1"
|
||||||
@ -50,7 +51,7 @@
|
|||||||
android:textColor="#9AB3FF"
|
android:textColor="#9AB3FF"
|
||||||
android:textSize="18sp"
|
android:textSize="18sp"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/btn_download"
|
app:layout_constraintEnd_toStartOf="@+id/btn_download"
|
||||||
app:layout_constraintStart_toStartOf="@+id/artist"
|
app:layout_constraintStart_toEndOf="@+id/imageUrl"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@ -61,7 +62,6 @@
|
|||||||
android:layout_marginStart="12dp"
|
android:layout_marginStart="12dp"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:paddingLeft="9dp"
|
|
||||||
android:text="Alan Walker"
|
android:text="Alan Walker"
|
||||||
android:textSize="12sp"
|
android:textSize="12sp"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
@ -75,8 +75,7 @@
|
|||||||
style="@style/TextAppearance.AppCompat.Body2"
|
style="@style/TextAppearance.AppCompat.Body2"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="3dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:paddingLeft="9dp"
|
|
||||||
android:text="4 minutes, 20 sec"
|
android:text="4 minutes, 20 sec"
|
||||||
android:textSize="12sp"
|
android:textSize="12sp"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/artist"
|
app:layout_constraintBottom_toBottomOf="@+id/artist"
|
||||||
@ -88,8 +87,9 @@
|
|||||||
android:id="@+id/btn_download"
|
android:id="@+id/btn_download"
|
||||||
android:layout_width="60dp"
|
android:layout_width="60dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
|
android:background="@drawable/circular_background"
|
||||||
android:backgroundTint="@color/black"
|
android:backgroundTint="@color/black"
|
||||||
android:scaleType="fitCenter"
|
android:scaleType="centerInside"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
@ -28,11 +28,13 @@ buildscript {
|
|||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:4.1.0'
|
classpath 'com.android.tools.build:gradle:4.2.0-alpha16'
|
||||||
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"
|
||||||
|
//Hilt
|
||||||
classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version"
|
classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version"
|
||||||
|
//Kotlinx-Serialization
|
||||||
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
// in the individual module build.gradle files
|
// in the individual module build.gradle files
|
||||||
@ -45,9 +47,6 @@ allprojects {
|
|||||||
jcenter()
|
jcenter()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
maven { url "https://jitpack.io" }
|
maven { url "https://jitpack.io" }
|
||||||
flatDir {
|
|
||||||
dirs 'libs'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,5 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
include ':mobile-ffmpeg'
|
|
||||||
|
|
||||||
include ':app'
|
include ':app'
|
||||||
rootProject.name = "spotiflyer"
|
rootProject.name = "spotiflyer"
|
||||||
|
Loading…
Reference in New Issue
Block a user