public static LongSparseArray<XmlTvParser.XmlTvChannel> buildChannelMap( ContentResolver resolver, String inputId, List<XmlTvParser.XmlTvChannel> channels) { Uri uri = TvContract.buildChannelsUriForInput(inputId); String[] projection = { TvContract.Channels._ID, TvContract.Channels.COLUMN_DISPLAY_NUMBER }; LongSparseArray<XmlTvParser.XmlTvChannel> channelMap = new LongSparseArray<>(); try (Cursor cursor = resolver.query(uri, projection, null, null, null)) { if (cursor == null || cursor.getCount() == 0) { return null; } while (cursor.moveToNext()) { long channelId = cursor.getLong(0); String channelNumber = cursor.getString(1); channelMap.put(channelId, getChannelByNumber(channelNumber, channels)); } } catch (Exception e) { Log.d(TAG, "Content provider query: " + Arrays.toString(e.getStackTrace())); return null; } return channelMap; }
public static List<Program> getPrograms(ContentResolver resolver, Uri channelUri) { Uri uri = TvContract.buildProgramsUriForChannel(channelUri); List<Program> programs = new ArrayList<>(); // TvProvider returns programs in chronological order by default. try (Cursor cursor = resolver.query(uri, null, null, null, null)) { if (cursor == null || cursor.getCount() == 0) { return programs; } while (cursor.moveToNext()) { programs.add(Program.fromCursor(cursor)); } } catch (Exception e) { Log.w(TAG, "Unable to get programs for " + channelUri, e); } return programs; }
private void handleStartRecording() { if (DEBUG) Log.d(TAG, "handleStartRecording " + mScheduledRecording); long programId = mScheduledRecording.getProgramId(); mRecordingSession.startRecording(programId == ScheduledRecording.ID_NOT_SET ? null : TvContract.buildProgramUri(programId)); updateRecordingState(ScheduledRecording.STATE_RECORDING_IN_PROGRESS); // If it starts late, it's clipped. if (mScheduledRecording.getStartTimeMs() + CLIPPED_THRESHOLD_MS < mClock.currentTimeMillis()) { mStartedWithClipping = true; } mState = State.RECORDING_STARTED; if (!sendEmptyMessageAtAbsoluteTime(MSG_STOP_RECORDING, mScheduledRecording.getEndTimeMs())) { failAndQuit(); } }
@Override protected Void doInBackground(Void... params) { @DvrStorageStatusManager.StorageStatus int storageStatus = getDvrStorageStatus(); if (storageStatus == DvrStorageStatusManager.STORAGE_STATUS_MISSING) { return null; } List<ContentProviderOperation> ops = getDeleteOps(storageStatus == DvrStorageStatusManager.STORAGE_STATUS_TOTAL_CAPACITY_TOO_SMALL); if (ops == null || ops.isEmpty()) { return null; } Log.i(TAG, "New device storage mounted. # of recordings to be forgotten : " + ops.size()); for (int i = 0 ; i < ops.size() && !isCancelled() ; i += BATCH_OPERATION_COUNT) { int toIndex = (i + BATCH_OPERATION_COUNT) > ops.size() ? ops.size() : (i + BATCH_OPERATION_COUNT); ArrayList<ContentProviderOperation> batchOps = new ArrayList<>(ops.subList(i, toIndex)); try { mContext.getContentResolver().applyBatch(TvContract.AUTHORITY, batchOps); } catch (RemoteException | OperationApplicationException e) { Log.e(TAG, "Failed to clean up RecordedPrograms.", e); } } return null; }
private void setTitleAndImage(RecordingCardView cardView, ScheduledRecording recording) { Channel channel = mChannelDataManager.getChannel(recording.getChannelId()); SpannableString title = recording.getProgramTitleWithEpisodeNumber(mContext) == null ? null : new SpannableString(recording.getProgramTitleWithEpisodeNumber(mContext)); if (TextUtils.isEmpty(title)) { title = new SpannableString(channel != null ? channel.getDisplayName() : mContext.getResources().getString(R.string.no_program_information)); } else { String programTitle = recording.getProgramTitle(); title.setSpan(new TextAppearanceSpan(mContext, R.style.text_appearance_card_view_episode_number), programTitle == null ? 0 : programTitle.length(), title.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } String imageUri = recording.getProgramPosterArtUri(); boolean isChannelLogo = false; if (TextUtils.isEmpty(imageUri)) { imageUri = channel != null ? TvContract.buildChannelLogoUri(channel.getId()).toString() : null; isChannelLogo = true; } cardView.setTitle(title); cardView.setImageUri(imageUri, isChannelLogo); }
/** * Sets background image and logo image URI and channel is used for fallback images. */ public Builder setImageUris(@Nullable String posterArtUri, @Nullable String thumbnailUri, @Nullable Channel channel) { mDetailsContent.mLogoImageUri = null; mDetailsContent.mBackgroundImageUri = null; if (!TextUtils.isEmpty(posterArtUri) && !TextUtils.isEmpty(thumbnailUri)) { mDetailsContent.mLogoImageUri = posterArtUri; mDetailsContent.mBackgroundImageUri = thumbnailUri; } else if (!TextUtils.isEmpty(posterArtUri)) { // thumbnailUri is empty mDetailsContent.mLogoImageUri = posterArtUri; mDetailsContent.mBackgroundImageUri = posterArtUri; } else if (!TextUtils.isEmpty(thumbnailUri)) { // posterArtUri is empty mDetailsContent.mLogoImageUri = thumbnailUri; mDetailsContent.mBackgroundImageUri = thumbnailUri; } if (TextUtils.isEmpty(mDetailsContent.mLogoImageUri) && channel != null) { String channelLogoUri = TvContract.buildChannelLogoUri(channel.getId()) .toString(); mDetailsContent.mLogoImageUri = channelLogoUri; mDetailsContent.mBackgroundImageUri = channelLogoUri; } return this; }
private void setupMediaSession(RecordedProgram program) { mProgramDurationMs = program.getDurationMillis(); String cardTitleText = program.getTitle(); if (TextUtils.isEmpty(cardTitleText)) { Channel channel = mChannelDataManager.getChannel(program.getChannelId()); cardTitleText = (channel != null) ? channel.getDisplayName() : mActivity.getString(R.string.no_program_information); } updateMediaMetadata(program.getId(), cardTitleText, program.getDescription(), mProgramDurationMs, null, 0); String posterArtUri = program.getPosterArtUri(); if (posterArtUri == null) { posterArtUri = TvContract.buildChannelLogoUri(program.getChannelId()).toString(); } updatePosterArt(program, cardTitleText, program.getDescription(), mProgramDurationMs, null, posterArtUri); mMediaSession.setActive(true); }
private void onStart() { if (!mStarted) { mStarted = true; mCancelLoadTask = false; if (!PermissionUtils.hasAccessWatchedHistory(mContext)) { mWatchedHistoryManager = new WatchedHistoryManager(mContext); mWatchedHistoryManager.setListener(this); mWatchedHistoryManager.start(); } else { mContext.getContentResolver().registerContentObserver( TvContract.WatchedPrograms.CONTENT_URI, true, mContentObserver); mHandler.obtainMessage(MSG_UPDATE_WATCH_HISTORY, TvContract.WatchedPrograms.CONTENT_URI) .sendToTarget(); } mTvInputManager = (TvInputManager) mContext.getSystemService(Context.TV_INPUT_SERVICE); mTvInputManager.registerCallback(mInternalCallback, mHandler); for (TvInputInfo input : mTvInputManager.getTvInputList()) { mInputs.add(input.getId()); } } if (mChannelRecordMapLoaded) { mHandler.sendEmptyMessage(MSG_NOTIFY_CHANNEL_RECORD_MAP_LOADED); } }
/** * Updates a column {@code columnName} of DB table {@code uri} with the value * {@code columnValue}. The selective rows in the ID list {@code ids} will be updated. * The DB operations will run on {@link AsyncDbTask#getExecutor()}. */ private void updateOneColumnValue( final String columnName, final int columnValue, final List<Long> ids) { if (!PermissionUtils.hasAccessAllEpg(mContext)) { // TODO: support this feature for non-system LC app. b/23939816 return; } AsyncDbTask.execute(new Runnable() { @Override public void run() { String selection = Utils.buildSelectionForIds(Channels._ID, ids); ContentValues values = new ContentValues(); values.put(columnName, columnValue); mContentResolver.update(TvContract.Channels.CONTENT_URI, values, selection, null); } }); }
private SetupUtils(TvApplication tvApplication) { mTvApplication = tvApplication; mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(tvApplication); mSetUpInputs = new ArraySet<>(); mSetUpInputs.addAll(mSharedPreferences.getStringSet(PREF_KEY_SET_UP_INPUTS, Collections.emptySet())); mKnownInputs = new ArraySet<>(); mKnownInputs.addAll(mSharedPreferences.getStringSet(PREF_KEY_KNOWN_INPUTS, Collections.emptySet())); mRecognizedInputs = new ArraySet<>(); mRecognizedInputs.addAll(mSharedPreferences.getStringSet(PREF_KEY_RECOGNIZED_INPUTS, mKnownInputs)); mIsFirstTune = mSharedPreferences.getBoolean(PREF_KEY_IS_FIRST_TUNE, true); mTunerInputId = TvContract.buildInputId(new ComponentName(tvApplication, TunerTvInputService.class)); }
/** * Grants permission for writing EPG data to a given package. * * @param context The Context used for granting permission. * @param packageName The name of the package to give permission. */ public static void grantEpgPermission(Context context, String packageName) { if (DEBUG) { Log.d(TAG, "grantEpgPermission(context=" + context + ", packageName=" + packageName + ")"); } try { int modeFlags = Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION; context.grantUriPermission(packageName, TvContract.Channels.CONTENT_URI, modeFlags); context.grantUriPermission(packageName, TvContract.Programs.CONTENT_URI, modeFlags); } catch (SecurityException e) { Log.e(TAG, "Either TvProvider does not allow granting of Uri permissions or the app" + " does not have permission.", e); } }
/** * Gets the info of the program on particular time. */ @WorkerThread public static Program getProgramAt(Context context, long channelId, long timeMs) { if (channelId == Channel.INVALID_ID) { Log.e(TAG, "getCurrentProgramAt - channelId is invalid"); return null; } if (context.getMainLooper().getThread().equals(Thread.currentThread())) { String message = "getCurrentProgramAt called on main thread"; if (DEBUG) { // Generating a stack trace can be expensive, only do it in debug mode. Log.w(TAG, message, new IllegalStateException(message)); } else { Log.w(TAG, message); } } Uri uri = TvContract.buildProgramsUriForChannel(TvContract.buildChannelUri(channelId), timeMs, timeMs); try (Cursor cursor = context.getContentResolver().query(uri, Program.PROJECTION, null, null, null)) { if (cursor != null && cursor.moveToNext()) { return Program.fromCursor(cursor); } } return null; }
private Program getRecordedProgram() { ContentResolver resolver = mContext.getContentResolver(); Uri programUri = mProgramUri; if (mProgramUri == null) { long avg = mRecordStartTime / 2 + mRecordEndTime / 2; programUri = TvContract.buildProgramsUriForChannel(mChannel.getChannelId(), avg, avg); } try (Cursor c = resolver.query(programUri, Program.PROJECTION, null, null, SORT_BY_TIME)) { if (c != null) { Program result = Program.onQuery(c); if (DEBUG) { Log.v(TAG, "Finished query for " + this); } return result; } else { if (c == null) { Log.e(TAG, "Unknown query error for " + this); } else { if (DEBUG) Log.d(TAG, "Canceled query for " + this); } return null; } } }
private Uri insertRecordedProgram(Program program, long channelId, String storageUri, long totalBytes, long startTime, long endTime) { // TODO: Set title even though program is null. RecordedProgram recordedProgram = RecordedProgram.builder() .setInputId(mInputId) .setChannelId(channelId) .setDataUri(storageUri) .setDurationMillis(endTime - startTime) .setDataBytes(totalBytes) // startTime and endTime could be overridden by program's start and end value. .setStartTimeUtcMillis(startTime) .setEndTimeUtcMillis(endTime) .build(); ContentValues values = RecordedProgram.toValues(recordedProgram); if (program != null) { values.putAll(program.buildValues()); } return mContext.getContentResolver().insert(TvContract.RecordedPrograms.CONTENT_URI, values); }
public TunerChannel getChannel(long channelId) { TunerChannel channel = mTunerChannelMap.get(channelId); if (channel != null) { return channel; } mHandler.sendEmptyMessage(MSG_BUILD_CHANNEL_MAP); byte[] data = null; try (Cursor cursor = mContext.getContentResolver().query(TvContract.buildChannelUri( channelId), CHANNEL_DATA_SELECTION_ARGS, null, null, null)) { if (cursor != null && cursor.moveToFirst()) { data = cursor.getBlob(1); } } if (data == null) { return null; } channel = TunerChannel.parseFrom(data); if (channel == null) { return null; } channel.setChannelId(channelId); return channel; }
public void scannedChannelHandlingCompleted() { mIsScanning.set(false); if (!mPreviousScannedChannels.isEmpty()) { ArrayList<ContentProviderOperation> ops = new ArrayList<>(); for (TunerChannel channel : mPreviousScannedChannels) { ops.add(ContentProviderOperation.newDelete( TvContract.buildChannelUri(channel.getChannelId())).build()); } try { mContext.getContentResolver().applyBatch(TvContract.AUTHORITY, ops); } catch (RemoteException | OperationApplicationException e) { Log.e(TAG, "Error deleting obsolete channels", e); } } if (mChannelScanListener != null && mChannelScanHandler != null) { mChannelScanHandler.post(new Runnable() { @Override public void run() { mChannelScanListener.onChannelHandlingDone(); } }); } else { Log.e(TAG, "Error. mChannelScanListener is null."); } }
private ContentProviderOperation buildContentProviderOperation( ContentProviderOperation.Builder builder, EitItem item, Long channelId) { if (channelId != null) { builder.withValue(TvContract.Programs.COLUMN_CHANNEL_ID, channelId); } if (item != null) { builder.withValue(TvContract.Programs.COLUMN_TITLE, item.getTitleText()) .withValue(TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS, item.getStartTimeUtcMillis()) .withValue(TvContract.Programs.COLUMN_END_TIME_UTC_MILLIS, item.getEndTimeUtcMillis()) .withValue(TvContract.Programs.COLUMN_CONTENT_RATING, item.getContentRating()) .withValue(TvContract.Programs.COLUMN_AUDIO_LANGUAGE, item.getAudioLanguage()) .withValue(TvContract.Programs.COLUMN_SHORT_DESCRIPTION, item.getDescription()) .withValue(TvContract.Programs.COLUMN_VERSION_NUMBER, item.getEventId()); } return builder.build(); }
@Override protected void setUp() throws Exception { super.setUp(); assertTrue("More than 2 channels to test", Constants.UNIT_TEST_CHANNEL_COUNT > 2); mContentProvider = new FakeContentProvider(getContext()); mContentResolver = new FakeContentResolver(); mContentResolver.addProvider(TvContract.AUTHORITY, mContentProvider); mListener = new TestChannelDataManagerListener(); Utils.runOnMainSync(new Runnable() { @Override public void run() { TvInputManagerHelper mockHelper = Mockito.mock(TvInputManagerHelper.class); Mockito.when(mockHelper.hasTvInputInfo(Matchers.anyString())).thenReturn(true); mChannelDataManager = new ChannelDataManager(getContext(), mockHelper, mContentResolver); mChannelDataManager.addListener(mListener); } }); }
@Override protected void setUp() throws Exception { super.setUp(); mClock = FakeClock.createWithCurrentTime(); mListener = new TestProgramDataManagerListener(); mContentProvider = new FakeContentProvider(getContext()); mContentResolver = new FakeContentResolver(); mContentResolver.addProvider(TvContract.AUTHORITY, mContentProvider); mHandlerThread = new HandlerThread(TAG); mHandlerThread.start(); mProgramDataManager = new ProgramDataManager( mContentResolver, mClock, mHandlerThread.getLooper(), null); mProgramDataManager.setPrefetchEnabled(true); mProgramDataManager.addListener(mListener); }
/** * Simulate program data appends at the end of the existing programs. * This appends programs until the maximum program query range * ({@link ProgramDataManager#PROGRAM_GUIDE_MAX_TIME_RANGE}) * where we started with the inserting half of it. */ public void simulateAppend(long channelId) { long endTimeMs = mClock.currentTimeMillis() + ProgramDataManager.PROGRAM_GUIDE_MAX_TIME_RANGE; List<ProgramInfoWrapper> programList = mProgramInfoList.get((int) channelId); if (mProgramInfoList == null) { return; } ProgramInfo stub = ProgramInfo.create(); ProgramInfoWrapper last = programList.get(programList.size() - 1); while (last.startTimeMs < endTimeMs) { ProgramInfo nextProgramInfo = stub.build(getContext(), last.index + 1); ProgramInfoWrapper next = new ProgramInfoWrapper(last.index + 1, last.startTimeMs + last.programInfo.durationMs, nextProgramInfo); programList.add(next); last = next; } mContentResolver.notifyChange(TvContract.Programs.CONTENT_URI, null); }
@Override public long getLong(int columnIndex) { String columnName = getColumnName(columnIndex); switch (columnName) { case TvContract.Programs.COLUMN_CHANNEL_ID: return mChannelId; case TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS: return mCurrentProgram.startTimeMs; case TvContract.Programs.COLUMN_END_TIME_UTC_MILLIS: return mCurrentProgram.startTimeMs + mCurrentProgram.programInfo.durationMs; } if (DEBUG) { Log.d(TAG, "Column (" + columnName + ") is ignored in getLong()"); } return 0; }
@Override public String getString(int columnIndex) { String columnName = getColumnName(columnIndex); switch (columnName) { case TvContract.Programs.COLUMN_TITLE: return mCurrentProgram.programInfo.title; case TvContract.Programs.COLUMN_SHORT_DESCRIPTION: return mCurrentProgram.programInfo.description; case TvContract.Programs.COLUMN_EPISODE_TITLE: return mCurrentProgram.programInfo.episode; } if (DEBUG) { Log.d(TAG, "Column (" + columnName + ") is ignored in getString()"); } return null; }
public static void registerChannels(Context context, String inputId, boolean updateBrowsable, int channelCount) { Log.i(TAG, "Registering " + channelCount + " channels"); List<ChannelInfo> channels = new ArrayList<>(); for (int i = 1; i <= channelCount; i++) { channels.add(ChannelInfo.create(context, i)); } ChannelUtils.updateChannels(context, inputId, channels); if (updateBrowsable) { updateChannelsBrowsable(context.getContentResolver(), inputId); } // Reload channels so we have the ids. Map<Long, ChannelInfo> channelIdToInfoMap = ChannelUtils.queryChannelInfoMapForTvInput(context, inputId); for (Long channelId : channelIdToInfoMap.keySet()) { // TODO: http://b/21705569 Create better program info for tests ProgramInfo programInfo = ProgramInfo.create(); ProgramUtils.populatePrograms(context, TvContract.buildChannelUri(channelId), programInfo); } }
public static ProgramInfo fromCursor(Cursor c) { // TODO: Fill other fields. Builder builder = new Builder(); int index = c.getColumnIndex(TvContract.Programs.COLUMN_TITLE); if (index >= 0) { builder.setTitle(c.getString(index)); } index = c.getColumnIndex(TvContract.Programs.COLUMN_SHORT_DESCRIPTION); if (index >= 0) { builder.setDescription(c.getString(index)); } index = c.getColumnIndex(TvContract.Programs.COLUMN_EPISODE_TITLE); if (index >= 0) { builder.setEpisode(c.getString(index)); } return builder.build(); }
/** * Query and return the map of (channel_id, ChannelInfo). * See: {@link ChannelInfo#fromCursor(Cursor)}. */ @WorkerThread public static Map<Long, ChannelInfo> queryChannelInfoMapForTvInput( Context context, String inputId) { Uri uri = TvContract.buildChannelsUriForInput(inputId); Map<Long, ChannelInfo> map = new HashMap<>(); String[] projections = new String[ChannelInfo.PROJECTION.length + 1]; projections[0] = Channels._ID; System.arraycopy(ChannelInfo.PROJECTION, 0, projections, 1, ChannelInfo.PROJECTION.length); try (Cursor cursor = context.getContentResolver() .query(uri, projections, null, null, null)) { if (cursor != null) { while (cursor.moveToNext()) { map.put(cursor.getLong(0), ChannelInfo.fromCursor(cursor)); } } return map; } }
public static ChannelInfo fromCursor(Cursor c) { // TODO: Fill other fields. Builder builder = new Builder(); int index = c.getColumnIndex(TvContract.Channels.COLUMN_DISPLAY_NUMBER); if (index >= 0) { builder.setNumber(c.getString(index)); } index = c.getColumnIndex(TvContract.Channels.COLUMN_DISPLAY_NAME); if (index >= 0) { builder.setName(c.getString(index)); } index = c.getColumnIndex(TvContract.Channels.COLUMN_ORIGINAL_NETWORK_ID); if (index >= 0) { builder.setOriginalNetworkId(c.getInt(index)); } return builder.build(); }
public static List<Program> getPrograms(ContentResolver resolver, Uri channelUri) { Uri uri = TvContract.buildProgramsUriForChannel(channelUri); Cursor cursor = null; List<Program> programs = new ArrayList<>(); try { // TvProvider returns programs chronological order by default. cursor = resolver.query(uri, null, null, null, null); if (cursor == null || cursor.getCount() == 0) { return programs; } while (cursor.moveToNext()) { programs.add(Program.fromCursor(cursor)); } } catch (Exception e) { Log.w(TAG, "Unable to get programs for " + channelUri, e); } finally { if (cursor != null) { cursor.close(); } } return programs; }
public static long getLastProgramEndTimeMillis(ContentResolver resolver, Uri channelUri) { Uri uri = TvContract.buildProgramsUriForChannel(channelUri); String[] projection = {Programs.COLUMN_END_TIME_UTC_MILLIS}; Cursor cursor = null; try { // TvProvider returns programs chronological order by default. cursor = resolver.query(uri, projection, null, null, null); if (cursor == null || cursor.getCount() == 0) { return 0; } cursor.moveToLast(); return cursor.getLong(0); } catch (Exception e) { Log.w(TAG, "Unable to get last program end time for " + channelUri, e); } finally { if (cursor != null) { cursor.close(); } } return 0; }
/** * Finds already existing programs for a given channel * @param mContext The context of this application * @param channelUri The URI of the channel * @return */ public List<Program> getPrograms(Context mContext, Uri channelUri) { ContentResolver resolver = mContext.getContentResolver(); Uri uri = TvContract.buildProgramsUriForChannel(channelUri); Cursor cursor = null; List<Program> programs = new ArrayList<>(); try { // TvProvider returns programs chronological order by default. cursor = resolver.query(uri, null, null, null, null); if (cursor == null || cursor.getCount() == 0) { return programs; } while (cursor.moveToNext()) { programs.add(Program.fromCursor(cursor)); } } catch (Exception e) { Log.w(TAG, "Unable to get programs for " + channelUri, e); } finally { if (cursor != null) { cursor.close(); } } return programs; }
/** * If you don't have access to an EPG or don't want to supply programs, you can simply * add several instances of this generic program object. * * Note you will have to set the start and end times manually. * @param channel The channel for which the program will be displayed * @return A very generic program object */ public Program getGenericProgram(Channel channel) { TvContentRating rating = RATING_PG; return new Program.Builder() .setTitle(channel.getName() + " Live") .setProgramId(channel.getServiceId()) // .setEpisodeNumber(1) // .setSeasonNumber(1) // .setEpisodeTitle("Streaming") .setDescription("Currently streaming") .setLongDescription(channel.getName() + " is currently streaming live.") .setCanonicalGenres(new String[]{TvContract.Programs.Genres.ENTERTAINMENT}) .setThumbnailUri(channel.getLogoUrl()) .setPosterArtUri(channel.getLogoUrl()) .setInternalProviderData(channel.getName()) .setContentRatings(new TvContentRating[] {rating}) .setVideoHeight(1080) .setVideoWidth(1920) .build(); }
@Override public boolean onTune(Uri channelUri) { Log.d(TAG, "onTune " + channelUri); notifyVideoUnavailable(TvInputManager.VIDEO_UNAVAILABLE_REASON_TUNING); String[] projection = {TvContract.Channels.COLUMN_INTERNAL_PROVIDER_DATA}; try (Cursor cursor = context.getContentResolver().query( channelUri, projection, null, // selection null, // selectionArgs null // sortOrder )) { if (cursor == null || !cursor.moveToNext()) { Log.e(TAG, "Channel not found: " + channelUri); return false; } String url = cursor.getString(0); play(url); return true; } }
/** * This method is used to check if the current event is already present in the DB * * @param program Program to check in DB * @return True if the program is present in the DB, false otherwise */ protected boolean checkifExist(long channelID, long startTime, long endTime) { Uri uri = TvContract.buildProgramsUriForChannel(channelID, startTime, endTime); Cursor cursor = mContext.getContentResolver().query(uri, projection, null, null, null); if (cursor == null || cursor.getCount() == 0) { cursor.close(); mLog.w("[checkifExist][item does not exist in DB][[uri: " + uri.toString() + "]"); return false; } else { cursor.close(); return true; } /** * TODO Implement program update */ }
private ArrayList<ChannelDescriptor> loadChannels(String inputId) { ArrayList<ChannelDescriptor> ret = new ArrayList<ChannelDescriptor>(); final String[] projection = { Channels._ID, Channels.COLUMN_DISPLAY_NAME, Channels.COLUMN_DISPLAY_NUMBER, Channels.COLUMN_SERVICE_ID, Channels.COLUMN_TYPE, Channels.COLUMN_SERVICE_TYPE }; Cursor cursor = mContext.getContentResolver().query( TvContract.buildChannelsUriForInput(mInputId), projection, null, null, null); if (cursor == null) { return ret; } cursor.moveToFirst(); while (!cursor.isAfterLast()) { ChannelDescriptor cd = new ChannelDescriptor(cursor); mLog.d("[loadChannels] index=" + cd.getChannelId() + " info=" + cd); ret.add(cd); cursor.moveToNext(); } cursor.close(); return ret; }
private static void actuallyWriteData(final Context context, GoogleApiClient gapi) { DriveSettingsManager sm = new DriveSettingsManager(context); sm.setGoogleDriveSyncable(gapi, new DriveSettingsManager.GoogleDriveListener() { @Override public void onActionFinished(boolean cloudToLocal) { Log.d(TAG, "Action finished " + cloudToLocal); } }); try { sm.writeToGoogleDrive(DriveId.decodeFromString(sm.getString(R.string.sm_google_drive_id)), ChannelDatabase.getInstance(context).toString()); GoogleDriveBroadcastReceiver.changeStatus(context, GoogleDriveBroadcastReceiver.EVENT_UPLOAD_COMPLETE); final String info = TvContract.buildInputId(TV_INPUT_SERVICE); CumulusJobService.requestImmediateSync1(context, info, CumulusJobService.DEFAULT_IMMEDIATE_EPG_DURATION_MILLIS, new ComponentName(context, CumulusJobService.class)); Log.d(TAG, "Data actually written"); // Toast.makeText(context, "Channels uploaded", Toast.LENGTH_SHORT).show(); } catch(Exception e) { // Probably invalid drive id. No worries, just let someone know Log.e(TAG, e.getMessage() + ""); Toast.makeText(context, R.string.invalid_file, Toast.LENGTH_SHORT).show(); } }
public String[] getGenres() { if(getGenresString() == null) { return new String[]{TvContract.Programs.Genres.MOVIES}; } if(getGenresString().isEmpty()) { return new String[]{TvContract.Programs.Genres.MOVIES}; } else { //Parse genres CommaArray ca = new CommaArray(getGenresString()); Iterator<String> it = ca.getIterator(); ArrayList<String> arrayList = new ArrayList<>(); while(it.hasNext()) { String i = it.next(); arrayList.add(i); } return arrayList.toArray(new String[arrayList.size()]); } }
@Before public void insertChannels() { Context context = getActivity(); ContentValues contentValues = new ContentValues(); contentValues.put(TvContract.Channels.COLUMN_ORIGINAL_NETWORK_ID, 1); contentValues.put(TvContract.Channels.COLUMN_DISPLAY_NAME, "Hello"); contentValues.put(TvContract.Channels.COLUMN_DISPLAY_NUMBER, "123"); contentValues.put(TvContract.Channels.COLUMN_INPUT_ID, ActivityUtils.TV_INPUT_SERVICE.flattenToString()); contentValues.put(TvContract.Channels.COLUMN_INTERNAL_PROVIDER_DATA, MEDIA_URL); Uri databaseUri = context.getContentResolver().insert(TvContract.Channels.CONTENT_URI, contentValues); Log.d(TAG, "Inserted in Uri " + databaseUri); // Make sure we actually inserted something ContentResolver contentResolver = context.getContentResolver(); Cursor cursor = contentResolver.query(TvContract.Channels.CONTENT_URI, null, null, null, null); assertNotNull(cursor); assertEquals(1, cursor.getCount()); assertTrue(cursor.moveToNext()); assertEquals(1, cursor.getLong(cursor.getColumnIndex( TvContract.Channels.COLUMN_ORIGINAL_NETWORK_ID))); cursor.close(); }
@Override public void onCreate() { super.onCreate(); // Create background thread mDbHandlerThread = new HandlerThread(getClass().getSimpleName()); mDbHandlerThread.start(); // Initialize the channel map and set observer for changes mContentResolver = BaseTvInputService.this.getContentResolver(); updateChannelMap(); mChannelObserver = new ContentObserver(new Handler(mDbHandlerThread.getLooper())) { @Override public void onChange(boolean selfChange) { updateChannelMap(); } }; mContentResolver.registerContentObserver(TvContract.Channels.CONTENT_URI, true, mChannelObserver); // Setup our BroadcastReceiver IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(TvInputManager.ACTION_BLOCKED_RATINGS_CHANGED); intentFilter.addAction(TvInputManager.ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED); registerReceiver(mParentalControlsBroadcastReceiver, intentFilter); }
@Before public void setUp() throws Exception { super.setUp(); injectInstrumentation(InstrumentationRegistry.getInstrumentation()); getActivity(); // Delete all channels getActivity().getContentResolver().delete(TvContract.buildChannelsUriForInput(mInputId), null, null); mSampleJobService = new TestJobService(); mSampleJobService.mContext = getActivity(); mChannelList = mSampleJobService.getChannels(); TvContractUtils.updateChannels(getActivity(), mInputId, mChannelList); mChannelMap = TvContractUtils.buildChannelMap(getActivity().getContentResolver(), mInputId); assertEquals(2, mChannelMap.size()); }
@Test public void testChannelsProgramSync() { // Tests that programs and channels were correctly obtained from the EpgSyncJobService Uri channelUri = TvContract.buildChannelUri(mChannelMap.keyAt(0)); Channel firstChannel = mChannelList.get(0); assertEquals("Test Channel", firstChannel.getDisplayName()); assertNotNull(firstChannel.getInternalProviderData()); assertTrue(firstChannel.getInternalProviderData().isRepeatable()); mProgramList = mSampleJobService.getProgramsForChannel(channelUri, firstChannel, mStartMs, mEndMs); assertEquals(1, mProgramList.size()); channelUri = TvContract.buildChannelUri(mChannelMap.keyAt(1)); Channel secondChannel = mChannelList.get(1); assertEquals("XML Test Channel", secondChannel.getDisplayName()); assertNotNull(secondChannel.getInternalProviderData()); assertTrue(secondChannel.getInternalProviderData().isRepeatable()); mProgramList = mSampleJobService.getProgramsForChannel(channelUri, secondChannel, mStartMs, mEndMs); assertEquals(5, mProgramList.size()); }
@Test public void testRequestSync() throws InterruptedException { // Tests that a sync can be requested and complete LocalBroadcastManager.getInstance(getActivity()).registerReceiver( mSyncStatusChangedReceiver, new IntentFilter(EpgSyncJobService.ACTION_SYNC_STATUS_CHANGED)); mSyncStatusLatch = new CountDownLatch(2); EpgSyncJobService.cancelAllSyncRequests(getActivity()); EpgSyncJobService.requestImmediateSync(getActivity(), TestTvInputService.INPUT_ID, 1000 * 60 * 60, // 1 hour sync period new ComponentName(getActivity(), TestJobService.class)); mSyncStatusLatch.await(); // Sync is completed List<Channel> channelList = TvContractUtils.getChannels(getActivity().getContentResolver()); Log.d("TvContractUtils", channelList.toString()); assertEquals(2, channelList.size()); List<Program> programList = TvContractUtils.getPrograms(getActivity().getContentResolver(), TvContract.buildChannelUri(channelList.get(0).getId())); assertEquals(5, programList.size()); }