@ -1,28 +1,18 @@
package com.deniscerri.ytdl.core.packages
import android.annotation.SuppressLint
import android.app.DownloadManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager
import android.os.Build
import android.os.Environment
import android.util.Log
import androidx.activity.result.ActivityResultLauncher
import androidx.core.content.edit
import androidx.core.net.toUri
import androidx.documentfile.provider.DocumentFile
import androidx.preference.PreferenceManager
import com.deniscerri.ytdl.R
import com.deniscerri.ytdl.core.RuntimeManager
import com.deniscerri.ytdl.core.ZipUtils
import com.deniscerri.ytdl.database.models.GithubReleaseAsset
import com.deniscerri.ytdl.util.FileUtil
import com.google.gson.annotations.SerializedName
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.withContext
import kotlinx.serialization.SerialName
@ -197,86 +187,44 @@ abstract class PackageBase {
)
}
private var downloadReleaseId = - 1L
private val onDownloadReleaseComplete = object : BroadcastReceiver ( ) {
@SuppressLint ( " Range " )
override fun onReceive ( context : Context ? , intent : Intent ) {
if ( context == null ) return ;
val id = intent . getLongExtra ( DownloadManager . EXTRA _DOWNLOAD _ID , - 1L )
val downloadManager = context . getSystemService ( Context . DOWNLOAD _SERVICE ) as DownloadManager
if ( id == downloadReleaseId ) {
context . unregisterReceiver ( this )
val query = DownloadManager . Query ( ) . setFilterById ( id )
val cursor = downloadManager . query ( query )
if ( cursor . moveToFirst ( ) ) {
val status = cursor . getInt ( cursor . getColumnIndex ( DownloadManager . COLUMN _STATUS ) )
if ( status == DownloadManager . STATUS _SUCCESSFUL ) {
val localUri = cursor . getString ( cursor . getColumnIndex ( DownloadManager . COLUMN _LOCAL _URI ) )
FileUtil . openFileIntent ( context , localUri )
}
}
cursor . close ( )
}
}
}
@SuppressLint ( " UnspecifiedRegisterReceiverFlag " , " Range " )
suspend fun downloadReleaseApk ( context: Context , release: PackageRelease , onProgress : ( Long ) -> Unit ) : Result < Unit > {
suspend fun downloadReleaseApk ( release : PackageRelease , onProgress : ( Long ) -> Unit ) : Result < File > {
return withContext ( Dispatchers . IO ) {
try {
val releaseVersion = release . assets . first ( )
val uri = releaseVersion . browser _download _url . toUri ( )
Environment
. getExternalStoragePublicDirectory ( Environment . DIRECTORY _DOWNLOADS )
. mkdirs ( )
val downloadManager = context . getSystemService ( Context . DOWNLOAD _SERVICE ) as DownloadManager
downloadReleaseId = downloadManager . enqueue (
DownloadManager . Request ( uri )
. setAllowedNetworkTypes (
DownloadManager . Request . NETWORK _WIFI or
DownloadManager . Request . NETWORK _MOBILE
)
. setAllowedOverRoaming ( true )
. setNotificationVisibility ( DownloadManager . Request . VISIBILITY _VISIBLE _NOTIFY _COMPLETED )
. setTitle ( releaseVersion . name )
. setDescription ( context . getString ( R . string . downloading _update ) )
. setDestinationInExternalPublicDir ( Environment . DIRECTORY _DOWNLOADS , releaseVersion . name )
)
var downloading = true
while ( downloading ) {
val query = DownloadManager . Query ( ) . setFilterById ( downloadReleaseId )
val cursor = downloadManager . query ( query )
if ( cursor . moveToFirst ( ) ) {
val bytesDownloaded = cursor . getInt ( cursor . getColumnIndex ( DownloadManager . COLUMN _BYTES _DOWNLOADED _SO _FAR ) )
val totalBytes = cursor . getInt ( cursor . getColumnIndex ( DownloadManager . COLUMN _TOTAL _SIZE _BYTES ) )
val status = cursor . getInt ( cursor . getColumnIndex ( DownloadManager . COLUMN _STATUS ) )
if ( status == DownloadManager . STATUS _SUCCESSFUL ) {
downloading = false
}
File ( FileUtil . getDefaultApksPath ( ) ) . mkdirs ( )
val tempApk = File ( FileUtil . getDefaultApksPath ( ) , " ${packageFolderName} _ ${release.version.replace(".", "")} .apk " )
val request = Request . Builder ( )
. url ( release . assets . first ( ) . browser _download _url )
. build ( )
if ( totalBytes > 0 ) {
val progress = ( bytesDownloaded * 100L / totalBytes )
Environment . getExternalStoragePublicDirectory ( Environment . DIRECTORY _DOWNLOADS ) . mkdirs ( )
val response = sharedClient . newCall ( request ) . execute ( )
if ( ! response . isSuccessful ) {
return @withContext Result . failure ( Throwable ( response . body . string ( ) ) )
}
val body = response . body
val totalBytes = body . contentLength ( )
var bytesDownloaded = 0L
body . byteStream ( ) . use { inputStream ->
tempApk . outputStream ( ) . use { outputStream ->
val buffer = ByteArray ( 8192 )
var bytesRead : Int
while ( inputStream . read ( buffer ) . also { bytesRead = it } != - 1 ) {
if ( !is Active ) throw CancellationException ( " Download cancelled by user " )
outputStream . write ( buffer , 0 , bytesRead )
bytesDownloaded += bytesRead
val progress = ( ( bytesDownloaded * 100 ) / totalBytes )
onProgress ( progress )
}
}
cursor . close ( )
delay ( 500 )
}
val intentFilter = IntentFilter ( DownloadManager . ACTION _DOWNLOAD _COMPLETE )
if ( Build . VERSION . SDK _INT >= Build . VERSION_CODES . TIRAMISU ) {
context . registerReceiver ( onDownloadReleaseComplete , intentFilter , Context . RECEIVER _EXPORTED )
} else {
context . registerReceiver ( onDownloadReleaseComplete , intentFilter )
}
Result . success ( Unit )
Result . success ( tempApk )
} catch ( e : Exception ) {
Result . failure ( e )
}