mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-10-14 03:31:06 +02:00
Initial commit: SpotiFLAC Android/iOS app
This commit is contained in:
commit
3fdcf6d5b7
126 files changed
+14079
No files matched your search
@@ -0,0 +1,5 @@
|
||||
package com.example.temp_project
|
||||
|
||||
import io.flutter.embedding.android.FlutterActivity
|
||||
|
||||
class MainActivity : FlutterActivity()
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.zarz.spotiflac
|
||||
|
||||
import android.app.Notification
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.app.Service
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.IBinder
|
||||
import androidx.core.app.NotificationCompat
|
||||
|
||||
class DownloadService : Service() {
|
||||
companion object {
|
||||
const val CHANNEL_ID = "spotiflac_download_channel"
|
||||
const val NOTIFICATION_ID = 1
|
||||
const val ACTION_START = "com.zarz.spotiflac.START_DOWNLOAD"
|
||||
const val ACTION_STOP = "com.zarz.spotiflac.STOP_DOWNLOAD"
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
createNotificationChannel()
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
when (intent?.action) {
|
||||
ACTION_START -> startForegroundService()
|
||||
ACTION_STOP -> stopSelf()
|
||||
}
|
||||
return START_NOT_STICKY
|
||||
}
|
||||
|
||||
override fun onBind(intent: Intent?): IBinder? = null
|
||||
|
||||
private fun createNotificationChannel() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val channel = NotificationChannel(
|
||||
CHANNEL_ID,
|
||||
"Download Progress",
|
||||
NotificationManager.IMPORTANCE_LOW
|
||||
).apply {
|
||||
description = "Shows download progress for SpotiFLAC"
|
||||
setShowBadge(false)
|
||||
}
|
||||
val manager = getSystemService(NotificationManager::class.java)
|
||||
manager.createNotificationChannel(channel)
|
||||
}
|
||||
}
|
||||
|
||||
private fun startForegroundService() {
|
||||
val notification = createNotification("Downloading...", 0)
|
||||
startForeground(NOTIFICATION_ID, notification)
|
||||
}
|
||||
|
||||
fun updateProgress(trackName: String, progress: Int) {
|
||||
val notification = createNotification(trackName, progress)
|
||||
val manager = getSystemService(NotificationManager::class.java)
|
||||
manager.notify(NOTIFICATION_ID, notification)
|
||||
}
|
||||
|
||||
private fun createNotification(title: String, progress: Int): Notification {
|
||||
val intent = Intent(this, MainActivity::class.java)
|
||||
val pendingIntent = PendingIntent.getActivity(
|
||||
this, 0, intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
||||
)
|
||||
|
||||
val stopIntent = Intent(this, DownloadService::class.java).apply {
|
||||
action = ACTION_STOP
|
||||
}
|
||||
val stopPendingIntent = PendingIntent.getService(
|
||||
this, 0, stopIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
||||
)
|
||||
|
||||
return NotificationCompat.Builder(this, CHANNEL_ID)
|
||||
.setContentTitle("SpotiFLAC")
|
||||
.setContentText(title)
|
||||
.setSmallIcon(android.R.drawable.stat_sys_download)
|
||||
.setProgress(100, progress, progress == 0)
|
||||
.setOngoing(true)
|
||||
.setContentIntent(pendingIntent)
|
||||
.addAction(android.R.drawable.ic_menu_close_clear_cancel, "Cancel", stopPendingIntent)
|
||||
.build()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
package com.zarz.spotiflac
|
||||
|
||||
import io.flutter.embedding.android.FlutterActivity
|
||||
import io.flutter.embedding.engine.FlutterEngine
|
||||
import io.flutter.plugin.common.MethodChannel
|
||||
import gobackend.Gobackend
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class MainActivity: FlutterActivity() {
|
||||
private val CHANNEL = "com.zarz.spotiflac/backend"
|
||||
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
|
||||
|
||||
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
|
||||
super.configureFlutterEngine(flutterEngine)
|
||||
|
||||
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
|
||||
scope.launch {
|
||||
try {
|
||||
when (call.method) {
|
||||
"parseSpotifyUrl" -> {
|
||||
val url = call.argument<String>("url") ?: ""
|
||||
val response = withContext(Dispatchers.IO) {
|
||||
Gobackend.parseSpotifyURL(url)
|
||||
}
|
||||
result.success(response)
|
||||
}
|
||||
"getSpotifyMetadata" -> {
|
||||
val url = call.argument<String>("url") ?: ""
|
||||
val response = withContext(Dispatchers.IO) {
|
||||
Gobackend.getSpotifyMetadata(url)
|
||||
}
|
||||
result.success(response)
|
||||
}
|
||||
"searchSpotify" -> {
|
||||
val query = call.argument<String>("query") ?: ""
|
||||
val limit = call.argument<Int>("limit") ?: 10
|
||||
val response = withContext(Dispatchers.IO) {
|
||||
Gobackend.searchSpotify(query, limit.toLong())
|
||||
}
|
||||
result.success(response)
|
||||
}
|
||||
"checkAvailability" -> {
|
||||
val spotifyId = call.argument<String>("spotify_id") ?: ""
|
||||
val isrc = call.argument<String>("isrc") ?: ""
|
||||
val response = withContext(Dispatchers.IO) {
|
||||
Gobackend.checkAvailability(spotifyId, isrc)
|
||||
}
|
||||
result.success(response)
|
||||
}
|
||||
"downloadTrack" -> {
|
||||
val requestJson = call.arguments as String
|
||||
val response = withContext(Dispatchers.IO) {
|
||||
Gobackend.downloadTrack(requestJson)
|
||||
}
|
||||
result.success(response)
|
||||
}
|
||||
"downloadWithFallback" -> {
|
||||
val requestJson = call.arguments as String
|
||||
val response = withContext(Dispatchers.IO) {
|
||||
Gobackend.downloadWithFallback(requestJson)
|
||||
}
|
||||
result.success(response)
|
||||
}
|
||||
"getDownloadProgress" -> {
|
||||
val response = withContext(Dispatchers.IO) {
|
||||
Gobackend.getDownloadProgress()
|
||||
}
|
||||
result.success(response)
|
||||
}
|
||||
"setDownloadDirectory" -> {
|
||||
val path = call.argument<String>("path") ?: ""
|
||||
withContext(Dispatchers.IO) {
|
||||
Gobackend.setDownloadDirectory(path)
|
||||
}
|
||||
result.success(null)
|
||||
}
|
||||
"checkDuplicate" -> {
|
||||
val outputDir = call.argument<String>("output_dir") ?: ""
|
||||
val isrc = call.argument<String>("isrc") ?: ""
|
||||
val response = withContext(Dispatchers.IO) {
|
||||
Gobackend.checkDuplicate(outputDir, isrc)
|
||||
}
|
||||
result.success(response)
|
||||
}
|
||||
"buildFilename" -> {
|
||||
val template = call.argument<String>("template") ?: ""
|
||||
val metadata = call.argument<String>("metadata") ?: "{}"
|
||||
val response = withContext(Dispatchers.IO) {
|
||||
Gobackend.buildFilename(template, metadata)
|
||||
}
|
||||
result.success(response)
|
||||
}
|
||||
"sanitizeFilename" -> {
|
||||
val filename = call.argument<String>("filename") ?: ""
|
||||
val response = withContext(Dispatchers.IO) {
|
||||
Gobackend.sanitizeFilename(filename)
|
||||
}
|
||||
result.success(response)
|
||||
}
|
||||
"fetchLyrics" -> {
|
||||
val spotifyId = call.argument<String>("spotify_id") ?: ""
|
||||
val trackName = call.argument<String>("track_name") ?: ""
|
||||
val artistName = call.argument<String>("artist_name") ?: ""
|
||||
val response = withContext(Dispatchers.IO) {
|
||||
Gobackend.fetchLyrics(spotifyId, trackName, artistName)
|
||||
}
|
||||
result.success(response)
|
||||
}
|
||||
"getLyricsLRC" -> {
|
||||
val spotifyId = call.argument<String>("spotify_id") ?: ""
|
||||
val trackName = call.argument<String>("track_name") ?: ""
|
||||
val artistName = call.argument<String>("artist_name") ?: ""
|
||||
val response = withContext(Dispatchers.IO) {
|
||||
Gobackend.getLyricsLRC(spotifyId, trackName, artistName)
|
||||
}
|
||||
result.success(response)
|
||||
}
|
||||
"embedLyricsToFile" -> {
|
||||
val filePath = call.argument<String>("file_path") ?: ""
|
||||
val lyrics = call.argument<String>("lyrics") ?: ""
|
||||
val response = withContext(Dispatchers.IO) {
|
||||
Gobackend.embedLyricsToFile(filePath, lyrics)
|
||||
}
|
||||
result.success(response)
|
||||
}
|
||||
else -> result.notImplemented()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
result.error("ERROR", e.message, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user