下面列出了怎么用android.media.tv.TvContentRating的API类实例代码及写法,或者点击链接到github查看源代码。
@Override
public List<String> getBlockedRatings(int userId) {
final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(),
Binder.getCallingUid(), userId, "getBlockedRatings");
final long identity = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
UserState userState = getOrCreateUserStateLocked(resolvedUserId);
List<String> ratings = new ArrayList<>();
for (TvContentRating rating
: userState.persistentDataStore.getBlockedRatings()) {
ratings.add(rating.flattenToString());
}
return ratings;
}
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@Override
public void addBlockedRating(String rating, int userId) {
ensureParentalControlsPermission();
final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(),
Binder.getCallingUid(), userId, "addBlockedRating");
final long identity = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
UserState userState = getOrCreateUserStateLocked(resolvedUserId);
userState.persistentDataStore.addBlockedRating(
TvContentRating.unflattenFromString(rating));
}
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@Override
public void removeBlockedRating(String rating, int userId) {
ensureParentalControlsPermission();
final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(),
Binder.getCallingUid(), userId, "removeBlockedRating");
final long identity = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
UserState userState = getOrCreateUserStateLocked(resolvedUserId);
userState.persistentDataStore.removeBlockedRating(
TvContentRating.unflattenFromString(rating));
}
} finally {
Binder.restoreCallingIdentity(identity);
}
}
private void saveToXml(XmlSerializer serializer) throws IOException {
serializer.startDocument(null, true);
serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
serializer.startTag(null, TAG_TV_INPUT_MANAGER_STATE);
serializer.startTag(null, TAG_BLOCKED_RATINGS);
synchronized (mBlockedRatings) {
for (TvContentRating rating : mBlockedRatings) {
serializer.startTag(null, TAG_RATING);
serializer.attribute(null, ATTR_STRING, rating.flattenToString());
serializer.endTag(null, TAG_RATING);
}
}
serializer.endTag(null, TAG_BLOCKED_RATINGS);
serializer.startTag(null, TAG_PARENTAL_CONTROLS);
serializer.attribute(null, ATTR_ENABLED, Boolean.toString(mParentalControlsEnabled));
serializer.endTag(null, TAG_PARENTAL_CONTROLS);
serializer.endTag(null, TAG_TV_INPUT_MANAGER_STATE);
serializer.endDocument();
}
/**
* 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 isRatingBlocked(String rating, int userId) {
final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(),
Binder.getCallingUid(), userId, "isRatingBlocked");
final long identity = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
UserState userState = getOrCreateUserStateLocked(resolvedUserId);
return userState.persistentDataStore.isRatingBlocked(
TvContentRating.unflattenFromString(rating));
}
} finally {
Binder.restoreCallingIdentity(identity);
}
}
public boolean isRatingBlocked(TvContentRating rating) {
loadIfNeeded();
synchronized (mBlockedRatings) {
for (TvContentRating blockedRating : mBlockedRatings) {
if (rating.contains(blockedRating)) {
return true;
}
}
}
return false;
}
public void addBlockedRating(TvContentRating rating) {
loadIfNeeded();
if (rating != null && !mBlockedRatings.contains(rating)) {
mBlockedRatings.add(rating);
mBlockedRatingsChanged = true;
postSave();
}
}
public void removeBlockedRating(TvContentRating rating) {
loadIfNeeded();
if (rating != null && mBlockedRatings.contains(rating)) {
mBlockedRatings.remove(rating);
mBlockedRatingsChanged = true;
postSave();
}
}
private void loadBlockedRatingsFromXml(XmlPullParser parser)
throws IOException, XmlPullParserException {
final int outerDepth = parser.getDepth();
while (XmlUtils.nextElementWithin(parser, outerDepth)) {
if (parser.getName().equals(TAG_RATING)) {
String ratingString = parser.getAttributeValue(null, ATTR_STRING);
if (TextUtils.isEmpty(ratingString)) {
throw new XmlPullParserException(
"Missing " + ATTR_STRING + " attribute on " + TAG_RATING);
}
mBlockedRatings.add(TvContentRating.unflattenFromString(ratingString));
}
}
}
/**
* Converts a TV ratings from an XML file to {@link TvContentRating}.
*
* @param rating An XmlTvRating.
* @return A TvContentRating.
*/
private static TvContentRating xmlTvRatingToTvContentRating(XmlTvParser.XmlTvRating rating) {
if (ANDROID_TV_RATING.equals(rating.system)) {
return TvContentRating.unflattenFromString(rating.value);
}
return null;
}
/**
* Parses a string of comma-separated ratings into an array of {@link TvContentRating}.
*
* @param commaSeparatedRatings String containing various ratings, separated by commas.
* @return An array of TvContentRatings.
* @hide
*/
public static TvContentRating[] stringToContentRatings(String commaSeparatedRatings) {
if (TextUtils.isEmpty(commaSeparatedRatings)) {
return null;
}
String[] ratings = commaSeparatedRatings.split("\\s*,\\s*");
TvContentRating[] contentRatings = new TvContentRating[ratings.length];
for (int i = 0; i < contentRatings.length; ++i) {
contentRatings[i] = TvContentRating.unflattenFromString(ratings[i]);
}
return contentRatings;
}
/**
* Flattens an array of {@link TvContentRating} into a String to be inserted into a database.
*
* @param contentRatings An array of TvContentRatings.
* @return A comma-separated String of ratings.
* @hide
*/
public static String contentRatingsToString(TvContentRating[] contentRatings) {
if (contentRatings == null || contentRatings.length == 0) {
return null;
}
final String DELIMITER = ",";
StringBuilder ratings = new StringBuilder(contentRatings[0].flattenToString());
for (int i = 1; i < contentRatings.length; ++i) {
ratings.append(DELIMITER);
ratings.append(contentRatings[i].flattenToString());
}
return ratings.toString();
}
@Override
public void onUnblockContent(TvContentRating rating) {
// If called with null, parental controls are off.
if (rating == null) {
mUnblockedRatingSet.clear();
}
unblockContent(rating);
if (mPlayingRecordedProgram) {
playRecordedContent();
} else {
playCurrentContent();
}
}
private boolean blockContentIfNeeded() {
if (mCurrentContentRatingSet == null || !mTvInputManager.isParentalControlsEnabled()) {
// Content rating is invalid so we don't need to block anymore.
// Unblock content here explicitly to resume playback.
unblockContent(null);
return true;
}
// Check each content rating that the program has.
TvContentRating blockedRating = null;
for (TvContentRating contentRating : mCurrentContentRatingSet) {
if (mTvInputManager.isRatingBlocked(contentRating)
&& !mUnblockedRatingSet.contains(contentRating)) {
// This should be blocked.
blockedRating = contentRating;
}
}
if (blockedRating == null) {
// Content rating is null so we don't need to block anymore.
// Unblock content here explicitly to resume playback.
unblockContent(null);
return true;
}
mLastBlockedRating = blockedRating;
// Children restricted content might be blocked by TV app as well,
// but TIS should do its best not to show any single frame of blocked content.
onBlockContent(blockedRating);
notifyContentBlocked(blockedRating);
if (mTimeShiftedPlaybackPosition != TvInputManager.TIME_SHIFT_INVALID_TIME) {
onTimeShiftPause();
}
return false;
}
private void unblockContent(TvContentRating rating) {
// TIS should unblock content only if unblock request is legitimate.
if (rating == null || mLastBlockedRating == null || rating.equals(mLastBlockedRating)) {
mLastBlockedRating = null;
if (rating != null) {
mUnblockedRatingSet.add(rating);
}
notifyContentAllowed();
}
}
@RequiresApi(api = Build.VERSION_CODES.M) @Test
public void testFullyPopulatedProgram() {
// Tests cloning and database I/O of a program with every value being defined.
InternalProviderData internalProviderData = new InternalProviderData();
internalProviderData.setVideoType(TvContractUtils.SOURCE_TYPE_HLS);
internalProviderData.setVideoUrl("http://example.com/stream.m3u8");
Program fullyPopulatedProgram = new Program.Builder()
.setSearchable(false)
.setChannelId(3)
.setThumbnailUri("http://example.com/thumbnail.png")
.setInternalProviderData(internalProviderData)
.setAudioLanguages("en-us")
.setBroadcastGenres(new String[] {"Music", "Family"})
.setCanonicalGenres(new String[] {TvContract.Programs.Genres.MOVIES})
.setContentRatings(new TvContentRating[] {TvContentRating.UNRATED})
.setDescription("This is a sample program")
.setEndTimeUtcMillis(1000)
.setEpisodeNumber("Pilot", 0)
.setEpisodeTitle("Hello World")
.setLongDescription("This is a longer description than the previous description")
.setPosterArtUri("http://example.com/poster.png")
.setRecordingProhibited(false)
.setSeasonNumber("The Final Season", 7)
.setSeasonTitle("The Final Season")
.setStartTimeUtcMillis(0)
.setTitle("Google")
.setVideoHeight(1080)
.setVideoWidth(1920)
.build();
ContentValues contentValues = fullyPopulatedProgram.toContentValues();
compareProgram(fullyPopulatedProgram, Program.fromCursor(getProgramCursor(contentValues)));
Program clonedFullyPopulatedProgram = new Program.Builder(fullyPopulatedProgram).build();
compareProgram(fullyPopulatedProgram, clonedFullyPopulatedProgram);
}
@RequiresApi(api = Build.VERSION_CODES.M)
@Test
public void testProgramConversion() {
// Tests that a RecordedProgram can be converted to a Program and back to a RecordedProgram
RecordedProgram sampleRecordedProgram = new RecordedProgram.Builder()
.setAudioLanguages("en-us")
.setBroadcastGenres(new String[]{"Sports"})
.setCanonicalGenres(new String[]{TvContract.Programs.Genres.ANIMAL_WILDLIFE})
.setContentRatings(new TvContentRating[]{TvContentRating.UNRATED})
.setEpisodeTitle("Sample Episode")
.setInputId(TEST_INPUT_ID)
.setTitle("Sample Title")
.setSearchable(false)
.setStartTimeUtcMillis(0)
.setEndTimeUtcMillis(1000)
.setSeasonTitle("First Season")
.setSeasonDisplayNumber("1", 1)
.setVideoHeight(1080)
.setVideoWidth(1920)
.build();
Program sampleProgram = sampleRecordedProgram.toProgram();
RecordedProgram clonedSampleRecordedProgram = new RecordedProgram.Builder(sampleProgram)
.setInputId(TEST_INPUT_ID)
.build();
compareRecordedProgram(sampleRecordedProgram, clonedSampleRecordedProgram);
}
@RequiresApi(api = Build.VERSION_CODES.M)
@Test
public void testFullyPopulatedRecording() {
// Tests that every attribute in a RecordedProgram can be set and persist through database
// I/O operations
RecordedProgram fullyPopulatedProgram = new RecordedProgram.Builder()
.setAudioLanguages("en-us")
.setBroadcastGenres(new String[]{"Sports"})
.setCanonicalGenres(new String[]{TvContract.Programs.Genres.ANIMAL_WILDLIFE})
.setContentRatings(new TvContentRating[]{TvContentRating.UNRATED})
.setEpisodeDisplayNumber("24", 24)
.setEpisodeTitle("Sample Episode")
.setInputId(TEST_INPUT_ID)
.setTitle("Sample Title")
.setSearchable(false)
.setStartTimeUtcMillis(0)
.setEndTimeUtcMillis(1000)
.setInternalProviderData(new InternalProviderData())
.setRecordingDataBytes(1024 * 1024)
.setRecordingDataUri("file://sdcard/TV.apk")
.setRecordingDurationMillis(1000)
.setSeasonTitle("First Season")
.setSeasonDisplayNumber("1", 1)
.setVideoHeight(1080)
.setVideoWidth(1920)
.build();
ContentValues contentValues = fullyPopulatedProgram.toContentValues();
compareRecordedProgram(fullyPopulatedProgram,
RecordedProgram.fromCursor(getRecordedProgramCursor(contentValues)));
RecordedProgram clonedFullyPopulatedProgram =
new RecordedProgram.Builder(fullyPopulatedProgram).build();
compareRecordedProgram(fullyPopulatedProgram, clonedFullyPopulatedProgram);
}
public static TvContentRating[] stringToContentRatings(String commaSeparatedRatings) {
if (TextUtils.isEmpty(commaSeparatedRatings)) {
return null;
}
String[] ratings = commaSeparatedRatings.split("\\s*,\\s*");
TvContentRating[] contentRatings = new TvContentRating[ratings.length];
for (int i = 0; i < contentRatings.length; ++i) {
contentRatings[i] = TvContentRating.unflattenFromString(ratings[i]);
}
return contentRatings;
}
public static String contentRatingsToString(TvContentRating[] contentRatings) {
if (contentRatings == null || contentRatings.length == 0) {
return null;
}
final String DELIMITER = ",";
StringBuilder ratings = new StringBuilder(contentRatings[0].flattenToString());
for (int i = 1; i < contentRatings.length; ++i) {
ratings.append(DELIMITER);
ratings.append(contentRatings[i].flattenToString());
}
return ratings.toString();
}
@Override
public void onUnblockContent(TvContentRating unblockedRating) {
super.onUnblockContent(unblockedRating);
if(tvInputProvider.getApplicationContext().getResources().getBoolean(R.bool.channel_surfer_lifecycle_toasts))
Toast.makeText(tvInputProvider.getApplicationContext(), "Unblocked "+unblockedRating.flattenToString(), Toast.LENGTH_SHORT).show();
notifyContentAllowed();
}
/**
* Converts a TV ratings from an XML file to {@link TvContentRating}.
*
* @param rating An XmlTvRating.
* @return A TvContentRating.
*/
private static TvContentRating xmlTvRatingToTvContentRating(
CumulusXmlParser.XmlTvRating rating) {
if (ANDROID_TV_RATING.equals(rating.system)) {
return TvContentRating.unflattenFromString(rating.value);
}
return null;
}
/**
* Converts a TV ratings from an XML file to {@link TvContentRating}.
*
* @param rating An XmlTvRating.
* @return A TvContentRating.
*/
private static TvContentRating xmlTvRatingToTvContentRating(XmlTvParser.XmlTvRating rating) {
if (ANDROID_TV_RATING.equals(rating.system)) {
return TvContentRating.unflattenFromString(rating.value);
}
return null;
}
/**
* Parses a string of comma-separated ratings into an array of {@link TvContentRating}.
*
* @param commaSeparatedRatings String containing various ratings, separated by commas.
* @return An array of TvContentRatings.
* @hide
*/
public static TvContentRating[] stringToContentRatings(String commaSeparatedRatings) {
if (TextUtils.isEmpty(commaSeparatedRatings)) {
return null;
}
String[] ratings = commaSeparatedRatings.split("\\s*,\\s*");
TvContentRating[] contentRatings = new TvContentRating[ratings.length];
for (int i = 0; i < contentRatings.length; ++i) {
contentRatings[i] = TvContentRating.unflattenFromString(ratings[i]);
}
return contentRatings;
}
/**
* Flattens an array of {@link TvContentRating} into a String to be inserted into a database.
*
* @param contentRatings An array of TvContentRatings.
* @return A comma-separated String of ratings.
* @hide
*/
public static String contentRatingsToString(TvContentRating[] contentRatings) {
if (contentRatings == null || contentRatings.length == 0) {
return null;
}
final String DELIMITER = ",";
StringBuilder ratings = new StringBuilder(contentRatings[0].flattenToString());
for (int i = 1; i < contentRatings.length; ++i) {
ratings.append(DELIMITER);
ratings.append(contentRatings[i].flattenToString());
}
return ratings.toString();
}
@Override
public void onUnblockContent(TvContentRating rating) {
// If called with null, parental controls are off.
if (rating == null) {
mUnblockedRatingSet.clear();
}
unblockContent(rating);
if (mPlayingRecordedProgram) {
playRecordedContent();
} else {
playCurrentContent();
}
}
private boolean blockContentIfNeeded() {
if (mCurrentContentRatingSet == null || !mTvInputManager.isParentalControlsEnabled()) {
// Content rating is invalid so we don't need to block anymore.
// Unblock content here explicitly to resume playback.
unblockContent(null);
return true;
}
// Check each content rating that the program has.
TvContentRating blockedRating = null;
for (TvContentRating contentRating : mCurrentContentRatingSet) {
if (mTvInputManager.isRatingBlocked(contentRating)
&& !mUnblockedRatingSet.contains(contentRating)) {
// This should be blocked.
blockedRating = contentRating;
}
}
if (blockedRating == null) {
// Content rating is null so we don't need to block anymore.
// Unblock content here explicitly to resume playback.
unblockContent(null);
return true;
}
mLastBlockedRating = blockedRating;
// Children restricted content might be blocked by TV app as well,
// but TIS should do its best not to show any single frame of blocked content.
onBlockContent(blockedRating);
notifyContentBlocked(blockedRating);
if (mTimeShiftedPlaybackPosition != TvInputManager.TIME_SHIFT_INVALID_TIME) {
onTimeShiftPause();
}
return false;
}
private void unblockContent(TvContentRating rating) {
// TIS should unblock content only if unblock request is legitimate.
if (rating == null || mLastBlockedRating == null || rating.equals(mLastBlockedRating)) {
mLastBlockedRating = null;
if (rating != null) {
mUnblockedRatingSet.add(rating);
}
notifyContentAllowed();
}
}
@RequiresApi(api = Build.VERSION_CODES.M) @Test
public void testFullyPopulatedProgram() {
// Tests cloning and database I/O of a program with every value being defined.
InternalProviderData internalProviderData = new InternalProviderData();
internalProviderData.setVideoType(TvContractUtils.SOURCE_TYPE_HLS);
internalProviderData.setVideoUrl("http://example.com/stream.m3u8");
Program fullyPopulatedProgram = new Program.Builder()
.setSearchable(false)
.setChannelId(3)
.setThumbnailUri("http://example.com/thumbnail.png")
.setInternalProviderData(internalProviderData)
.setAudioLanguages("en-us")
.setBroadcastGenres(new String[] {"Music", "Family"})
.setCanonicalGenres(new String[] {TvContract.Programs.Genres.MOVIES})
.setContentRatings(new TvContentRating[] {TvContentRating.UNRATED})
.setDescription("This is a sample program")
.setEndTimeUtcMillis(1000)
.setEpisodeNumber("Pilot", 0)
.setEpisodeTitle("Hello World")
.setLongDescription("This is a longer description than the previous description")
.setPosterArtUri("http://example.com/poster.png")
.setRecordingProhibited(false)
.setSeasonNumber("The Final Season", 7)
.setSeasonTitle("The Final Season")
.setStartTimeUtcMillis(0)
.setTitle("Google")
.setVideoHeight(1080)
.setVideoWidth(1920)
.build();
ContentValues contentValues = fullyPopulatedProgram.toContentValues();
compareProgram(fullyPopulatedProgram, Program.fromCursor(getProgramCursor(contentValues)));
Program clonedFullyPopulatedProgram = new Program.Builder(fullyPopulatedProgram).build();
compareProgram(fullyPopulatedProgram, clonedFullyPopulatedProgram);
}