| /* |
| * Copyright (C) 2015 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.tv.dvr.data; |
| |
| import android.content.ContentValues; |
| import android.database.Cursor; |
| import android.os.Parcel; |
| import android.os.Parcelable; |
| import android.support.annotation.IntDef; |
| import android.text.TextUtils; |
| import com.android.tv.data.BaseProgram; |
| import com.android.tv.data.Program; |
| import com.android.tv.dvr.DvrScheduleManager; |
| import com.android.tv.dvr.provider.DvrContract.SeriesRecordings; |
| import com.android.tv.util.Utils; |
| import java.lang.annotation.Retention; |
| import java.lang.annotation.RetentionPolicy; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.Comparator; |
| import java.util.Objects; |
| |
| /** |
| * Schedules the recording of a Series of Programs. |
| * |
| * <p>Contains the data needed to create new ScheduleRecordings as the programs become available in |
| * the EPG. |
| */ |
| public class SeriesRecording implements Parcelable { |
| /** Indicates that the ID is not assigned yet. */ |
| public static final long ID_NOT_SET = 0; |
| |
| /** The default priority of this recording. */ |
| public static final long DEFAULT_PRIORITY = Long.MAX_VALUE >> 1; |
| |
| @Retention(RetentionPolicy.SOURCE) |
| @IntDef( |
| flag = true, |
| value = {OPTION_CHANNEL_ONE, OPTION_CHANNEL_ALL}) |
| public @interface ChannelOption {} |
| /** An option which indicates that the episodes in one channel are recorded. */ |
| public static final int OPTION_CHANNEL_ONE = 0; |
| /** An option which indicates that the episodes in all the channels are recorded. */ |
| public static final int OPTION_CHANNEL_ALL = 1; |
| |
| @Retention(RetentionPolicy.SOURCE) |
| @IntDef( |
| flag = true, |
| value = {STATE_SERIES_NORMAL, STATE_SERIES_STOPPED}) |
| public @interface SeriesState {} |
| |
| /** The state indicates that the series recording is a normal one. */ |
| public static final int STATE_SERIES_NORMAL = 0; |
| |
| /** The state indicates that the series recording is stopped. */ |
| public static final int STATE_SERIES_STOPPED = 1; |
| |
| /** Compare priority in descending order. */ |
| public static final Comparator<SeriesRecording> PRIORITY_COMPARATOR = |
| (SeriesRecording lhs, SeriesRecording rhs) -> { |
| int value = Long.compare(rhs.mPriority, lhs.mPriority); |
| if (value == 0) { |
| // New recording has the higher priority. |
| value = Long.compare(rhs.mId, lhs.mId); |
| } |
| return value; |
| }; |
| |
| /** Compare ID in ascending order. */ |
| public static final Comparator<SeriesRecording> ID_COMPARATOR = |
| (SeriesRecording lhs, SeriesRecording rhs) -> Long.compare(lhs.mId, rhs.mId); |
| |
| /** |
| * Creates a new Builder with the values set from the series information of {@link BaseProgram}. |
| */ |
| public static Builder builder(String inputId, BaseProgram p) { |
| return new Builder() |
| .setInputId(inputId) |
| .setSeriesId(p.getSeriesId()) |
| .setChannelId(p.getChannelId()) |
| .setTitle(p.getTitle()) |
| .setDescription(p.getDescription()) |
| .setLongDescription(p.getLongDescription()) |
| .setCanonicalGenreIds(p.getCanonicalGenreIds()) |
| .setPosterUri(p.getPosterArtUri()) |
| .setPhotoUri(p.getThumbnailUri()); |
| } |
| |
| /** Creates a new Builder with the values set from an existing {@link SeriesRecording}. */ |
| public static Builder buildFrom(SeriesRecording r) { |
| return new Builder() |
| .setId(r.mId) |
| .setInputId(r.getInputId()) |
| .setChannelId(r.getChannelId()) |
| .setPriority(r.getPriority()) |
| .setTitle(r.getTitle()) |
| .setDescription(r.getDescription()) |
| .setLongDescription(r.getLongDescription()) |
| .setSeriesId(r.getSeriesId()) |
| .setStartFromEpisode(r.getStartFromEpisode()) |
| .setStartFromSeason(r.getStartFromSeason()) |
| .setChannelOption(r.getChannelOption()) |
| .setCanonicalGenreIds(r.getCanonicalGenreIds()) |
| .setPosterUri(r.getPosterUri()) |
| .setPhotoUri(r.getPhotoUri()) |
| .setState(r.getState()); |
| } |
| |
| /** |
| * Use this projection if you want to create {@link SeriesRecording} object using {@link |
| * #fromCursor}. |
| */ |
| public static final String[] PROJECTION = { |
| // Columns must match what is read in fromCursor() |
| SeriesRecordings._ID, |
| SeriesRecordings.COLUMN_INPUT_ID, |
| SeriesRecordings.COLUMN_CHANNEL_ID, |
| SeriesRecordings.COLUMN_PRIORITY, |
| SeriesRecordings.COLUMN_TITLE, |
| SeriesRecordings.COLUMN_SHORT_DESCRIPTION, |
| SeriesRecordings.COLUMN_LONG_DESCRIPTION, |
| SeriesRecordings.COLUMN_SERIES_ID, |
| SeriesRecordings.COLUMN_START_FROM_EPISODE, |
| SeriesRecordings.COLUMN_START_FROM_SEASON, |
| SeriesRecordings.COLUMN_CHANNEL_OPTION, |
| SeriesRecordings.COLUMN_CANONICAL_GENRE, |
| SeriesRecordings.COLUMN_POSTER_URI, |
| SeriesRecordings.COLUMN_PHOTO_URI, |
| SeriesRecordings.COLUMN_STATE |
| }; |
| /** Creates {@link SeriesRecording} object from the given {@link Cursor}. */ |
| public static SeriesRecording fromCursor(Cursor c) { |
| int index = -1; |
| return new Builder() |
| .setId(c.getLong(++index)) |
| .setInputId(c.getString(++index)) |
| .setChannelId(c.getLong(++index)) |
| .setPriority(c.getLong(++index)) |
| .setTitle(c.getString(++index)) |
| .setDescription(c.getString(++index)) |
| .setLongDescription(c.getString(++index)) |
| .setSeriesId(c.getString(++index)) |
| .setStartFromEpisode(c.getInt(++index)) |
| .setStartFromSeason(c.getInt(++index)) |
| .setChannelOption(channelOption(c.getString(++index))) |
| .setCanonicalGenreIds(c.getString(++index)) |
| .setPosterUri(c.getString(++index)) |
| .setPhotoUri(c.getString(++index)) |
| .setState(seriesRecordingState(c.getString(++index))) |
| .build(); |
| } |
| |
| /** |
| * Returns the ContentValues with keys as the columns specified in {@link SeriesRecordings} and |
| * the values from {@code r}. |
| */ |
| public static ContentValues toContentValues(SeriesRecording r) { |
| ContentValues values = new ContentValues(); |
| if (r.getId() != ID_NOT_SET) { |
| values.put(SeriesRecordings._ID, r.getId()); |
| } else { |
| values.putNull(SeriesRecordings._ID); |
| } |
| values.put(SeriesRecordings.COLUMN_INPUT_ID, r.getInputId()); |
| values.put(SeriesRecordings.COLUMN_CHANNEL_ID, r.getChannelId()); |
| values.put(SeriesRecordings.COLUMN_PRIORITY, r.getPriority()); |
| values.put(SeriesRecordings.COLUMN_TITLE, r.getTitle()); |
| values.put(SeriesRecordings.COLUMN_SHORT_DESCRIPTION, r.getDescription()); |
| values.put(SeriesRecordings.COLUMN_LONG_DESCRIPTION, r.getLongDescription()); |
| values.put(SeriesRecordings.COLUMN_SERIES_ID, r.getSeriesId()); |
| values.put(SeriesRecordings.COLUMN_START_FROM_EPISODE, r.getStartFromEpisode()); |
| values.put(SeriesRecordings.COLUMN_START_FROM_SEASON, r.getStartFromSeason()); |
| values.put(SeriesRecordings.COLUMN_CHANNEL_OPTION, channelOption(r.getChannelOption())); |
| values.put( |
| SeriesRecordings.COLUMN_CANONICAL_GENRE, |
| Utils.getCanonicalGenre(r.getCanonicalGenreIds())); |
| values.put(SeriesRecordings.COLUMN_POSTER_URI, r.getPosterUri()); |
| values.put(SeriesRecordings.COLUMN_PHOTO_URI, r.getPhotoUri()); |
| values.put(SeriesRecordings.COLUMN_STATE, seriesRecordingState(r.getState())); |
| return values; |
| } |
| |
| private static String channelOption(@ChannelOption int option) { |
| switch (option) { |
| case OPTION_CHANNEL_ONE: |
| return SeriesRecordings.OPTION_CHANNEL_ONE; |
| case OPTION_CHANNEL_ALL: |
| return SeriesRecordings.OPTION_CHANNEL_ALL; |
| } |
| return SeriesRecordings.OPTION_CHANNEL_ONE; |
| } |
| |
| @ChannelOption |
| private static int channelOption(String option) { |
| switch (option) { |
| case SeriesRecordings.OPTION_CHANNEL_ONE: |
| return OPTION_CHANNEL_ONE; |
| case SeriesRecordings.OPTION_CHANNEL_ALL: |
| return OPTION_CHANNEL_ALL; |
| } |
| return OPTION_CHANNEL_ONE; |
| } |
| |
| private static String seriesRecordingState(@SeriesState int state) { |
| switch (state) { |
| case STATE_SERIES_NORMAL: |
| return SeriesRecordings.STATE_SERIES_NORMAL; |
| case STATE_SERIES_STOPPED: |
| return SeriesRecordings.STATE_SERIES_STOPPED; |
| } |
| return SeriesRecordings.STATE_SERIES_NORMAL; |
| } |
| |
| @SeriesState |
| private static int seriesRecordingState(String state) { |
| switch (state) { |
| case SeriesRecordings.STATE_SERIES_NORMAL: |
| return STATE_SERIES_NORMAL; |
| case SeriesRecordings.STATE_SERIES_STOPPED: |
| return STATE_SERIES_STOPPED; |
| } |
| return STATE_SERIES_NORMAL; |
| } |
| |
| /** Builder for {@link SeriesRecording}. */ |
| public static class Builder { |
| private long mId = ID_NOT_SET; |
| private long mPriority = DvrScheduleManager.DEFAULT_SERIES_PRIORITY; |
| private String mTitle; |
| private String mDescription; |
| private String mLongDescription; |
| private String mInputId; |
| private long mChannelId; |
| private String mSeriesId; |
| private int mStartFromSeason = SeriesRecordings.THE_BEGINNING; |
| private int mStartFromEpisode = SeriesRecordings.THE_BEGINNING; |
| private int mChannelOption = OPTION_CHANNEL_ONE; |
| private int[] mCanonicalGenreIds; |
| private String mPosterUri; |
| private String mPhotoUri; |
| private int mState = SeriesRecording.STATE_SERIES_NORMAL; |
| |
| /** @see #getId() */ |
| public Builder setId(long id) { |
| mId = id; |
| return this; |
| } |
| |
| /** @see #getPriority() () */ |
| public Builder setPriority(long priority) { |
| mPriority = priority; |
| return this; |
| } |
| |
| /** @see #getTitle() */ |
| public Builder setTitle(String title) { |
| mTitle = title; |
| return this; |
| } |
| |
| /** @see #getDescription() */ |
| public Builder setDescription(String description) { |
| mDescription = description; |
| return this; |
| } |
| |
| /** @see #getLongDescription() */ |
| public Builder setLongDescription(String longDescription) { |
| mLongDescription = longDescription; |
| return this; |
| } |
| |
| /** @see #getInputId() */ |
| public Builder setInputId(String inputId) { |
| mInputId = inputId; |
| return this; |
| } |
| |
| /** @see #getChannelId() */ |
| public Builder setChannelId(long channelId) { |
| mChannelId = channelId; |
| return this; |
| } |
| |
| /** @see #getSeriesId() */ |
| public Builder setSeriesId(String seriesId) { |
| mSeriesId = seriesId; |
| return this; |
| } |
| |
| /** @see #getStartFromSeason() */ |
| public Builder setStartFromSeason(int startFromSeason) { |
| mStartFromSeason = startFromSeason; |
| return this; |
| } |
| |
| /** @see #getChannelOption() */ |
| public Builder setChannelOption(@ChannelOption int option) { |
| mChannelOption = option; |
| return this; |
| } |
| |
| /** @see #getStartFromEpisode() */ |
| public Builder setStartFromEpisode(int startFromEpisode) { |
| mStartFromEpisode = startFromEpisode; |
| return this; |
| } |
| |
| /** @see #getCanonicalGenreIds() */ |
| public Builder setCanonicalGenreIds(String genres) { |
| mCanonicalGenreIds = Utils.getCanonicalGenreIds(genres); |
| return this; |
| } |
| |
| /** @see #getCanonicalGenreIds() */ |
| public Builder setCanonicalGenreIds(int[] canonicalGenreIds) { |
| mCanonicalGenreIds = canonicalGenreIds; |
| return this; |
| } |
| |
| /** @see #getPosterUri() */ |
| public Builder setPosterUri(String posterUri) { |
| mPosterUri = posterUri; |
| return this; |
| } |
| |
| /** @see #getPhotoUri() */ |
| public Builder setPhotoUri(String photoUri) { |
| mPhotoUri = photoUri; |
| return this; |
| } |
| |
| /** @see #getState() */ |
| public Builder setState(@SeriesState int state) { |
| mState = state; |
| return this; |
| } |
| |
| /** Creates a new {@link SeriesRecording}. */ |
| public SeriesRecording build() { |
| return new SeriesRecording( |
| mId, |
| mPriority, |
| mTitle, |
| mDescription, |
| mLongDescription, |
| mInputId, |
| mChannelId, |
| mSeriesId, |
| mStartFromSeason, |
| mStartFromEpisode, |
| mChannelOption, |
| mCanonicalGenreIds, |
| mPosterUri, |
| mPhotoUri, |
| mState); |
| } |
| } |
| |
| public static SeriesRecording fromParcel(Parcel in) { |
| return new Builder() |
| .setId(in.readLong()) |
| .setPriority(in.readLong()) |
| .setTitle(in.readString()) |
| .setDescription(in.readString()) |
| .setLongDescription(in.readString()) |
| .setInputId(in.readString()) |
| .setChannelId(in.readLong()) |
| .setSeriesId(in.readString()) |
| .setStartFromSeason(in.readInt()) |
| .setStartFromEpisode(in.readInt()) |
| .setChannelOption(in.readInt()) |
| .setCanonicalGenreIds(in.createIntArray()) |
| .setPosterUri(in.readString()) |
| .setPhotoUri(in.readString()) |
| .setState(in.readInt()) |
| .build(); |
| } |
| |
| public static final Parcelable.Creator<SeriesRecording> CREATOR = |
| new Parcelable.Creator<SeriesRecording>() { |
| @Override |
| public SeriesRecording createFromParcel(Parcel in) { |
| return SeriesRecording.fromParcel(in); |
| } |
| |
| @Override |
| public SeriesRecording[] newArray(int size) { |
| return new SeriesRecording[size]; |
| } |
| }; |
| |
| private long mId; |
| private final long mPriority; |
| private final String mTitle; |
| private final String mDescription; |
| private final String mLongDescription; |
| private final String mInputId; |
| private final long mChannelId; |
| private final String mSeriesId; |
| private final int mStartFromSeason; |
| private final int mStartFromEpisode; |
| @ChannelOption private final int mChannelOption; |
| private final int[] mCanonicalGenreIds; |
| private final String mPosterUri; |
| private final String mPhotoUri; |
| @SeriesState private int mState; |
| |
| /** The input id of this SeriesRecording. */ |
| public String getInputId() { |
| return mInputId; |
| } |
| |
| /** |
| * The channelId to match. The channel ID might not be valid when the channel option is "ALL". |
| */ |
| public long getChannelId() { |
| return mChannelId; |
| } |
| |
| /** The id of this SeriesRecording. */ |
| public long getId() { |
| return mId; |
| } |
| |
| /** Sets the ID. */ |
| public void setId(long id) { |
| mId = id; |
| } |
| |
| /** |
| * The priority of this recording. |
| * |
| * <p>The highest number is recorded first. If there is a tie in mPriority then the higher mId |
| * wins. |
| */ |
| public long getPriority() { |
| return mPriority; |
| } |
| |
| /** The series title. */ |
| public String getTitle() { |
| return mTitle; |
| } |
| |
| /** The series description. */ |
| public String getDescription() { |
| return mDescription; |
| } |
| |
| /** The long series description. */ |
| public String getLongDescription() { |
| return mLongDescription; |
| } |
| |
| /** |
| * SeriesId when not null is used to match programs instead of using title and channelId. |
| * |
| * <p>SeriesId is an opaque but stable string. |
| */ |
| public String getSeriesId() { |
| return mSeriesId; |
| } |
| |
| /** |
| * If not == {@link SeriesRecordings#THE_BEGINNING} and seasonNumber == startFromSeason then |
| * only record episodes with a episodeNumber >= this |
| */ |
| public int getStartFromEpisode() { |
| return mStartFromEpisode; |
| } |
| |
| /** |
| * If not == {@link SeriesRecordings#THE_BEGINNING} then only record episodes with a |
| * seasonNumber >= this |
| */ |
| public int getStartFromSeason() { |
| return mStartFromSeason; |
| } |
| |
| /** Returns the channel recording option. */ |
| @ChannelOption |
| public int getChannelOption() { |
| return mChannelOption; |
| } |
| |
| /** Returns the canonical genre ID's. */ |
| public int[] getCanonicalGenreIds() { |
| return mCanonicalGenreIds; |
| } |
| |
| /** Returns the poster URI. */ |
| public String getPosterUri() { |
| return mPosterUri; |
| } |
| |
| /** Returns the photo URI. */ |
| public String getPhotoUri() { |
| return mPhotoUri; |
| } |
| |
| /** Returns the state of series recording. */ |
| @SeriesState |
| public int getState() { |
| return mState; |
| } |
| |
| /** Checks whether the series recording is stopped or not. */ |
| public boolean isStopped() { |
| return mState == STATE_SERIES_STOPPED; |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (this == o) return true; |
| if (!(o instanceof SeriesRecording)) return false; |
| SeriesRecording that = (SeriesRecording) o; |
| return mPriority == that.mPriority |
| && mChannelId == that.mChannelId |
| && mStartFromSeason == that.mStartFromSeason |
| && mStartFromEpisode == that.mStartFromEpisode |
| && Objects.equals(mId, that.mId) |
| && Objects.equals(mTitle, that.mTitle) |
| && Objects.equals(mDescription, that.mDescription) |
| && Objects.equals(mLongDescription, that.mLongDescription) |
| && Objects.equals(mSeriesId, that.mSeriesId) |
| && mChannelOption == that.mChannelOption |
| && Arrays.equals(mCanonicalGenreIds, that.mCanonicalGenreIds) |
| && Objects.equals(mPosterUri, that.mPosterUri) |
| && Objects.equals(mPhotoUri, that.mPhotoUri) |
| && mState == that.mState; |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash( |
| mPriority, |
| mChannelId, |
| mStartFromSeason, |
| mStartFromEpisode, |
| mId, |
| mTitle, |
| mDescription, |
| mLongDescription, |
| mSeriesId, |
| mChannelOption, |
| Arrays.hashCode(mCanonicalGenreIds), |
| mPosterUri, |
| mPhotoUri, |
| mState); |
| } |
| |
| @Override |
| public String toString() { |
| return "SeriesRecording{" |
| + "inputId=" |
| + mInputId |
| + ", channelId=" |
| + mChannelId |
| + ", id='" |
| + mId |
| + '\'' |
| + ", priority=" |
| + mPriority |
| + ", title='" |
| + mTitle |
| + '\'' |
| + ", description='" |
| + mDescription |
| + '\'' |
| + ", longDescription='" |
| + mLongDescription |
| + '\'' |
| + ", startFromSeason=" |
| + mStartFromSeason |
| + ", startFromEpisode=" |
| + mStartFromEpisode |
| + ", channelOption=" |
| + mChannelOption |
| + ", canonicalGenreIds=" |
| + Arrays.toString(mCanonicalGenreIds) |
| + ", posterUri=" |
| + mPosterUri |
| + ", photoUri=" |
| + mPhotoUri |
| + ", state=" |
| + mState |
| + '}'; |
| } |
| |
| private SeriesRecording( |
| long id, |
| long priority, |
| String title, |
| String description, |
| String longDescription, |
| String inputId, |
| long channelId, |
| String seriesId, |
| int startFromSeason, |
| int startFromEpisode, |
| int channelOption, |
| int[] canonicalGenreIds, |
| String posterUri, |
| String photoUri, |
| int state) { |
| this.mId = id; |
| this.mPriority = priority; |
| this.mTitle = title; |
| this.mDescription = description; |
| this.mLongDescription = longDescription; |
| this.mInputId = inputId; |
| this.mChannelId = channelId; |
| this.mSeriesId = seriesId; |
| this.mStartFromSeason = startFromSeason; |
| this.mStartFromEpisode = startFromEpisode; |
| this.mChannelOption = channelOption; |
| this.mCanonicalGenreIds = canonicalGenreIds; |
| this.mPosterUri = posterUri; |
| this.mPhotoUri = photoUri; |
| this.mState = state; |
| } |
| |
| @Override |
| public int describeContents() { |
| return 0; |
| } |
| |
| @Override |
| public void writeToParcel(Parcel out, int paramInt) { |
| out.writeLong(mId); |
| out.writeLong(mPriority); |
| out.writeString(mTitle); |
| out.writeString(mDescription); |
| out.writeString(mLongDescription); |
| out.writeString(mInputId); |
| out.writeLong(mChannelId); |
| out.writeString(mSeriesId); |
| out.writeInt(mStartFromSeason); |
| out.writeInt(mStartFromEpisode); |
| out.writeInt(mChannelOption); |
| out.writeIntArray(mCanonicalGenreIds); |
| out.writeString(mPosterUri); |
| out.writeString(mPhotoUri); |
| out.writeInt(mState); |
| } |
| |
| /** Returns an array containing all of the elements in the list. */ |
| public static SeriesRecording[] toArray(Collection<SeriesRecording> series) { |
| return series.toArray(new SeriesRecording[series.size()]); |
| } |
| |
| /** |
| * Returns {@code true} if the {@code program} is part of the series and meets the season and |
| * episode constraints. |
| */ |
| public boolean matchProgram(Program program) { |
| return matchProgram(program, mChannelOption); |
| } |
| |
| /** |
| * Returns {@code true} if the {@code program} is part of the series and meets the season and |
| * episode constraints. It checks the channel option only if {@code checkChannelOption} is |
| * {@code true}. |
| */ |
| public boolean matchProgram(Program program, @ChannelOption int channelOption) { |
| String seriesId = program.getSeriesId(); |
| long channelId = program.getChannelId(); |
| String seasonNumber = program.getSeasonNumber(); |
| String episodeNumber = program.getEpisodeNumber(); |
| if (!mSeriesId.equals(seriesId) |
| || (channelOption == SeriesRecording.OPTION_CHANNEL_ONE |
| && mChannelId != channelId)) { |
| return false; |
| } |
| // Season number and episode number matches if |
| // start_season_number < program_season_number |
| // || (start_season_number == program_season_number |
| // && start_episode_number <= program_episode_number). |
| if (mStartFromSeason == SeriesRecordings.THE_BEGINNING || TextUtils.isEmpty(seasonNumber)) { |
| return true; |
| } else { |
| int intSeasonNumber; |
| try { |
| intSeasonNumber = Integer.valueOf(seasonNumber); |
| } catch (NumberFormatException e) { |
| return true; |
| } |
| if (intSeasonNumber > mStartFromSeason) { |
| return true; |
| } else if (intSeasonNumber < mStartFromSeason) { |
| return false; |
| } |
| } |
| if (mStartFromEpisode == SeriesRecordings.THE_BEGINNING |
| || TextUtils.isEmpty(episodeNumber)) { |
| return true; |
| } else { |
| int intEpisodeNumber; |
| try { |
| intEpisodeNumber = Integer.valueOf(episodeNumber); |
| } catch (NumberFormatException e) { |
| return true; |
| } |
| return intEpisodeNumber >= mStartFromEpisode; |
| } |
| } |
| } |