mirror of
https://github.com/jellyfin/jellyfin-androidtv.git
synced 2025-05-17 19:36:03 +08:00
@ -1,7 +1,7 @@
|
|||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
apply plugin: 'kotlin-android'
|
apply plugin: 'kotlin-android'
|
||||||
apply plugin: 'kotlin-android-extensions'
|
apply plugin: 'kotlin-android-extensions'
|
||||||
def version = "0.11.0"
|
def version = "0.11.1"
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 28
|
compileSdkVersion 28
|
||||||
@ -15,7 +15,7 @@ android {
|
|||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 28
|
targetSdkVersion 28
|
||||||
versionCode 905
|
versionCode 906
|
||||||
versionName version
|
versionName version
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,9 @@ public enum HomeSectionType {
|
|||||||
RESUME_AUDIO("resumeaudio"),
|
RESUME_AUDIO("resumeaudio"),
|
||||||
ACTIVE_RECORDINGS("activerecordings"),
|
ACTIVE_RECORDINGS("activerecordings"),
|
||||||
NEXT_UP("nextup"),
|
NEXT_UP("nextup"),
|
||||||
LIVE_TV("livetv");
|
LIVE_TV("livetv"),
|
||||||
|
|
||||||
|
NONE("none");
|
||||||
|
|
||||||
public static HomeSectionType getByName(String name) {
|
public static HomeSectionType getByName(String name) {
|
||||||
for (HomeSectionType type : HomeSectionType.values()) {
|
for (HomeSectionType type : HomeSectionType.values()) {
|
||||||
@ -25,4 +27,4 @@ public enum HomeSectionType {
|
|||||||
HomeSectionType(String name) {
|
HomeSectionType(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,27 @@
|
|||||||
package org.jellyfin.androidtv.playback;
|
package org.jellyfin.androidtv.playback;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.graphics.PixelFormat;
|
import android.graphics.PixelFormat;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
import android.view.SurfaceHolder;
|
import android.view.SurfaceHolder;
|
||||||
import android.view.SurfaceView;
|
import android.view.SurfaceView;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
|
|
||||||
|
import com.google.android.exoplayer2.DefaultRenderersFactory;
|
||||||
import com.google.android.exoplayer2.ExoPlaybackException;
|
import com.google.android.exoplayer2.ExoPlaybackException;
|
||||||
import com.google.android.exoplayer2.ExoPlayerFactory;
|
import com.google.android.exoplayer2.ExoPlayerFactory;
|
||||||
import com.google.android.exoplayer2.Player;
|
import com.google.android.exoplayer2.Player;
|
||||||
|
import com.google.android.exoplayer2.Renderer;
|
||||||
import com.google.android.exoplayer2.SimpleExoPlayer;
|
import com.google.android.exoplayer2.SimpleExoPlayer;
|
||||||
import com.google.android.exoplayer2.source.ProgressiveMediaSource;
|
import com.google.android.exoplayer2.source.ProgressiveMediaSource;
|
||||||
|
import com.google.android.exoplayer2.text.TextOutput;
|
||||||
|
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
|
||||||
import com.google.android.exoplayer2.ui.PlayerView;
|
import com.google.android.exoplayer2.ui.PlayerView;
|
||||||
import com.google.android.exoplayer2.upstream.DataSource;
|
import com.google.android.exoplayer2.upstream.DataSource;
|
||||||
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
||||||
@ -69,6 +75,7 @@ public class VideoManager implements IVLCVout.OnNewVideoLayoutListener {
|
|||||||
private long mForcedTime = -1;
|
private long mForcedTime = -1;
|
||||||
private long mLastTime = -1;
|
private long mLastTime = -1;
|
||||||
private long mMetaDuration = -1;
|
private long mMetaDuration = -1;
|
||||||
|
private long lastExoPlayerPosition = -1;
|
||||||
|
|
||||||
private boolean nativeMode = false;
|
private boolean nativeMode = false;
|
||||||
private boolean mSurfaceReady = false;
|
private boolean mSurfaceReady = false;
|
||||||
@ -92,7 +99,19 @@ public class VideoManager implements IVLCVout.OnNewVideoLayoutListener {
|
|||||||
} else {
|
} else {
|
||||||
mSubtitlesSurface.setVisibility(View.GONE);
|
mSubtitlesSurface.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
mExoPlayer = ExoPlayerFactory.newSimpleInstance(TvApp.getApplication());
|
|
||||||
|
mExoPlayer = ExoPlayerFactory.newSimpleInstance(
|
||||||
|
TvApp.getApplication(),
|
||||||
|
new DefaultRenderersFactory(TvApp.getApplication()) {
|
||||||
|
@Override
|
||||||
|
protected void buildTextRenderers(Context context,
|
||||||
|
TextOutput output,
|
||||||
|
Looper outputLooper, int extensionRendererMode,
|
||||||
|
ArrayList<Renderer> out) {
|
||||||
|
// Do not add text renderers since we handle subtitles
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new DefaultTrackSelector());
|
||||||
mExoPlayerView = view.findViewById(R.id.exoPlayerView);
|
mExoPlayerView = view.findViewById(R.id.exoPlayerView);
|
||||||
mExoPlayerView.setPlayer(mExoPlayer);
|
mExoPlayerView.setPlayer(mExoPlayer);
|
||||||
mExoPlayer.addListener(new Player.EventListener() {
|
mExoPlayer.addListener(new Player.EventListener() {
|
||||||
@ -169,7 +188,15 @@ public class VideoManager implements IVLCVout.OnNewVideoLayoutListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public long getCurrentPosition() {
|
public long getCurrentPosition() {
|
||||||
if (nativeMode) return mExoPlayer.getCurrentPosition();
|
if (nativeMode) {
|
||||||
|
if (mExoPlayer == null) {
|
||||||
|
return lastExoPlayerPosition;
|
||||||
|
} else {
|
||||||
|
long mExoPlayerCurrentPosition = mExoPlayer.getCurrentPosition();
|
||||||
|
lastExoPlayerPosition = mExoPlayerCurrentPosition;
|
||||||
|
return mExoPlayerCurrentPosition;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (mVlcPlayer == null) return 0;
|
if (mVlcPlayer == null) return 0;
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import android.content.DialogInterface;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.util.ArrayMap;
|
||||||
|
|
||||||
import org.jellyfin.androidtv.R;
|
import org.jellyfin.androidtv.R;
|
||||||
import org.jellyfin.androidtv.TvApp;
|
import org.jellyfin.androidtv.TvApp;
|
||||||
@ -45,17 +46,11 @@ import java.io.IOException;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.TreeMap;
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import androidx.leanback.widget.ArrayObjectAdapter;
|
import androidx.leanback.widget.ArrayObjectAdapter;
|
||||||
import androidx.leanback.widget.ListRow;
|
import androidx.leanback.widget.ListRow;
|
||||||
import androidx.leanback.widget.OnItemViewClickedListener;
|
|
||||||
import androidx.leanback.widget.Presenter;
|
|
||||||
import androidx.leanback.widget.Row;
|
|
||||||
import androidx.leanback.widget.RowPresenter;
|
|
||||||
|
|
||||||
public class HomeFragment extends StdBrowseFragment {
|
public class HomeFragment extends StdBrowseFragment {
|
||||||
// Copied from jellyfin-web (homesections.js#getDefaultSection)
|
// Copied from jellyfin-web (homesections.js#getDefaultSection)
|
||||||
@ -65,7 +60,8 @@ public class HomeFragment extends StdBrowseFragment {
|
|||||||
HomeSectionType.RESUME_AUDIO,
|
HomeSectionType.RESUME_AUDIO,
|
||||||
HomeSectionType.LIVE_TV,
|
HomeSectionType.LIVE_TV,
|
||||||
HomeSectionType.NEXT_UP,
|
HomeSectionType.NEXT_UP,
|
||||||
HomeSectionType.LATEST_MEDIA
|
HomeSectionType.LATEST_MEDIA,
|
||||||
|
HomeSectionType.NONE
|
||||||
};
|
};
|
||||||
|
|
||||||
private List<HomeFragmentRow> rows = new ArrayList<>();
|
private List<HomeFragmentRow> rows = new ArrayList<>();
|
||||||
@ -234,8 +230,14 @@ public class HomeFragment extends StdBrowseFragment {
|
|||||||
Pattern pattern = Pattern.compile("^homesection(\\d+)$");
|
Pattern pattern = Pattern.compile("^homesection(\\d+)$");
|
||||||
|
|
||||||
// Add sections to map first to make sure they stay in the correct order
|
// Add sections to map first to make sure they stay in the correct order
|
||||||
Map<Integer, HomeSectionType> sections = new TreeMap<>();
|
ArrayMap<Integer, HomeSectionType> sections = new ArrayMap<>();
|
||||||
|
|
||||||
|
// Set defaults
|
||||||
|
for (int i = 0; i < DEFAULT_SECTIONS.length; i++) {
|
||||||
|
sections.put(i, DEFAULT_SECTIONS[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overwrite with user-preferred
|
||||||
for (String key : prefs.keySet()) {
|
for (String key : prefs.keySet()) {
|
||||||
Matcher matcher = pattern.matcher(key);
|
Matcher matcher = pattern.matcher(key);
|
||||||
if (!matcher.matches()) continue;
|
if (!matcher.matches()) continue;
|
||||||
@ -250,14 +252,10 @@ public class HomeFragment extends StdBrowseFragment {
|
|||||||
// Fallback when no customization is done by the user
|
// Fallback when no customization is done by the user
|
||||||
rows.clear();
|
rows.clear();
|
||||||
|
|
||||||
if (sections.size() > 0) {
|
// Actually add the sections
|
||||||
for (HomeSectionType section : sections.values()) {
|
for (HomeSectionType section : sections.values()) {
|
||||||
|
if (section != HomeSectionType.NONE)
|
||||||
addSection(section);
|
addSection(section);
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (HomeSectionType section : DEFAULT_SECTIONS) {
|
|
||||||
addSection(section);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
loadRows();
|
loadRows();
|
||||||
|
@ -51,7 +51,9 @@ public class AuthenticationHelper {
|
|||||||
public void onClick(DialogInterface dialog, int whichButton) {
|
public void onClick(DialogInterface dialog, int whichButton) {
|
||||||
String addressValue = address.getText().toString();
|
String addressValue = address.getText().toString();
|
||||||
TvApp.getApplication().getLogger().Debug("Entered address: " + addressValue);
|
TvApp.getApplication().getLogger().Debug("Entered address: " + addressValue);
|
||||||
signInToServer(TvApp.getApplication().getConnectionManager(), addressValue, activity);
|
if (!addressValue.isEmpty()) {
|
||||||
|
signInToServer(TvApp.getApplication().getConnectionManager(), addressValue, activity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}).show();
|
}).show();
|
||||||
}
|
}
|
||||||
|
@ -134,7 +134,7 @@
|
|||||||
android:title="@string/pref_enable_acra"
|
android:title="@string/pref_enable_acra"
|
||||||
android:summaryOn="@string/pref_acra_enabled"
|
android:summaryOn="@string/pref_acra_enabled"
|
||||||
android:summaryOff="@string/pref_acra_disabled"
|
android:summaryOff="@string/pref_acra_disabled"
|
||||||
android:defaultValue="false"/>
|
android:defaultValue="true"/>
|
||||||
<CheckBoxPreference android:key="acra.alwaysaccept"
|
<CheckBoxPreference android:key="acra.alwaysaccept"
|
||||||
android:title="@string/pref_acra_alwaysaccept"
|
android:title="@string/pref_acra_alwaysaccept"
|
||||||
android:summaryOn="@string/pref_acra_alwaysaccept_enabled"
|
android:summaryOn="@string/pref_acra_alwaysaccept_enabled"
|
||||||
|
Reference in New Issue
Block a user