Album Bug Fixes & Dependencies Updated.
0
.github/FUNDING.yml
vendored
Normal file → Executable file
16
.idea/codeStyles/Project.xml
Normal file → Executable file
@ -1,6 +1,22 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<JetCodeStyleSettings>
|
||||
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
|
||||
<value>
|
||||
<package name="java.util" alias="false" withSubpackages="false" />
|
||||
<package name="kotlinx.android.synthetic" alias="false" withSubpackages="true" />
|
||||
<package name="io.ktor" alias="false" withSubpackages="true" />
|
||||
</value>
|
||||
</option>
|
||||
<option name="PACKAGES_IMPORT_LAYOUT">
|
||||
<value>
|
||||
<package name="" alias="false" withSubpackages="true" />
|
||||
<package name="java" alias="false" withSubpackages="true" />
|
||||
<package name="javax" alias="false" withSubpackages="true" />
|
||||
<package name="kotlin" alias="false" withSubpackages="true" />
|
||||
<package name="" alias="true" withSubpackages="true" />
|
||||
</value>
|
||||
</option>
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
</JetCodeStyleSettings>
|
||||
<codeStyleSettings language="XML">
|
||||
|
0
.idea/codeStyles/codeStyleConfig.xml
Normal file → Executable file
6
.idea/dictionaries/shabinder.xml
Normal file → Executable file
@ -2,15 +2,21 @@
|
||||
<dictionary name="shabinder">
|
||||
<words>
|
||||
<w>downloadrecord</w>
|
||||
<w>emoji</w>
|
||||
<w>ffmpeg</w>
|
||||
<w>flyer</w>
|
||||
<w>insta</w>
|
||||
<w>instagram</w>
|
||||
<w>jetbrains</w>
|
||||
<w>kotlinx</w>
|
||||
<w>mainfragment</w>
|
||||
<w>maxresdefault</w>
|
||||
<w>moshi</w>
|
||||
<w>mozilla</w>
|
||||
<w>musicforeveryone</w>
|
||||
<w>musicplaceholder</w>
|
||||
<w>raleway</w>
|
||||
<w>semibold</w>
|
||||
<w>shabinder</w>
|
||||
<w>singh</w>
|
||||
<w>spoti</w>
|
||||
|
1
.idea/gradle.xml
Normal file → Executable file
@ -16,6 +16,7 @@
|
||||
</set>
|
||||
</option>
|
||||
<option name="resolveModulePerSourceSet" value="false" />
|
||||
<option name="useQualifiedModuleNames" value="true" />
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
|
0
.idea/jarRepositories.xml
Normal file → Executable file
2
.idea/misc.xml
Normal file → Executable file
@ -8,7 +8,7 @@
|
||||
<component name="ProjectPlainTextFileTypeManager">
|
||||
<file url="file://$PROJECT_DIR$/app/src/main/java/com/shabinder/spotiflyer/testing/YoutubeInterface.kt.backup" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
|
0
.idea/runConfigurations.xml
Normal file → Executable file
0
.idea/vcs.xml
Normal file → Executable file
0
ScreenShots/DownloadHistory.png
Normal file → Executable file
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 79 KiB |
0
ScreenShots/HomeScreen.png
Normal file → Executable file
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 63 KiB |
0
ScreenShots/LibraryScreen.jpg
Normal file → Executable file
Before Width: | Height: | Size: 73 KiB After Width: | Height: | Size: 73 KiB |
0
ScreenShots/LibraryScreen2.jpg
Normal file → Executable file
Before Width: | Height: | Size: 111 KiB After Width: | Height: | Size: 111 KiB |
0
ScreenShots/Notification.png
Normal file → Executable file
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB |
0
ScreenShots/PlayList.png
Normal file → Executable file
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 75 KiB |
0
app/.gitignore
vendored
Normal file → Executable file
0
app/SpotifyDownload.png
Normal file → Executable file
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 87 KiB |
54
app/build.gradle
Normal file → Executable file
@ -25,7 +25,7 @@ apply plugin: 'dagger.hilt.android.plugin'
|
||||
|
||||
android {
|
||||
compileSdkVersion 29
|
||||
buildToolsVersion "30.0.0"
|
||||
buildToolsVersion "30.0.2"
|
||||
|
||||
buildFeatures{
|
||||
dataBinding = true
|
||||
@ -35,8 +35,8 @@ android {
|
||||
applicationId 'com.shabinder.spotiflyer'
|
||||
minSdkVersion 22
|
||||
targetSdkVersion 29
|
||||
versionCode 5
|
||||
versionName "1.4"
|
||||
versionCode 6
|
||||
versionName "1.5"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
packagingOptions {
|
||||
@ -61,6 +61,9 @@ android {
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
}
|
||||
@ -73,20 +76,20 @@ android {
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include:['*.jar'])
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
implementation 'androidx.core:core-ktx:1.3.1'
|
||||
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.2.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||
implementation 'androidx.webkit:webkit:1.3.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'
|
||||
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.0'
|
||||
implementation 'androidx.navigation:navigation-ui-ktx:2.3.0'
|
||||
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.1'
|
||||
implementation 'androidx.navigation:navigation-ui-ktx:2.3.1'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.1.0'
|
||||
implementation 'com.google.android.material:material:1.2.0'
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.7"
|
||||
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 "androidx.room:room-runtime:2.2.5"
|
||||
kapt "androidx.room:room-compiler:2.2.5"
|
||||
@ -106,30 +109,21 @@ dependencies {
|
||||
transitive = true
|
||||
}
|
||||
|
||||
// Authentication Way Changed!
|
||||
// implementation ('com.google.apis:google-api-services-youtube:v3-rev180-1.22.0'){
|
||||
// exclude module: 'httpclient'
|
||||
// }
|
||||
// //noinspection GradleDependency
|
||||
// implementation ('com.google.oauth-client:google-oauth-client:1.22.0'){
|
||||
// exclude module: 'httpclient'
|
||||
// }
|
||||
// implementation 'com.spotify.android:auth:1.1.0'
|
||||
implementation 'com.squareup.okhttp3:okhttp:4.8.0'
|
||||
implementation 'com.squareup.okhttp3:okhttp:4.9.0'
|
||||
|
||||
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
||||
implementation "com.squareup.moshi:moshi:1.9.3"
|
||||
implementation "com.squareup.moshi:moshi-kotlin:1.9.3"
|
||||
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.mpatric:mp3agic:0.9.1'
|
||||
implementation 'com.shreyaspatil:EasyUpiPayment:2.2'
|
||||
implementation 'com.github.sealedtx:java-youtube-downloader:2.2.3'
|
||||
implementation "androidx.tonyodev.fetch2:xfetch2:3.1.4"
|
||||
implementation 'com.shreyaspatil:EasyUpiPayment:3.0.0'
|
||||
implementation 'com.github.sealedtx:java-youtube-downloader:2.4.2'
|
||||
implementation "androidx.tonyodev.fetch2:xfetch2:3.1.5"
|
||||
implementation 'com.github.javiersantos:AppUpdater:2.7'
|
||||
|
||||
implementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava'
|
||||
testImplementation 'junit:junit:4.13'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||
testImplementation 'junit:junit:4.13.1'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
||||
}
|
0
app/build_passing.svg
Normal file → Executable file
Before Width: | Height: | Size: 724 B After Width: | Height: | Size: 724 B |
0
app/proguard-rules.pro
vendored
Normal file → Executable file
0
app/src/androidTest/java/com/shabinder/spotiflyer/ExampleInstrumentedTest.kt
Normal file → Executable file
16
app/src/main/AndroidManifest.xml
Normal file → Executable file
@ -17,6 +17,7 @@
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.shabinder.spotiflyer">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
@ -29,8 +30,6 @@
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
|
||||
|
||||
<!-- <uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />-->
|
||||
|
||||
<application
|
||||
android:name=".App"
|
||||
android:allowBackup="true"
|
||||
@ -38,10 +37,13 @@
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:forceDarkAllowed="true"
|
||||
android:requestLegacyExternalStorage="true"
|
||||
android:theme="@style/AppTheme">
|
||||
android:theme="@style/AppTheme"
|
||||
tools:targetApi="q">
|
||||
|
||||
<activity android:name="com.shabinder.spotiflyer.MainActivity">
|
||||
<activity android:name="com.shabinder.spotiflyer.MainActivity"
|
||||
android:launchMode="singleTask">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
@ -57,10 +59,7 @@
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<!-- <activity
|
||||
android:name="com.spotify.sdk.android.authentication.LoginActivity"
|
||||
android:theme="@android:style/Theme.Translucent.NoTitleBar" />
|
||||
-->
|
||||
|
||||
<meta-data
|
||||
android:name="preloaded_fonts"
|
||||
android:resource="@array/preloaded_fonts" />
|
||||
@ -68,5 +67,4 @@
|
||||
<service android:name=".worker.ForegroundService"/>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
0
app/src/main/ic_launcher-playstore.png
Normal file → Executable file
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 89 KiB |
0
app/src/main/java/com/shabinder/spotiflyer/App.kt
Normal file → Executable file
56
app/src/main/java/com/shabinder/spotiflyer/MainActivity.kt
Normal file → Executable file
@ -29,6 +29,7 @@ import android.os.PowerManager
|
||||
import android.provider.Settings
|
||||
import android.util.Log
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.github.javiersantos.appupdater.AppUpdater
|
||||
@ -37,7 +38,7 @@ import com.shabinder.spotiflyer.databinding.MainActivityBinding
|
||||
import com.shabinder.spotiflyer.downloadHelper.SpotifyDownloadHelper
|
||||
import com.shabinder.spotiflyer.utils.SpotifyService
|
||||
import com.shabinder.spotiflyer.utils.SpotifyServiceTokenRequest
|
||||
import com.shabinder.spotiflyer.utils.createDirectory
|
||||
import com.shabinder.spotiflyer.utils.createDirectories
|
||||
import com.squareup.moshi.Moshi
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.launch
|
||||
@ -62,20 +63,12 @@ class MainActivity : AppCompatActivity(){
|
||||
@Inject lateinit var spotifyServiceTokenRequest: SpotifyServiceTokenRequest
|
||||
@Inject lateinit var moshi: Moshi
|
||||
|
||||
companion object{
|
||||
private var instance = MainActivity()
|
||||
fun getInstance():MainActivity{
|
||||
return instance
|
||||
}
|
||||
}
|
||||
init {
|
||||
instance = this
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = DataBindingUtil.setContentView(this,R.layout.main_activity)
|
||||
binding = DataBindingUtil.setContentView(this, R.layout.main_activity)
|
||||
sharedViewModel = ViewModelProvider(this).get(SharedViewModel::class.java)
|
||||
//Enabling Dark Mode
|
||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
|
||||
sharedPref = this.getPreferences(Context.MODE_PRIVATE)
|
||||
|
||||
//starting Notification and Downloader Service!
|
||||
@ -93,11 +86,17 @@ class MainActivity : AppCompatActivity(){
|
||||
createDirectories()
|
||||
isConnected = sharedViewModel.isOnline(this)
|
||||
sharedViewModel.isConnected.value = isConnected
|
||||
Log.i("Connection Status",isConnected.toString())
|
||||
Log.i("Connection Status", isConnected.toString())
|
||||
|
||||
handleIntentFromExternalActivity()
|
||||
}
|
||||
|
||||
override fun onNewIntent(intent: Intent?) {
|
||||
super.onNewIntent(intent)
|
||||
Log.i("NEW INTENT", "Received")
|
||||
handleIntentFromExternalActivity(intent)
|
||||
}
|
||||
|
||||
@SuppressLint("BatteryLife")
|
||||
fun disableDozeMode() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
@ -133,7 +132,7 @@ class MainActivity : AppCompatActivity(){
|
||||
/**
|
||||
* Adding my own new Spotify Web Api Requests!
|
||||
* */
|
||||
private fun implementSpotifyService(token:String) {
|
||||
private fun implementSpotifyService(token: String) {
|
||||
val httpClient: OkHttpClient.Builder = OkHttpClient.Builder()
|
||||
httpClient.addInterceptor(object : Interceptor {
|
||||
|
||||
@ -175,12 +174,12 @@ class MainActivity : AppCompatActivity(){
|
||||
}
|
||||
|
||||
|
||||
private fun handleIntentFromExternalActivity() {
|
||||
private fun handleIntentFromExternalActivity(intent: Intent? = getIntent()) {
|
||||
if (intent?.action == Intent.ACTION_SEND) {
|
||||
if ("text/plain" == intent.type) {
|
||||
intent.getStringExtra(Intent.EXTRA_TEXT)?.let {
|
||||
Log.i("Intent Received",it)
|
||||
sharedViewModel.intentString = it
|
||||
Log.i("Intent Received", it)
|
||||
sharedViewModel.intentString.value = it
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -195,8 +194,8 @@ class MainActivity : AppCompatActivity(){
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(savedInstanceState:Bundle) {
|
||||
savedInstanceState.putString("token",token)
|
||||
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
||||
savedInstanceState.putString("token", token)
|
||||
super.onSaveInstanceState(savedInstanceState)
|
||||
}
|
||||
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
|
||||
@ -208,15 +207,6 @@ class MainActivity : AppCompatActivity(){
|
||||
}
|
||||
}
|
||||
|
||||
private fun createDirectories() {
|
||||
createDirectory(SpotifyDownloadHelper.defaultDir)
|
||||
createDirectory(SpotifyDownloadHelper.defaultDir+".Images/")
|
||||
createDirectory(SpotifyDownloadHelper.defaultDir+"Tracks/")
|
||||
createDirectory(SpotifyDownloadHelper.defaultDir+"Albums/")
|
||||
createDirectory(SpotifyDownloadHelper.defaultDir+"Playlists/")
|
||||
createDirectory(SpotifyDownloadHelper.defaultDir+"YT_Downloads/")
|
||||
}
|
||||
|
||||
private fun checkIfLatestVersion() {
|
||||
val appUpdater = AppUpdater(this)
|
||||
.showAppUpdated(false)//true:Show App is Update Dialog
|
||||
@ -234,4 +224,14 @@ class MainActivity : AppCompatActivity(){
|
||||
}
|
||||
appUpdater.start()
|
||||
}
|
||||
|
||||
companion object{
|
||||
private var instance = MainActivity()
|
||||
fun getInstance():MainActivity{
|
||||
return instance
|
||||
}
|
||||
}
|
||||
init {
|
||||
instance = this
|
||||
}
|
||||
}
|
2
app/src/main/java/com/shabinder/spotiflyer/SharedViewModel.kt
Normal file → Executable file
@ -31,7 +31,7 @@ import kotlinx.coroutines.Job
|
||||
import java.io.File
|
||||
|
||||
class SharedViewModel : ViewModel() {
|
||||
var intentString = ""
|
||||
var intentString = MutableLiveData<String>().apply { value = "" }
|
||||
var spotifyService = MutableLiveData<SpotifyService>()
|
||||
var accessToken = MutableLiveData<String>().apply { value = "" }
|
||||
var isConnected = MutableLiveData<Boolean>().apply { value = false }
|
||||
|
0
app/src/main/java/com/shabinder/spotiflyer/database/DatabaseDAO.kt
Normal file → Executable file
0
app/src/main/java/com/shabinder/spotiflyer/database/DownloadRecord.kt
Normal file → Executable file
0
app/src/main/java/com/shabinder/spotiflyer/database/DownloadRecordDatabase.kt
Normal file → Executable file
70
app/src/main/java/com/shabinder/spotiflyer/downloadHelper/SpotifyDownloadHelper.kt
Normal file → Executable file
@ -27,7 +27,6 @@ import android.util.Log
|
||||
import android.view.View
|
||||
import android.view.animation.AlphaAnimation
|
||||
import android.view.animation.Animation
|
||||
import android.webkit.ValueCallback
|
||||
import android.webkit.WebView
|
||||
import android.webkit.WebViewClient
|
||||
import android.widget.TextView
|
||||
@ -38,6 +37,7 @@ import com.github.kiulian.downloader.model.quality.AudioQuality
|
||||
import com.shabinder.spotiflyer.models.DownloadObject
|
||||
import com.shabinder.spotiflyer.models.Track
|
||||
import com.shabinder.spotiflyer.ui.spotify.SpotifyViewModel
|
||||
import com.shabinder.spotiflyer.utils.getEmojiByUnicode
|
||||
import com.shabinder.spotiflyer.worker.ForegroundService
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
@ -53,6 +53,7 @@ object SpotifyDownloadHelper {
|
||||
private var isBrowserLoading = false
|
||||
private var total = 0
|
||||
private var Processed = 0
|
||||
private var notFound = 0
|
||||
private var listProcessed:Boolean = false
|
||||
var youtubeList = mutableListOf<YoutubeRequest>()
|
||||
|
||||
@ -107,36 +108,40 @@ object SpotifyDownloadHelper {
|
||||
super.onPageFinished(view, url)
|
||||
view?.evaluateJavascript(
|
||||
"document.getElementsByClassName(\"yt-simple-endpoint style-scope ytd-video-renderer\")[0].href"
|
||||
,object :ValueCallback<String>{
|
||||
override fun onReceiveValue(value: String?) {
|
||||
Log.i("YT-id",value.toString().replace("\"",""))
|
||||
val id = value!!.substringAfterLast("=", "error").replace("\"","")
|
||||
Log.i("YT-id",id)
|
||||
if(id !="error"){//Link extracting error
|
||||
) { value ->
|
||||
Log.i("YT-id Link", value.toString().replace("\"", ""))
|
||||
val id = value!!.substringAfterLast("=", "error").replace("\"", "")
|
||||
Log.i("YT-ID", id)
|
||||
if (id != "error") {//Link extracting error
|
||||
Processed++
|
||||
downloadFile(subFolder, type, track, ytDownloader, id)
|
||||
}else notFound++
|
||||
updateStatusBar()
|
||||
downloadFile(subFolder, type, track,ytDownloader,id)
|
||||
}
|
||||
if(youtubeList.isNotEmpty()){
|
||||
if (youtubeList.isNotEmpty()) {
|
||||
val request = youtubeList[0]
|
||||
spotifyViewModel!!.uiScope.launch {
|
||||
getYTLink(request.type,request.subFolder,request.ytDownloader,request.searchQuery,request.track)
|
||||
getYTLink(
|
||||
request.type,
|
||||
request.subFolder,
|
||||
request.ytDownloader,
|
||||
request.searchQuery,
|
||||
request.track
|
||||
)
|
||||
}
|
||||
youtubeList.remove(request)
|
||||
if(youtubeList.size == 0){//list processing completed , webView is free again!
|
||||
if (youtubeList.size == 0) {//list processing completed , webView is free again!
|
||||
isBrowserLoading = false
|
||||
listProcessed = true
|
||||
}
|
||||
}else{//YT List Empty....Maybe it was one Single Download
|
||||
} else {//YT List Empty....Maybe it was one Single Download
|
||||
Handler().postDelayed({//Delay of 1.5 sec
|
||||
if(youtubeList.isEmpty()){//Lets Make It sure , There are No more Downloads In Queue.....
|
||||
if (youtubeList.isEmpty()) {//Lets Make It sure , There are No more Downloads In Queue.....
|
||||
isBrowserLoading = false
|
||||
listProcessed = true
|
||||
}
|
||||
},1500)
|
||||
}, 1500)
|
||||
}
|
||||
}
|
||||
} )
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -144,43 +149,52 @@ object SpotifyDownloadHelper {
|
||||
|
||||
private fun updateStatusBar() {
|
||||
statusBar!!.visibility = View.VISIBLE
|
||||
statusBar?.text = "Total: $total Processed: $Processed"
|
||||
statusBar?.text = "Total: $total ${getEmojiByUnicode(0x2705)}: $Processed ${getEmojiByUnicode(0x274C)}: $notFound"
|
||||
}
|
||||
|
||||
|
||||
fun downloadFile(subFolder: String?, type: String, track:Track, ytDownloader: YoutubeDownloader?, id: String) {
|
||||
spotifyViewModel!!.uiScope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
try {
|
||||
val video = ytDownloader?.getVideo(id)
|
||||
val detail = video?.details()
|
||||
val format:Format? =try {
|
||||
val format: Format? = try {
|
||||
video?.findAudioWithQuality(AudioQuality.high)?.get(0) as Format
|
||||
}catch (e:java.lang.IndexOutOfBoundsException){
|
||||
} catch (e: java.lang.IndexOutOfBoundsException) {
|
||||
try {
|
||||
video?.findAudioWithQuality(AudioQuality.medium)?.get(0) as Format
|
||||
}catch (e:java.lang.IndexOutOfBoundsException){
|
||||
try{
|
||||
} catch (e: java.lang.IndexOutOfBoundsException) {
|
||||
try {
|
||||
video?.findAudioWithQuality(AudioQuality.low)?.get(0) as Format
|
||||
}catch (e:java.lang.IndexOutOfBoundsException){
|
||||
Log.i("YTDownloader",e.toString())
|
||||
} catch (e: java.lang.IndexOutOfBoundsException) {
|
||||
Log.i("YTDownloader", e.toString())
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
format?.let {
|
||||
val url:String = format.url()
|
||||
// Log.i("DHelper Link Found", url)
|
||||
val outputFile:String = Environment.getExternalStorageDirectory().toString() + File.separator +
|
||||
defaultDir + removeIllegalChars(type) + File.separator + (if(subFolder == null){""}else{ removeIllegalChars(subFolder) + File.separator} + removeIllegalChars(track.name!!)+".m4a")
|
||||
val url: String = format.url()
|
||||
Log.i("DHelper Link Found", url)
|
||||
val outputFile: String =
|
||||
Environment.getExternalStorageDirectory().toString() + File.separator +
|
||||
defaultDir + removeIllegalChars(type) + File.separator + (if (subFolder == null) {
|
||||
""
|
||||
} else {
|
||||
removeIllegalChars(subFolder) + File.separator
|
||||
} + removeIllegalChars(track.name!!) + ".m4a")
|
||||
|
||||
val downloadObject = DownloadObject(
|
||||
track = track,
|
||||
url = url,
|
||||
outputDir = outputFile
|
||||
)
|
||||
Log.i("DH",outputFile)
|
||||
Log.i("DH", outputFile)
|
||||
startService(context!!, downloadObject)
|
||||
}
|
||||
}catch (e: com.github.kiulian.downloader.YoutubeException){
|
||||
Log.i("DH", "Error- Maybe Network")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
0
app/src/main/java/com/shabinder/spotiflyer/downloadHelper/YTDownloadHelper.kt
Normal file → Executable file
0
app/src/main/java/com/shabinder/spotiflyer/models/Album.kt
Normal file → Executable file
0
app/src/main/java/com/shabinder/spotiflyer/models/Artist.kt
Normal file → Executable file
0
app/src/main/java/com/shabinder/spotiflyer/models/Copyright.kt
Normal file → Executable file
0
app/src/main/java/com/shabinder/spotiflyer/models/DownloadObject.kt
Normal file → Executable file
0
app/src/main/java/com/shabinder/spotiflyer/models/Episodes.kt
Normal file → Executable file
0
app/src/main/java/com/shabinder/spotiflyer/models/Followers.kt
Normal file → Executable file
0
app/src/main/java/com/shabinder/spotiflyer/models/Image.kt
Normal file → Executable file
0
app/src/main/java/com/shabinder/spotiflyer/models/LinkedTrack.kt
Normal file → Executable file
0
app/src/main/java/com/shabinder/spotiflyer/models/PagingObjectPlaylistTrack.kt
Normal file → Executable file
0
app/src/main/java/com/shabinder/spotiflyer/models/PagingObjectTrack.kt
Normal file → Executable file
0
app/src/main/java/com/shabinder/spotiflyer/models/Playlist.kt
Normal file → Executable file
0
app/src/main/java/com/shabinder/spotiflyer/models/PlaylistTrack.kt
Normal file → Executable file
0
app/src/main/java/com/shabinder/spotiflyer/models/Token.kt
Normal file → Executable file
0
app/src/main/java/com/shabinder/spotiflyer/models/Track.kt
Normal file → Executable file
0
app/src/main/java/com/shabinder/spotiflyer/models/UserPrivate.kt
Normal file → Executable file
0
app/src/main/java/com/shabinder/spotiflyer/models/UserPublic.kt
Normal file → Executable file
0
app/src/main/java/com/shabinder/spotiflyer/models/YTTrack.kt
Normal file → Executable file
0
app/src/main/java/com/shabinder/spotiflyer/recyclerView/DownloadRecordAdapter.kt
Normal file → Executable file
1
app/src/main/java/com/shabinder/spotiflyer/recyclerView/SpotifyTrackListAdapter.kt
Normal file → Executable file
@ -54,6 +54,7 @@ class SpotifyTrackListAdapter: ListAdapter<Track,SpotifyTrackListAdapter.ViewHol
|
||||
if(itemCount ==1 || isAlbum){
|
||||
holder.binding.imageUrl.visibility = View.GONE}else{
|
||||
spotifyViewModel!!.uiScope.launch {
|
||||
//Placeholder Set
|
||||
bindImage(holder.binding.imageUrl, item.album!!.images?.get(0)?.url)
|
||||
}
|
||||
}
|
||||
|
0
app/src/main/java/com/shabinder/spotiflyer/recyclerView/YoutubeTrackListAdapter.kt
Normal file → Executable file
0
app/src/main/java/com/shabinder/spotiflyer/samples/response examples.txt
Normal file → Executable file
0
app/src/main/java/com/shabinder/spotiflyer/splash/SplashScreen.kt
Normal file → Executable file
0
app/src/main/java/com/shabinder/spotiflyer/ui/downloadrecord/DownloadRecordFragment.kt
Normal file → Executable file
0
app/src/main/java/com/shabinder/spotiflyer/ui/downloadrecord/DownloadRecordViewModel.kt
Normal file → Executable file
17
app/src/main/java/com/shabinder/spotiflyer/ui/mainfragment/MainFragment.kt
Normal file → Executable file
@ -28,13 +28,12 @@ import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.shabinder.spotiflyer.R
|
||||
import com.shabinder.spotiflyer.SharedViewModel
|
||||
import com.shabinder.spotiflyer.databinding.MainFragmentBinding
|
||||
import com.shreyaspatil.EasyUpiPayment.EasyUpiPayment
|
||||
import com.shreyaspatil.easyupipayment.EasyUpiPayment
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import javax.inject.Inject
|
||||
|
||||
@ -92,7 +91,17 @@ class MainFragment : Fragment() {
|
||||
* Handle Intent If there is any!
|
||||
**/
|
||||
private fun handleIntent() {
|
||||
sharedViewModel.accessToken.observe(viewLifecycleOwner, Observer {
|
||||
sharedViewModel.intentString.observe(viewLifecycleOwner,{
|
||||
//Waiting for Authentication to Finish with Spotify()Access Token Observe
|
||||
if(sharedViewModel.accessToken.value != ""){
|
||||
if(it != ""){
|
||||
binding.linkSearch.setText(sharedViewModel.intentString.value)
|
||||
binding.btnSearch.performClick()
|
||||
sharedViewModel.intentString.value = ""
|
||||
}
|
||||
}
|
||||
})/*
|
||||
sharedViewModel.accessToken.observe(viewLifecycleOwner, {
|
||||
//Waiting for Authentication to Finish with Spotify()Access Token Observe
|
||||
if (it != ""){
|
||||
if(sharedViewModel.intentString != ""){
|
||||
@ -101,7 +110,7 @@ class MainFragment : Fragment() {
|
||||
sharedViewModel.intentString = ""
|
||||
}
|
||||
}
|
||||
})
|
||||
})*/
|
||||
}
|
||||
|
||||
/**
|
||||
|
0
app/src/main/java/com/shabinder/spotiflyer/ui/mainfragment/MainViewModel.kt
Normal file → Executable file
24
app/src/main/java/com/shabinder/spotiflyer/ui/spotify/SpotifyFragment.kt
Normal file → Executable file
@ -36,6 +36,7 @@ import androidx.databinding.DataBindingUtil
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.recyclerview.widget.SimpleItemAnimator
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.DataSource
|
||||
import com.bumptech.glide.load.engine.GlideException
|
||||
@ -96,7 +97,7 @@ class SpotifyFragment : Fragment() {
|
||||
if(sharedViewModel.spotifyService.value == null){//Authentication pending!!
|
||||
(activity as MainActivity).authenticateSpotify()
|
||||
}
|
||||
if(!isNotOnline()){//Device Offline
|
||||
if(!isOnline()){//Device Offline
|
||||
sharedViewModel.showAlertDialog(resources,requireContext())
|
||||
}else if (type == "Error" || link == "Error") {//Incorrect Link
|
||||
showToast("Please Check Your Link!")
|
||||
@ -179,14 +180,14 @@ class SpotifyFragment : Fragment() {
|
||||
/**
|
||||
* CoverUrl Binding Observer!
|
||||
**/
|
||||
spotifyViewModel.coverUrl.observe(viewLifecycleOwner, Observer {
|
||||
spotifyViewModel.coverUrl.observe(viewLifecycleOwner, {
|
||||
if(it!="Loading") bindImage(binding.spotifyCoverImage,it)
|
||||
})
|
||||
|
||||
/**
|
||||
* TrackList Binding Observer!
|
||||
**/
|
||||
spotifyViewModel.trackList.observe(viewLifecycleOwner, Observer {
|
||||
spotifyViewModel.trackList.observe(viewLifecycleOwner, {
|
||||
if (it.isNotEmpty()){
|
||||
Log.i("SpotifyFragment","TrackList Updated")
|
||||
adapterConfig(it)
|
||||
@ -197,9 +198,17 @@ class SpotifyFragment : Fragment() {
|
||||
/**
|
||||
* Title Binding Observer!
|
||||
**/
|
||||
spotifyViewModel.title.observe(viewLifecycleOwner, Observer {
|
||||
spotifyViewModel.title.observe(viewLifecycleOwner, {
|
||||
binding.titleViewSpotify.text = it
|
||||
})
|
||||
|
||||
sharedViewModel.intentString.observe(viewLifecycleOwner,{
|
||||
//Waiting for Authentication to Finish with Spotify()Access Token Observe
|
||||
if(it != "" && it!=SpotifyFragmentArgs.fromBundle(requireArguments()).link){
|
||||
//New Intent Received , Time TO RELOAD
|
||||
(activity as MainActivity).onBackPressed()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun checkIfAllDownloaded() {
|
||||
@ -230,6 +239,7 @@ class SpotifyFragment : Fragment() {
|
||||
SpotifyDownloadHelper.spotifyViewModel = spotifyViewModel
|
||||
SpotifyDownloadHelper.statusBar = binding.StatusBarSpotify
|
||||
binding.trackListSpotify.adapter = adapterSpotify
|
||||
(binding.trackListSpotify.itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false
|
||||
}
|
||||
|
||||
/**
|
||||
@ -237,7 +247,7 @@ class SpotifyFragment : Fragment() {
|
||||
**/
|
||||
private fun loadAllImages(trackList: List<Track>) {
|
||||
trackList.forEach {
|
||||
val imgUrl = it.album!!.images?.get(0)?.url
|
||||
val imgUrl = it.album?.images?.get(0)?.url
|
||||
imgUrl?.let {
|
||||
val imgUri = imgUrl.toUri().buildUpon().scheme("https").build()
|
||||
Glide
|
||||
@ -295,14 +305,14 @@ class SpotifyFragment : Fragment() {
|
||||
/**
|
||||
* Util. Function to create toasts!
|
||||
**/
|
||||
fun showToast(message:String){
|
||||
private fun showToast(message:String){
|
||||
Toast.makeText(context,message,Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
/**
|
||||
* Util. Function To Check Connection Status
|
||||
**/
|
||||
private fun isNotOnline(): Boolean {
|
||||
private fun isOnline(): Boolean {
|
||||
val cm =
|
||||
requireActivity().getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
|
||||
val netInfo = cm.activeNetworkInfo
|
||||
|
21
app/src/main/java/com/shabinder/spotiflyer/ui/spotify/SpotifyViewModel.kt
Normal file → Executable file
@ -24,6 +24,7 @@ import androidx.lifecycle.ViewModel
|
||||
import com.shabinder.spotiflyer.database.DatabaseDAO
|
||||
import com.shabinder.spotiflyer.database.DownloadRecord
|
||||
import com.shabinder.spotiflyer.models.Album
|
||||
import com.shabinder.spotiflyer.models.Image
|
||||
import com.shabinder.spotiflyer.models.Playlist
|
||||
import com.shabinder.spotiflyer.models.Track
|
||||
import com.shabinder.spotiflyer.utils.SpotifyService
|
||||
@ -78,23 +79,24 @@ class SpotifyViewModel @ViewModelInject constructor(val databaseDAO: DatabaseDAO
|
||||
uiScope.launch {
|
||||
val albumObject = getAlbumDetails(link)
|
||||
folderType = "Albums"
|
||||
subFolder = albumObject?.name!!
|
||||
subFolder = albumObject?.name.toString()
|
||||
val tempTrackList = mutableListOf<Track>()
|
||||
albumObject.tracks?.items?.forEach {
|
||||
albumObject?.tracks?.items?.forEach {
|
||||
if(File(finalOutputDir(it.name!!,folderType,subFolder)).exists()){//Download Already Present!!
|
||||
it.downloaded = "Downloaded"
|
||||
}
|
||||
it.album = Album(images = listOf(Image(url = albumObject.images?.get(0)?.url)))
|
||||
tempTrackList.add(it)
|
||||
}
|
||||
trackList.value = tempTrackList
|
||||
title.value = albumObject.name
|
||||
coverUrl.value = albumObject.images?.get(0)!!.url!!
|
||||
title.value = albumObject?.name
|
||||
coverUrl.value = albumObject?.images?.get(0)?.url
|
||||
withContext(Dispatchers.IO){
|
||||
databaseDAO.insert(DownloadRecord(
|
||||
type = "Album",
|
||||
name = title.value!!,
|
||||
link = "https://open.spotify.com/$type/$link",
|
||||
coverUrl = coverUrl.value!!,
|
||||
coverUrl = coverUrl.value.toString(),
|
||||
totalFiles = tempTrackList.size,
|
||||
downloaded = File(finalOutputDir(type = folderType,subFolder = subFolder)).listFiles()?.size == tempTrackList.size,
|
||||
directory = finalOutputDir(type = folderType,subFolder = subFolder)
|
||||
@ -107,9 +109,10 @@ class SpotifyViewModel @ViewModelInject constructor(val databaseDAO: DatabaseDAO
|
||||
uiScope.launch {
|
||||
val playlistObject = getPlaylistDetails(link)
|
||||
folderType = "Playlists"
|
||||
subFolder = playlistObject?.name!!
|
||||
subFolder = playlistObject?.name.toString()
|
||||
val tempTrackList = mutableListOf<Track>()
|
||||
playlistObject.tracks?.items?.forEach {
|
||||
Log.i("Tracks Fetched",playlistObject?.tracks?.items?.size.toString())
|
||||
playlistObject?.tracks?.items?.forEach {
|
||||
it.track?.let {
|
||||
it1 -> if(File(finalOutputDir(it1.name!!,folderType,subFolder)).exists()){//Download Already Present!!
|
||||
it1.downloaded = "Downloaded"
|
||||
@ -118,8 +121,8 @@ class SpotifyViewModel @ViewModelInject constructor(val databaseDAO: DatabaseDAO
|
||||
}
|
||||
}
|
||||
trackList.value = tempTrackList
|
||||
title.value = playlistObject.name
|
||||
coverUrl.value = playlistObject.images?.get(0)!!.url!!
|
||||
title.value = playlistObject?.name
|
||||
coverUrl.value = playlistObject?.images?.get(0)!!.url!!
|
||||
withContext(Dispatchers.IO){
|
||||
databaseDAO.insert(DownloadRecord(
|
||||
type = "Playlist",
|
||||
|
0
app/src/main/java/com/shabinder/spotiflyer/ui/youtube/YoutubeFragment.kt
Normal file → Executable file
0
app/src/main/java/com/shabinder/spotiflyer/ui/youtube/YoutubeViewModel.kt
Normal file → Executable file
13
app/src/main/java/com/shabinder/spotiflyer/utils/BindingAdapter.kt
Normal file → Executable file
@ -17,8 +17,6 @@
|
||||
|
||||
package com.shabinder.spotiflyer.utils
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.os.Environment
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
@ -40,7 +38,6 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.IOException
|
||||
|
||||
fun finalOutputDir(itemName:String? = null,type:String, subFolder:String?=null,extension:String? = ".mp3"): String{
|
||||
@ -68,7 +65,7 @@ fun bindImage(imgView: ImageView, imgUrl: String?) {
|
||||
imgUrl?.let {
|
||||
val imgUri = imgUrl.toUri().buildUpon().scheme("https").build()
|
||||
Glide
|
||||
.with(imgView.context)
|
||||
.with(imgView)
|
||||
.asFile()
|
||||
.load(imgUri)
|
||||
.placeholder(R.drawable.ic_song_placeholder)
|
||||
@ -97,12 +94,12 @@ fun bindImage(imgView: ImageView, imgUrl: String?) {
|
||||
Environment.getExternalStorageDirectory(),
|
||||
SpotifyDownloadHelper.defaultDir+".Images/" + imgUrl.substringAfterLast('/',imgUrl) + ".jpeg"
|
||||
) // the File to save , append increasing numeric counter to prevent files from getting overwritten.
|
||||
val options = BitmapFactory.Options()
|
||||
options.inPreferredConfig = Bitmap.Config.ARGB_8888
|
||||
val bitmap = BitmapFactory.decodeStream(FileInputStream(resource), null, options)
|
||||
resource?.copyTo(file)
|
||||
withContext(Dispatchers.Main){
|
||||
imgView.setImageBitmap(bitmap)
|
||||
Glide.with(imgView)
|
||||
.load(file)
|
||||
.placeholder(R.drawable.ic_song_placeholder)
|
||||
.into(imgView)
|
||||
// Log.i("Glide","imageSaved")
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
|
14
app/src/main/java/com/shabinder/spotiflyer/utils/Provider.kt
Normal file → Executable file
@ -23,7 +23,7 @@ import com.shabinder.spotiflyer.App
|
||||
import com.shabinder.spotiflyer.MainActivity
|
||||
import com.shabinder.spotiflyer.database.DatabaseDAO
|
||||
import com.shabinder.spotiflyer.database.DownloadRecordDatabase
|
||||
import com.shreyaspatil.EasyUpiPayment.EasyUpiPayment
|
||||
import com.shreyaspatil.easyupipayment.EasyUpiPayment
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
|
||||
import dagger.Module
|
||||
@ -34,7 +34,6 @@ import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.moshi.MoshiConverterFactory
|
||||
import javax.inject.Singleton
|
||||
@ -53,14 +52,13 @@ object Provider {
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideUpi():EasyUpiPayment {
|
||||
return EasyUpiPayment.Builder()
|
||||
.with(MainActivity.getInstance())
|
||||
return EasyUpiPayment.Builder(MainActivity.getInstance())
|
||||
.setPayeeVpa("technoshab@paytm")
|
||||
.setPayeeName("Shabinder Singh")
|
||||
.setTransactionId("UNIQUE_TRANSACTION_ID")
|
||||
.setTransactionRefId("UNIQUE_TRANSACTION_REF_ID")
|
||||
.setDescription("Thanks for donating")
|
||||
.setAmount("39.00")
|
||||
.setAmount("49.00")
|
||||
.build()
|
||||
}
|
||||
|
||||
@ -82,15 +80,13 @@ object Provider {
|
||||
@Singleton
|
||||
fun getSpotifyTokenInterface():SpotifyServiceTokenRequest{
|
||||
val httpClient2: OkHttpClient.Builder = OkHttpClient.Builder()
|
||||
httpClient2.addInterceptor(object : Interceptor {
|
||||
override fun intercept(chain: Interceptor.Chain): Response {
|
||||
httpClient2.addInterceptor(Interceptor { chain ->
|
||||
val request: Request =
|
||||
chain.request().newBuilder().addHeader(
|
||||
"Authorization",
|
||||
"Basic ${android.util.Base64.encodeToString("${App.clientId}:${App.clientSecret}".toByteArray(),android.util.Base64.NO_WRAP)}"
|
||||
).build()
|
||||
return chain.proceed(request)
|
||||
}
|
||||
chain.proceed(request)
|
||||
})
|
||||
|
||||
val retrofit = Retrofit.Builder()
|
||||
|
0
app/src/main/java/com/shabinder/spotiflyer/utils/SpotifyInterface.kt
Normal file → Executable file
32
app/src/main/java/com/shabinder/spotiflyer/utils/Utils.kt
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package com.shabinder.spotiflyer.utils
|
||||
|
||||
import com.shabinder.spotiflyer.downloadHelper.SpotifyDownloadHelper
|
||||
|
||||
fun createDirectories() {
|
||||
createDirectory(SpotifyDownloadHelper.defaultDir)
|
||||
createDirectory(SpotifyDownloadHelper.defaultDir + ".Images/")
|
||||
createDirectory(SpotifyDownloadHelper.defaultDir + "Tracks/")
|
||||
createDirectory(SpotifyDownloadHelper.defaultDir + "Albums/")
|
||||
createDirectory(SpotifyDownloadHelper.defaultDir + "Playlists/")
|
||||
createDirectory(SpotifyDownloadHelper.defaultDir + "YT_Downloads/")
|
||||
}
|
||||
fun getEmojiByUnicode(unicode: Int): String? {
|
||||
return String(Character.toChars(unicode))
|
||||
}
|
15
app/src/main/java/com/shabinder/spotiflyer/worker/ForegroundService.kt
Normal file → Executable file
@ -42,7 +42,6 @@ import com.shabinder.spotiflyer.models.DownloadObject
|
||||
import com.shabinder.spotiflyer.models.Track
|
||||
import com.tonyodev.fetch2.*
|
||||
import com.tonyodev.fetch2core.DownloadBlock
|
||||
import com.tonyodev.fetch2core.Func
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
@ -123,9 +122,9 @@ class ForegroundService : Service(){
|
||||
val notification = NotificationCompat.Builder(this, channelId)
|
||||
.setSmallIcon(R.drawable.down_arrowbw)
|
||||
.setNotificationSilent()
|
||||
.setSubText("Speed: $speed KB/s")
|
||||
.setSubText("Total: $total Completed:$converted")
|
||||
.setStyle(NotificationCompat.InboxStyle()
|
||||
.setBigContentTitle("Total: $total Completed:$converted")
|
||||
.setBigContentTitle("Speed: $speed KB/s")
|
||||
.addLine(messageList[0])
|
||||
.addLine(messageList[1])
|
||||
.addLine(messageList[2])
|
||||
@ -164,12 +163,12 @@ class ForegroundService : Service(){
|
||||
request.networkType = NetworkType.ALL
|
||||
|
||||
fetch!!.enqueue(request,
|
||||
Func {
|
||||
{
|
||||
obj.track?.let { it1 -> requestMap.put(it, it1) }
|
||||
downloadList.remove(obj)
|
||||
Log.i(tag, "Enqueuing Download")
|
||||
},
|
||||
Func {
|
||||
{
|
||||
Log.i(tag, "Enqueuing Error:${it.throwable.toString()}")}
|
||||
)
|
||||
}
|
||||
@ -337,7 +336,7 @@ class ForegroundService : Service(){
|
||||
requestMap.remove(download.request)
|
||||
}
|
||||
}
|
||||
if(requestMap.keys.toList().isEmpty()) speed = 0
|
||||
speed = 0
|
||||
updateNotification()
|
||||
}
|
||||
|
||||
@ -473,10 +472,10 @@ class ForegroundService : Service(){
|
||||
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
val notification = NotificationCompat.Builder(this, channelId)
|
||||
.setSmallIcon(R.drawable.down_arrowbw)
|
||||
.setSubText("Speed: $speed KB/s")
|
||||
.setSubText("Total: $total Completed:$converted")
|
||||
.setNotificationSilent()
|
||||
.setStyle(NotificationCompat.InboxStyle()
|
||||
.setBigContentTitle("Total: $total Completed:$converted")
|
||||
.setBigContentTitle("Speed: $speed KB/s")
|
||||
.addLine(messageList[0])
|
||||
.addLine(messageList[1])
|
||||
.addLine(messageList[2])
|
||||
|
17
app/src/main/res/drawable-v24/ic_launcher_foreground.xml
Normal file → Executable file
@ -1,3 +1,20 @@
|
||||
<!--
|
||||
~ 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/>.
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
|
17
app/src/main/res/drawable/btn_design.xml
Normal file → Executable file
@ -1,4 +1,21 @@
|
||||
<?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:shape="rectangle">
|
||||
|
0
app/src/main/res/drawable/down_arrowbw.png
Normal file → Executable file
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
0
app/src/main/res/drawable/gradient.xml
Normal file → Executable file
17
app/src/main/res/drawable/ic_arrow.xml
Normal file → Executable file
@ -1,3 +1,20 @@
|
||||
<!--
|
||||
~ 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/>.
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="26dp"
|
||||
android:height="22dp" 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"/>
|
||||
|
0
app/src/main/res/drawable/ic_arrow_share.xml
Normal file → Executable file
0
app/src/main/res/drawable/ic_arrow_slim.xml
Normal file → Executable file
0
app/src/main/res/drawable/ic_github.xml
Normal file → Executable file
0
app/src/main/res/drawable/ic_heart.xml
Normal file → Executable file
0
app/src/main/res/drawable/ic_history.xml
Normal file → Executable file
0
app/src/main/res/drawable/ic_instagram.xml
Normal file → Executable file
17
app/src/main/res/drawable/ic_launcher_background.xml
Normal file → Executable file
@ -1,4 +1,21 @@
|
||||
<?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/>.
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
|
0
app/src/main/res/drawable/ic_linkedin.xml
Normal file → Executable file
0
app/src/main/res/drawable/ic_mug.xml
Normal file → Executable file
17
app/src/main/res/drawable/ic_musicplaceholder.xml
Normal file → Executable file
@ -1,3 +1,20 @@
|
||||
<!--
|
||||
~ 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/>.
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="300dp"
|
||||
android:height="300dp" android:viewportWidth="512" android:viewportHeight="512">
|
||||
<path android:fillColor="#A3FFFFFF" android:pathData="m256,80a48.054,48.054 0,0 1,48 48v32h12a19.991,19.991 0,0 0,3.524 -39.671,63.984 63.984,0 0,0 -127.048,0 19.991,19.991 0,0 0,3.524 39.671h12v-32a48.054,48.054 0,0 1,48 -48z"/>
|
||||
|
0
app/src/main/res/drawable/ic_refresh.xml
Normal file → Executable file
0
app/src/main/res/drawable/ic_refreshgradient.xml
Normal file → Executable file
0
app/src/main/res/drawable/ic_share_open.xml
Normal file → Executable file
17
app/src/main/res/drawable/ic_song_placeholder.xml
Normal file → Executable file
@ -1,3 +1,20 @@
|
||||
<!--
|
||||
~ 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/>.
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="42dp"
|
||||
android:height="42dp" android:viewportWidth="512" android:viewportHeight="512">
|
||||
<path android:fillColor="#A3FFFFFF" android:pathData="m511.739,103.734 l-257,50.947v233.725c-10.733,-7.199 -23.633,-11.406 -37.5,-11.406 -37.22,0 -67.5,30.28 -67.5,67.5s30.28,67.5 67.5,67.5c34.684,0 63.329,-26.299 67.073,-60h0.427v-182.682l197,-39.053v98.141c-10.733,-7.199 -23.633,-11.406 -37.5,-11.406 -37.22,0 -67.5,30.28 -67.5,67.5s30.28,67.5 67.5,67.5c39.927,0 71.547,-34.762 67.073,-75h0.427zM217.239,482c-20.678,0 -37.5,-16.822 -37.5,-37.5s16.822,-37.5 37.5,-37.5 37.5,16.822 37.5,37.5 -16.822,37.5 -37.5,37.5zM444.239,422c-20.678,0 -37.5,-16.822 -37.5,-37.5s16.822,-37.5 37.5,-37.5 37.5,16.822 37.5,37.5 -16.822,37.5 -37.5,37.5zM481.739,199.682 L284.739,238.735v-59.416l197,-39.053z"/>
|
||||
|
0
app/src/main/res/drawable/ic_spotify_logo.xml
Normal file → Executable file
0
app/src/main/res/drawable/ic_tick.xml
Normal file → Executable file
0
app/src/main/res/drawable/ic_youtube.xml
Normal file → Executable file
17
app/src/main/res/drawable/rounded_gradient.xml
Normal file → Executable file
@ -1,4 +1,21 @@
|
||||
<?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" >
|
||||
<gradient
|
||||
android:angle="90"
|
||||
|
0
app/src/main/res/drawable/spotify_download.png
Normal file → Executable file
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 87 KiB |
17
app/src/main/res/drawable/text_background.xml
Normal file → Executable file
@ -1,4 +1,21 @@
|
||||
<?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:shape="rectangle"
|
||||
>
|
||||
|
19
app/src/main/res/drawable/text_background_accented.xml
Normal file → Executable file
@ -1,4 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<?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/>.
|
||||
-->
|
||||
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
|
||||
<item>
|
||||
<!-- create gradient you want to use with the angle you want to use -->
|
||||
|
0
app/src/main/res/drawable/transparent.xml
Normal file → Executable file
0
app/src/main/res/font/amita.xml
Normal file → Executable file
17
app/src/main/res/font/averia_libre.xml
Normal file → Executable file
@ -1,4 +1,21 @@
|
||||
<?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/>.
|
||||
-->
|
||||
|
||||
<font-family xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
app:fontProviderAuthority="com.google.android.gms.fonts"
|
||||
app:fontProviderCerts="@array/com_google_android_gms_fonts_certs"
|
||||
|
17
app/src/main/res/font/capriola.xml
Normal file → Executable file
@ -1,4 +1,21 @@
|
||||
<?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/>.
|
||||
-->
|
||||
|
||||
<font-family xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
app:fontProviderAuthority="com.google.android.gms.fonts"
|
||||
app:fontProviderCerts="@array/com_google_android_gms_fonts_certs"
|
||||
|
17
app/src/main/res/font/raleway.xml
Normal file → Executable file
@ -1,4 +1,21 @@
|
||||
<?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/>.
|
||||
-->
|
||||
|
||||
<font-family xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
app:fontProviderAuthority="com.google.android.gms.fonts"
|
||||
app:fontProviderCerts="@array/com_google_android_gms_fonts_certs"
|
||||
|
17
app/src/main/res/font/raleway_semibold.xml
Normal file → Executable file
@ -1,4 +1,21 @@
|
||||
<?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/>.
|
||||
-->
|
||||
|
||||
<font-family xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
app:fontProviderAuthority="com.google.android.gms.fonts"
|
||||
app:fontProviderCerts="@array/com_google_android_gms_fonts_certs"
|
||||
|