mirror of
https://github.com/jellyfin/jellyfin-androidtv.git
synced 2026-10-26 16:45:23 +00:00
Fix Live TV guide crash when channel loading fails (#5801)
* Fix Live TV guide crash when channel loading fails * Handle unavailable channels in Live TV lookups
This commit is contained in:
1 parent
d9902de016
commit
04552d661f
5 files changed
+52
-3
No files matched your search
@@ -257,9 +257,11 @@ public class LiveProgramDetailPopup {
|
||||
|
||||
public android.widget.ImageButton createFavoriteButton() {
|
||||
BaseItemDto channel = TvManager.getChannel(TvManager.getAllChannelsIndex(mProgram.getChannelId()));
|
||||
boolean isFav = channel.getUserData() != null && channel.getUserData().isFavorite();
|
||||
boolean isFav = channel != null && channel.getUserData() != null && channel.getUserData().isFavorite();
|
||||
|
||||
android.widget.ImageButton fave = addImgButton(mDButtonRow, isFav ? R.drawable.ic_heart_red : R.drawable.ic_heart);
|
||||
fave.setEnabled(channel != null);
|
||||
if (channel == null) return fave;
|
||||
fave.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
||||
@@ -532,6 +532,7 @@ public class LiveTvGuideFragment extends Fragment implements LiveTvGuide, View.O
|
||||
for (int i = start; i <= end; i++) {
|
||||
if (isCancelled()) return null;
|
||||
final BaseItemDto channel = TvManager.getChannel(i);
|
||||
if (channel == null) continue;
|
||||
List<BaseItemDto> programs = TvManager.getProgramsForChannel(channel.getId(), mFilters);
|
||||
final LinearLayout row = getProgramRow(programs, channel.getId());
|
||||
if (row == null) continue; // no row to show
|
||||
|
||||
@@ -6,6 +6,7 @@ import android.text.format.DateUtils;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.leanback.widget.HeaderItem;
|
||||
import androidx.leanback.widget.ListRow;
|
||||
@@ -31,6 +32,7 @@ import java.time.ZoneOffset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -63,7 +65,7 @@ public class TvManager {
|
||||
}
|
||||
|
||||
public static List<BaseItemDto> getAllChannels() {
|
||||
return allChannels;
|
||||
return allChannels == null ? Collections.emptyList() : allChannels;
|
||||
}
|
||||
|
||||
public static void forceReload() {
|
||||
@@ -80,8 +82,10 @@ public class TvManager {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static BaseItemDto getChannel(int ndx) {
|
||||
return allChannels.get(ndx);
|
||||
List<BaseItemDto> channels = getAllChannels();
|
||||
return ndx >= 0 && ndx < channels.size() ? channels.get(ndx) : null;
|
||||
}
|
||||
|
||||
public static void updateLastPlayedDate(UUID channelId) {
|
||||
|
||||
+1
@@ -866,6 +866,7 @@ public class CustomPlaybackOverlayFragment extends Fragment implements LiveTvGui
|
||||
for (int i = start; i <= end; i++) {
|
||||
if (isCancelled()) return null;
|
||||
final BaseItemDto channel = TvManager.getChannel(i);
|
||||
if (channel == null) continue;
|
||||
List<BaseItemDto> programs = TvManager.getProgramsForChannel(channel.getId());
|
||||
final LinearLayout row = getProgramRow(programs, channel.getId());
|
||||
if (first) {
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package org.jellyfin.androidtv.ui.livetv
|
||||
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.shouldBe
|
||||
import org.jellyfin.sdk.model.api.BaseItemDto
|
||||
import org.jellyfin.sdk.model.api.BaseItemKind
|
||||
import java.util.UUID
|
||||
|
||||
class TvManagerTests : FunSpec({
|
||||
val channelsField = TvManager::class.java.getDeclaredField("allChannels").apply { isAccessible = true }
|
||||
var previousChannels: Any? = null
|
||||
|
||||
beforeTest {
|
||||
previousChannels = channelsField.get(null)
|
||||
channelsField.set(null, null)
|
||||
}
|
||||
|
||||
afterTest {
|
||||
channelsField.set(null, previousChannels)
|
||||
}
|
||||
|
||||
test("missing channel cache returns an empty list and no channel") {
|
||||
TvManager.getAllChannels() shouldBe emptyList()
|
||||
TvManager.getChannel(0) shouldBe null
|
||||
TvManager.getChannel(-1) shouldBe null
|
||||
}
|
||||
|
||||
test("empty channel cache returns no channel") {
|
||||
channelsField.set(null, emptyList<BaseItemDto>())
|
||||
TvManager.getChannel(0) shouldBe null
|
||||
}
|
||||
|
||||
test("cached channel lookup preserves valid channels and rejects invalid indices") {
|
||||
val channel = BaseItemDto(id = UUID.randomUUID(), type = BaseItemKind.TV_CHANNEL)
|
||||
channelsField.set(null, listOf(channel))
|
||||
TvManager.getChannel(0) shouldBe channel
|
||||
TvManager.getChannel(-1) shouldBe null
|
||||
TvManager.getChannel(1) shouldBe null
|
||||
TvManager.getChannel(Int.MAX_VALUE) shouldBe null
|
||||
}
|
||||
})
|
||||
Reference in new issue
Block a user