Fixed resource leak.

This commit is contained in:
Koen J 2024-08-30 13:44:14 +02:00
commit 3adf761158
2 changed files with 104 additions and 43 deletions

View file

@ -4,11 +4,12 @@ import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.content.pm.ActivityInfo
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.content.res.Configuration import android.content.res.Configuration
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.os.StrictMode
import android.os.StrictMode.VmPolicy
import android.util.Log import android.util.Log
import android.util.TypedValue import android.util.TypedValue
import android.view.View import android.view.View
@ -21,19 +22,45 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.motion.widget.MotionLayout import androidx.constraintlayout.motion.widget.MotionLayout
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentContainerView import androidx.fragment.app.FragmentContainerView
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.futo.platformplayer.* import com.futo.platformplayer.BuildConfig
import com.futo.platformplayer.R
import com.futo.platformplayer.Settings
import com.futo.platformplayer.UIDialogs
import com.futo.platformplayer.casting.StateCasting import com.futo.platformplayer.casting.StateCasting
import com.futo.platformplayer.constructs.Event1 import com.futo.platformplayer.constructs.Event1
import com.futo.platformplayer.fragment.mainactivity.bottombar.MenuBottomBarFragment import com.futo.platformplayer.fragment.mainactivity.bottombar.MenuBottomBarFragment
import com.futo.platformplayer.fragment.mainactivity.main.* import com.futo.platformplayer.fragment.mainactivity.main.BrowserFragment
import com.futo.platformplayer.fragment.mainactivity.main.BuyFragment
import com.futo.platformplayer.fragment.mainactivity.main.ChannelFragment
import com.futo.platformplayer.fragment.mainactivity.main.CommentsFragment
import com.futo.platformplayer.fragment.mainactivity.main.ContentSearchResultsFragment
import com.futo.platformplayer.fragment.mainactivity.main.CreatorSearchResultsFragment
import com.futo.platformplayer.fragment.mainactivity.main.CreatorsFragment
import com.futo.platformplayer.fragment.mainactivity.main.DownloadsFragment
import com.futo.platformplayer.fragment.mainactivity.main.HistoryFragment
import com.futo.platformplayer.fragment.mainactivity.main.HomeFragment
import com.futo.platformplayer.fragment.mainactivity.main.ImportPlaylistsFragment
import com.futo.platformplayer.fragment.mainactivity.main.ImportSubscriptionsFragment
import com.futo.platformplayer.fragment.mainactivity.main.MainFragment
import com.futo.platformplayer.fragment.mainactivity.main.PlaylistFragment
import com.futo.platformplayer.fragment.mainactivity.main.PlaylistSearchResultsFragment
import com.futo.platformplayer.fragment.mainactivity.main.PlaylistsFragment
import com.futo.platformplayer.fragment.mainactivity.main.PostDetailFragment
import com.futo.platformplayer.fragment.mainactivity.main.RemotePlaylistFragment
import com.futo.platformplayer.fragment.mainactivity.main.SourceDetailFragment
import com.futo.platformplayer.fragment.mainactivity.main.SourcesFragment
import com.futo.platformplayer.fragment.mainactivity.main.SubscriptionGroupFragment
import com.futo.platformplayer.fragment.mainactivity.main.SubscriptionGroupListFragment
import com.futo.platformplayer.fragment.mainactivity.main.SubscriptionsFeedFragment
import com.futo.platformplayer.fragment.mainactivity.main.SuggestionsFragment
import com.futo.platformplayer.fragment.mainactivity.main.TutorialFragment
import com.futo.platformplayer.fragment.mainactivity.main.VideoDetailFragment
import com.futo.platformplayer.fragment.mainactivity.main.WatchLaterFragment
import com.futo.platformplayer.fragment.mainactivity.topbar.AddTopBarFragment import com.futo.platformplayer.fragment.mainactivity.topbar.AddTopBarFragment
import com.futo.platformplayer.fragment.mainactivity.topbar.GeneralTopBarFragment import com.futo.platformplayer.fragment.mainactivity.topbar.GeneralTopBarFragment
import com.futo.platformplayer.fragment.mainactivity.topbar.ImportTopBarFragment import com.futo.platformplayer.fragment.mainactivity.topbar.ImportTopBarFragment
@ -41,7 +68,15 @@ import com.futo.platformplayer.fragment.mainactivity.topbar.NavigationTopBarFrag
import com.futo.platformplayer.fragment.mainactivity.topbar.SearchTopBarFragment import com.futo.platformplayer.fragment.mainactivity.topbar.SearchTopBarFragment
import com.futo.platformplayer.logging.Logger import com.futo.platformplayer.logging.Logger
import com.futo.platformplayer.models.ImportCache import com.futo.platformplayer.models.ImportCache
import com.futo.platformplayer.states.* import com.futo.platformplayer.setNavigationBarColorAndIcons
import com.futo.platformplayer.states.StateApp
import com.futo.platformplayer.states.StateBackup
import com.futo.platformplayer.states.StateDeveloper
import com.futo.platformplayer.states.StatePayment
import com.futo.platformplayer.states.StatePlatform
import com.futo.platformplayer.states.StatePlayer
import com.futo.platformplayer.states.StatePlaylists
import com.futo.platformplayer.states.StateSubscriptions
import com.futo.platformplayer.stores.FragmentedStorage import com.futo.platformplayer.stores.FragmentedStorage
import com.futo.platformplayer.stores.SubscriptionStorage import com.futo.platformplayer.stores.SubscriptionStorage
import com.futo.platformplayer.stores.v2.ManagedStore import com.futo.platformplayer.stores.v2.ManagedStore
@ -49,15 +84,22 @@ import com.futo.platformplayer.views.ToastView
import com.futo.polycentric.core.ApiMethods import com.futo.polycentric.core.ApiMethods
import com.google.gson.JsonParser import com.google.gson.JsonParser
import com.google.zxing.integration.android.IntentIntegrator import com.google.zxing.integration.android.IntentIntegrator
import kotlinx.coroutines.* import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import java.io.File import java.io.File
import java.io.PrintWriter import java.io.PrintWriter
import java.io.StringWriter import java.io.StringWriter
import java.lang.reflect.InvocationTargetException import java.lang.reflect.InvocationTargetException
import java.util.* import java.util.LinkedList
import java.util.Queue
import java.util.concurrent.ConcurrentLinkedQueue import java.util.concurrent.ConcurrentLinkedQueue
class MainActivity : AppCompatActivity, IWithResultLauncher { class MainActivity : AppCompatActivity, IWithResultLauncher {
//TODO: Move to dimensions //TODO: Move to dimensions
@ -154,6 +196,15 @@ class MainActivity : AppCompatActivity, IWithResultLauncher {
} }
constructor() : super() { constructor() : super() {
if (BuildConfig.DEBUG) {
StrictMode.setVmPolicy(
VmPolicy.Builder()
.detectLeakedClosableObjects()
.penaltyLog()
.build()
)
}
ApiMethods.UserAgent = "Grayjay Android (${BuildConfig.VERSION_CODE})"; ApiMethods.UserAgent = "Grayjay Android (${BuildConfig.VERSION_CODE})";
Thread.setDefaultUncaughtExceptionHandler { _, throwable -> Thread.setDefaultUncaughtExceptionHandler { _, throwable ->

View file

@ -540,15 +540,20 @@ class VideoDownload {
Logger.i(TAG, "Download '$name' segment $index Sequential"); Logger.i(TAG, "Download '$name' segment $index Sequential");
val segmentFile = File(context.cacheDir, "segment-${UUID.randomUUID()}") val segmentFile = File(context.cacheDir, "segment-${UUID.randomUUID()}")
val outputStream = segmentFile.outputStream()
try {
segmentFiles.add(segmentFile) segmentFiles.add(segmentFile)
val segmentLength = downloadSource_Sequential(client, segmentFile.outputStream(), segment.uri) { segmentLength, totalRead, lastSpeed -> val segmentLength = downloadSource_Sequential(client, outputStream, segment.uri) { segmentLength, totalRead, lastSpeed ->
val averageSegmentLength = if (index == 0) segmentLength else downloadedTotalLength / index val averageSegmentLength = if (index == 0) segmentLength else downloadedTotalLength / index
val expectedTotalLength = averageSegmentLength * (variantPlaylist.segments.size - 1) + segmentLength val expectedTotalLength = averageSegmentLength * (variantPlaylist.segments.size - 1) + segmentLength
onProgress(expectedTotalLength, downloadedTotalLength + totalRead, lastSpeed) onProgress(expectedTotalLength, downloadedTotalLength + totalRead, lastSpeed)
} }
downloadedTotalLength += segmentLength downloadedTotalLength += segmentLength
} finally {
outputStream.close()
}
} }
Logger.i(TAG, "Combining segments into $targetFile"); Logger.i(TAG, "Combining segments into $targetFile");
@ -757,8 +762,10 @@ class VideoDownload {
var lastSpeed: Long = 0; var lastSpeed: Long = 0;
val result = client.get(url); val result = client.get(url);
if (!result.isOk) if (!result.isOk) {
result.body?.close()
throw IllegalStateException("Failed to download source. Web[${result.code}] Error"); throw IllegalStateException("Failed to download source. Web[${result.code}] Error");
}
if (result.body == null) if (result.body == null)
throw IllegalStateException("Failed to download source. Web[${result.code}] No response"); throw IllegalStateException("Failed to download source. Web[${result.code}] No response");
@ -766,8 +773,8 @@ class VideoDownload {
val sourceStream = result.body.byteStream(); val sourceStream = result.body.byteStream();
var totalRead: Long = 0; var totalRead: Long = 0;
try {
var read: Int; var read: Int;
val buffer = ByteArray(4096); val buffer = ByteArray(4096);
do { do {
@ -796,8 +803,11 @@ class VideoDownload {
if (isCancelled) if (isCancelled)
throw CancellationException("Cancelled"); throw CancellationException("Cancelled");
} while (read > 0); } while (read > 0);
} finally {
sourceStream.close()
result.body.close()
}
lastSpeed = 0;
onProgress(sourceLength, totalRead, 0); onProgress(sourceLength, totalRead, 0);
return sourceLength; return sourceLength;
} }