diff --git a/gradle.properties b/gradle.properties index ef5d45a..5ab569f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ android.useAndroidX=true kotlin.code.style=official android.nonTransitiveRClass=true PUBLISH_VERSION=1.0.5 -SDK_CORE_VERSION=1.1.5 +SDK_CORE_VERSION=1.1.6-SNAPSHOT SDK_IM_VERSION=1.1.3 SDK_PUSH_VERSION=1.1.3 SDK_UPDATE_VERSION=1.1.8 diff --git a/sdk-core/src/main/java/com/xuqm/sdk/file/FileSDK.kt b/sdk-core/src/main/java/com/xuqm/sdk/file/FileSDK.kt index 42f7326..8508ecf 100644 --- a/sdk-core/src/main/java/com/xuqm/sdk/file/FileSDK.kt +++ b/sdk-core/src/main/java/com/xuqm/sdk/file/FileSDK.kt @@ -160,9 +160,16 @@ object FileSDK { notificationTitle: String? = null, onProgress: (Int) -> Unit = {}, ): File = withContext(Dispatchers.IO) { - val resolvedName = fileName?.takeIf { it.isNotBlank() } + val rawName = fileName?.takeIf { it.isNotBlank() } ?: downloadUrl.substringAfterLast('/').substringBefore('?').takeIf { it.isNotBlank() } ?: "download.bin" + // If the provided name has no extension, infer it from the URL path. + val resolvedName = if (!rawName.contains('.')) { + val urlExt = downloadUrl.substringAfterLast('/').substringBefore('?') + .substringAfterLast('.', "").lowercase() + .takeIf { it.isNotBlank() && it.length <= 10 && !it.contains('/') } + if (urlExt != null) "$rawName.$urlExt" else rawName + } else rawName val baseDir = when (destination) { FileDownloadDestination.PublicDownloads -> resolveBaseDir(context, destination) @@ -192,6 +199,7 @@ object FileSDK { } val capturedNotifId = notifId + var downloadError: Throwable? = null try { FileTransfer.downloadToFile(downloadUrl, target) { progress -> if (capturedNotifId != null) { @@ -204,21 +212,38 @@ object FileSDK { } onProgress(progress) } + } catch (e: Throwable) { + downloadError = e + android.util.Log.e("FileSDK", "download failed: url=$downloadUrl dest=${target.absolutePath}", e) + throw e } finally { capturedNotifId?.let { id -> val nm = NotificationManagerCompat.from(context) nm.cancel(id) if (nm.areNotificationsEnabled()) { - nm.notify( - id, - NotificationCompat.Builder(context, DOWNLOAD_CHANNEL_ID) - .setSmallIcon(android.R.drawable.stat_sys_download_done) - .setContentTitle(notificationTitle) - .setContentText("下载完成:$resolvedName") - .setContentIntent(buildOpenFilePendingIntent(context, target)) - .setAutoCancel(true) - .build(), - ) + val err = downloadError + if (err == null) { + nm.notify( + id, + NotificationCompat.Builder(context, DOWNLOAD_CHANNEL_ID) + .setSmallIcon(android.R.drawable.stat_sys_download_done) + .setContentTitle(notificationTitle) + .setContentText("下载完成:$resolvedName") + .setContentIntent(buildOpenFilePendingIntent(context, target)) + .setAutoCancel(true) + .build(), + ) + } else { + nm.notify( + id, + NotificationCompat.Builder(context, DOWNLOAD_CHANNEL_ID) + .setSmallIcon(android.R.drawable.stat_notify_error) + .setContentTitle(notificationTitle) + .setContentText("下载失败:${err.message ?: resolvedName}") + .setAutoCancel(true) + .build(), + ) + } } } }