Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ import com.hippo.ehviewer.AppConfig
import com.hippo.ehviewer.EhApplication
import com.hippo.ehviewer.R
import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.client.EhUtils
import com.hippo.ehviewer.client.data.GalleryInfo
import com.hippo.ehviewer.dao.DownloadInfo
import com.hippo.ehviewer.gallery.GalleryProvider2
import com.hippo.ehviewer.spider.SpiderDen
import com.hippo.ehviewer.spider.SpiderQueen
import com.hippo.lib.yorozuya.FileUtils as YorozuyaFileUtils
import com.hippo.lib.yorozuya.StringUtils
import com.hippo.lib.yorozuya.Utilities
Expand Down Expand Up @@ -44,13 +44,14 @@ class ArchiverDownloadCompleter private constructor(appContext: Context) {
if (!tryBeginHandling(taskId)) {
return
}
val tempDir = AppConfig.getExternalTempDir()
val tempDir = AppConfig.getExternalTempDir() ?: AppConfig.getTempDir()
if (tempDir == null) {
endHandling(taskId)
handleFailedTask(galleryInfo, taskId)
return
}
val displayName = createFileName(galleryInfo.title, galleryInfo.gid)
val displayName = EhUtils.getSuitableTitle(galleryInfo)
?: createFileName(galleryInfo.title, galleryInfo.gid)
val tempFile = File(tempDir, "archiver_${galleryInfo.gid}")

Thread {
Expand All @@ -66,6 +67,9 @@ class ArchiverDownloadCompleter private constructor(appContext: Context) {
tempFile.deleteOnExit()
}
postImportFailed(galleryInfo, taskId)
} finally {
// After the success post: a task still pending must keep its zip.
mainHandler.post { deleteIfPrivate(zipFile) }
}
}.start()
}
Expand Down Expand Up @@ -128,10 +132,7 @@ class ArchiverDownloadCompleter private constructor(appContext: Context) {
}
Collections.sort(tempPictures) { file1, file2 -> file1.name.compareTo(file2.name) }

val spiderDen = SpiderDen(galleryInfo)
spiderDen.setMode(SpiderQueen.MODE_DOWNLOAD)
spiderDen.prepareDownloadStorage()
val downloadDir = spiderDen.getDownloadDir()
val downloadDir = SpiderDen.getGalleryDownloadDir(galleryInfo)?.takeIf { it.ensureDir() }
if (downloadDir == null) {
postImportFailed(galleryInfo, taskId)
return
Expand Down Expand Up @@ -221,12 +222,12 @@ class ArchiverDownloadCompleter private constructor(appContext: Context) {

@JvmStatic
fun createFileName(name: String?, gid: Long): String {
var result = name?.let { YorozuyaFileUtils.sanitizeFilename(it) } ?: ""
result = truncateUtf8ToMaxBytes(result, MAX_ARCHIVER_BASENAME_UTF8_BYTES)
if (result.isEmpty()) {
result = if (gid > 0) "archiver_$gid" else "archiver"
}
return result
val suffix = if (gid > 0) "_$gid" else ""
val title = truncateUtf8ToMaxBytes(
name?.let { YorozuyaFileUtils.sanitizeFilename(it) } ?: "",
MAX_ARCHIVER_BASENAME_UTF8_BYTES - suffix.length
)
return title.ifEmpty { "archiver" } + suffix
}

/**
Expand Down Expand Up @@ -294,6 +295,12 @@ class ArchiverDownloadCompleter private constructor(appContext: Context) {
return true
}

private fun deleteIfPrivate(zipFile: File) {
if (zipFile.parentFile == AppConfig.getArchiverDir() && !zipFile.delete()) {
Log.w(TAG, "Failed to delete zip: ${zipFile.path}")
}
}

private fun deleteTempDir(destDir: File) {
if (destDir.exists() && !YorozuyaFileUtils.delete(destDir)) {
Log.w(TAG, "Failed to delete temp dir: ${destDir.path}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import android.content.pm.ServiceInfo
import android.os.Build
import android.os.Bundle
import android.os.IBinder
import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat
import com.hippo.ehviewer.R
import com.hippo.ehviewer.ui.MainActivity
Expand Down Expand Up @@ -95,14 +96,22 @@ class ArchiverDownloadService : Service() {
return START_NOT_STICKY
}
if (!foregroundStarted) {
startForegroundCompat(NOTIFICATION_ID, notification)
foregroundStarted = true
foregroundStarted = startForegroundCompat(NOTIFICATION_ID, notification)
} else {
notificationManager?.notify(NOTIFICATION_ID, notification)
}
return START_STICKY
}

@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
override fun onTimeout(startId: Int, fgsType: Int) {
// Stop first: stopping under a pause's pending startForegroundService crashes.
stopForeground(STOP_FOREGROUND_REMOVE)
foregroundStarted = false
stopSelf()
ArchiverDownloader.getInstance(this)?.pauseAll()
}

override fun onBind(intent: Intent?): IBinder? = null

private fun showPausedNotification(notification: Notification, startId: Int) {
Expand Down Expand Up @@ -209,11 +218,17 @@ class ArchiverDownloadService : Service() {
return PendingIntent.getService(this, requestCode, intent, PENDING_INTENT_FLAGS)
}

private fun startForegroundCompat(id: Int, notification: Notification) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
startForeground(id, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC)
} else {
startForeground(id, notification)
private fun startForegroundCompat(id: Int, notification: Notification): Boolean {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
startForeground(id, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC)
} else {
startForeground(id, notification)
}
return true
} catch (e: IllegalStateException) {
android.util.Log.w("ArchiverDownloadService", "startForeground refused", e)
return false
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,12 @@ class ArchiverDownloader private constructor(appContext: Context) {
publishProgress(task, true)
}

fun pauseAll() {
for (gid in activeTasks.keys) {
pause(gid)
}
}

fun resume(gid: Long) {
val task = activeTasks[gid] ?: return
if (!task.paused) {
Expand All @@ -130,7 +136,13 @@ class ArchiverDownloader private constructor(appContext: Context) {
deleteZipFile(task.zipFile)
clearTaskSettings(gid, task.taskId)
notifyCancel(gid, task.taskId)
ArchiverDownloadService.stop(appContext)
stopServiceIfIdle()
}

private fun stopServiceIfIdle() {
if (activeTasks.values.none { !it.paused }) {
ArchiverDownloadService.stop(appContext)
}
}

private fun startInternal(
Expand Down Expand Up @@ -188,13 +200,13 @@ class ArchiverDownloader private constructor(appContext: Context) {
activeTasks.remove(info.gid)
if (call.isCanceled) {
notifyCancel(info.gid, taskId)
ArchiverDownloadService.stop(appContext)
stopServiceIfIdle()
return
}
deleteZipFile(zipFile)
clearTaskSettings(info.gid, taskId)
notifyFailure(info.gid, taskId, e)
ArchiverDownloadService.stop(appContext)
stopServiceIfIdle()
}

override fun onResponse(call: Call, response: Response) {
Expand All @@ -219,7 +231,7 @@ class ArchiverDownloader private constructor(appContext: Context) {
clearTaskSettings(info.gid, taskId)
notifyFailure(info.gid, taskId, IOException("HTTP $code"))
response.close()
ArchiverDownloadService.stop(appContext)
stopServiceIfIdle()
return
}
val body = response.body()
Expand All @@ -229,7 +241,7 @@ class ArchiverDownloader private constructor(appContext: Context) {
clearTaskSettings(info.gid, taskId)
notifyFailure(info.gid, taskId, IOException("Empty response body"))
response.close()
ArchiverDownloadService.stop(appContext)
stopServiceIfIdle()
return
}
var writeOffset = offset
Expand Down Expand Up @@ -283,7 +295,7 @@ class ArchiverDownloader private constructor(appContext: Context) {
notifySuccess(info.gid, taskId, zipFile)
ArchiverDownloadCompleter.getInstance(appContext)
?.importDownloadedZip(zipFile, info, taskId)
ArchiverDownloadService.stop(appContext)
stopServiceIfIdle()
} catch (e: PauseSignal) {
if (task.call === call) {
publishProgress(task, true)
Expand All @@ -307,7 +319,7 @@ class ArchiverDownloader private constructor(appContext: Context) {
} else {
notifyFailure(info.gid, taskId, e)
}
ArchiverDownloadService.stop(appContext)
stopServiceIfIdle()
}
}
}
Expand All @@ -329,7 +341,7 @@ class ArchiverDownloader private constructor(appContext: Context) {
notifySuccess(info.gid, taskId, zipFile)
ArchiverDownloadCompleter.getInstance(appContext)
?.importDownloadedZip(zipFile, info, taskId)
ArchiverDownloadService.stop(appContext)
stopServiceIfIdle()
return
}
if (task.paused) {
Expand All @@ -340,7 +352,7 @@ class ArchiverDownloader private constructor(appContext: Context) {
deleteZipFile(zipFile)
clearTaskSettings(info.gid, taskId)
notifyFailure(info.gid, taskId, IOException("HTTP 416"))
ArchiverDownloadService.stop(appContext)
stopServiceIfIdle()
}

private fun publishProgress(task: ActiveTask, force: Boolean) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,11 @@ class DownloadService : Service(), DownloadManager.DownloadListener {
return START_STICKY
}

override fun onTimeout(startId: Int, fgsType: Int) {
mDownloadManager?.stopAllDownload()
checkStopSelf()
}

private fun handleIntent(intent: Intent?) {
var action: String? = null
if (intent != null) {
Expand Down
10 changes: 10 additions & 0 deletions app/src/main/java/com/hippo/ehviewer/smb/SmbDirectDownloader.java
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,16 @@ public void pause(long gid) {
});
}

/** {@link #pause} for every task at once, queued ones included (#166). */
public void pauseAll() {
SimpleHandler.getInstance().post(() -> {
for (SmbTaskLedger.ActiveJob job : ledger.suspendAll()) {
releaseQueen(job, "pause", job.info.gid);
}
afterQueueChange();
});
}

/** Resume a paused task by re-enqueueing it. No-op if the task isn't paused. */
public void resume(long gid) {
SimpleHandler.getInstance().post(() -> {
Expand Down
25 changes: 20 additions & 5 deletions app/src/main/java/com/hippo/ehviewer/smb/SmbDownloadService.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,20 @@ public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
return START_STICKY;
}

@Override
public void onTimeout(int startId, int fgsType) {
SmbDirectDownloader.getInstance().pauseAll();
stopForegroundCompat();
stopSelf();
}

@Override
public void onDestroy() {
SmbDirectDownloader.getInstance().detachService();
NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if (nm != null) {
nm.cancel(NOTIFICATION_ID);
}
super.onDestroy();
}

Expand All @@ -104,11 +115,15 @@ public void updateNotification(String title, String text, int max, int progress,
}

private void startInForeground(Notification notification) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
startForeground(NOTIFICATION_ID, notification,
ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC);
} else {
startForeground(NOTIFICATION_ID, notification);
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
startForeground(NOTIFICATION_ID, notification,
ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC);
} else {
startForeground(NOTIFICATION_ID, notification);
}
} catch (IllegalStateException e) {
Log.w(TAG, "startForeground refused", e);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ ActiveJob yield(long gid) {
}
}

/** Holds everything (SMB went away); returns the jobs the caller must release. */
/** Holds everything; returns the jobs the caller must release. */
@NonNull
List<ActiveJob> suspendAll() {
synchronized (lock) {
Expand Down
Loading
Loading