Skip to content

Commit

Permalink
Merge pull request #251 from androidx/release-1.0.0-rc01
Browse files Browse the repository at this point in the history
1.0.0 rc01
  • Loading branch information
christosts authored Feb 16, 2023
2 parents c2cbb63 + 98bf30d commit f17e846
Show file tree
Hide file tree
Showing 347 changed files with 27,478 additions and 6,091 deletions.
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/bug.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ body:
label: Media3 Version
description: What version of Media3 are you using?
options:
- 1.0.0-rc01
- 1.0.0-beta03
- 1.0.0-beta02
- 1.0.0-beta01
Expand Down
12 changes: 5 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,13 @@ Android, including local playback (via ExoPlayer) and media sessions.

## Current status

AndroidX Media is currently in beta and we welcome your feedback via the
[issue tracker][]. Please consult the [release notes][] for more details about
the beta release.
AndroidX Media is currently in release candidate and we welcome your feedback
via the [issue tracker][]. Please consult the [release notes][] for more details
about the current release.

ExoPlayer's new home will be in AndroidX Media, but for now we are publishing it
both in AndroidX Media and via the existing [ExoPlayer project][]. While
AndroidX Media is in beta we recommend that production apps using ExoPlayer
continue to depend on the existing ExoPlayer project. We are still handling
ExoPlayer issues on the [ExoPlayer issue tracker][].
both in AndroidX Media and via the existing [ExoPlayer project][] and we are
still handling ExoPlayer issues on the [ExoPlayer issue tracker][].

You'll find some [Media3 documentation on developer.android.com][], including a
[migration guide for existing ExoPlayer and MediaSession users][].
Expand Down
105 changes: 101 additions & 4 deletions RELEASENOTES.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,101 @@
Release notes
# Release notes

### 1.0.0-rc01 (2023-02-16)

This release corresponds to the
[ExoPlayer 2.18.3 release](https://github.com/google/ExoPlayer/releases/tag/r2.18.3).

* Core library:
* Tweak the renderer's decoder ordering logic to uphold the
`MediaCodecSelector`'s preferences, even if a decoder reports it may not
be able to play the media performantly. For example with default
selector, hardware decoder with only functional support will be
preferred over software decoder that fully supports the format
([#10604](https://github.com/google/ExoPlayer/issues/10604)).
* Add `ExoPlayer.Builder.setPlaybackLooper` that sets a pre-existing
playback thread for a new ExoPlayer instance.
* Allow download manager helpers to be cleared
([#10776](https://github.com/google/ExoPlayer/issues/10776)).
* Add parameter to `BasePlayer.seekTo` to also indicate the command used
for seeking.
* Use theme when loading drawables on API 21+
([#220](https://github.com/androidx/media/issues/220)).
* Add `ConcatenatingMediaSource2` that allows combining multiple media
items into a single window
([#247](https://github.com/androidx/media/issues/247)).
* Extractors:
* Throw a `ParserException` instead of a `NullPointerException` if the
sample table (stbl) is missing a required sample description (stsd) when
parsing trak atoms.
* Correctly skip samples when seeking directly to a sync frame in fMP4
([#10941](https://github.com/google/ExoPlayer/issues/10941)).
* Audio:
* Use the compressed audio format bitrate to calculate the min buffer size
for `AudioTrack` in direct playbacks (passthrough).
* Text:
* Fix `TextRenderer` passing an invalid (negative) index to
`Subtitle.getEventTime` if a subtitle file contains no cues.
* SubRip: Add support for UTF-16 files if they start with a byte order
mark.
* Metadata:
* Parse multiple null-separated values from ID3 frames, as permitted by
ID3 v2.4.
* Add `MediaMetadata.mediaType` to denote the type of content or the type
of folder described by the metadata.
* Add `MediaMetadata.isBrowsable` as a replacement for
`MediaMetadata.folderType`. The folder type will be deprecated in the
next release.
* DASH:
* Add full parsing for image adaptation sets, including tile counts
([#3752](https://github.com/google/ExoPlayer/issues/3752)).
* UI:
* Fix the deprecated
`PlayerView.setControllerVisibilityListener(PlayerControlView.VisibilityListener)`
to ensure visibility changes are passed to the registered listener
([#229](https://github.com/androidx/media/issues/229)).
* Fix the ordering of the center player controls in `PlayerView` when
using a right-to-left (RTL) layout
([#227](https://github.com/androidx/media/issues/227)).
* Session:
* Add abstract `SimpleBasePlayer` to help implement the `Player` interface
for custom players.
* Add helper method to convert platform session token to Media3
`SessionToken` ([#171](https://github.com/androidx/media/issues/171)).
* Use `onMediaMetadataChanged` to trigger updates of the platform media
session ([#219](https://github.com/androidx/media/issues/219)).
* Add the media session as an argument of `getMediaButtons()` of the
`DefaultMediaNotificationProvider` and use immutable lists for clarity
([#216](https://github.com/androidx/media/issues/216)).
* Add `onSetMediaItems` callback listener to provide means to modify/set
`MediaItem` list, starting index and position by session before setting
onto Player ([#156](https://github.com/androidx/media/issues/156)).
* Avoid double tap detection for non-Bluetooth media button events
([#233](https://github.com/androidx/media/issues/233)).
* Make `QueueTimeline` more robust in case of a shady legacy session state
([#241](https://github.com/androidx/media/issues/241)).
* Metadata:
* Parse multiple null-separated values from ID3 frames, as permitted by
ID3 v2.4.
* Add `MediaMetadata.mediaType` to denote the type of content or the type
of folder described by the metadata.
* Add `MediaMetadata.isBrowsable` as a replacement for
`MediaMetadata.folderType`. The folder type will be deprecated in the
next release.
* Cast extension:
* Bump Cast SDK version to 21.2.0.
* IMA extension:
* Remove player listener of the `ImaServerSideAdInsertionMediaSource` on
the application thread to avoid threading issues.
* Add a property `focusSkipButtonWhenAvailable` to the
`ImaServerSideAdInsertionMediaSource.AdsLoader.Builder` to request
focusing the skip button on TV devices and set it to true by default.
* Add a method `focusSkipButton()` to the
`ImaServerSideAdInsertionMediaSource.AdsLoader` to programmatically
request to focus the skip button.
* Bump IMA SDK version to 3.29.0.
* Demo app:
* Request notification permission for download notifications at runtime
([#10884](https://github.com/google/ExoPlayer/issues/10884)).

### 1.0.0-beta03 (2022-11-22)

Expand Down Expand Up @@ -259,15 +356,15 @@ This release corresponds to the
* Query the platform (API 29+) or assume the audio encoding channel count
for audio passthrough when the format audio channel count is unset,
which occurs with HLS chunkless preparation
([10204](https://github.com/google/ExoPlayer/issues/10204)).
([#10204](https://github.com/google/ExoPlayer/issues/10204)).
* Configure `AudioTrack` with channel mask
`AudioFormat.CHANNEL_OUT_7POINT1POINT4` if the decoder outputs 12
channel PCM audio
([#10322](#https://github.com/google/ExoPlayer/pull/10322).
([#10322](#https://github.com/google/ExoPlayer/pull/10322)).
* DRM
* Ensure the DRM session is always correctly updated when seeking
immediately after a format change
([10274](https://github.com/google/ExoPlayer/issues/10274)).
([#10274](https://github.com/google/ExoPlayer/issues/10274)).
* Text:
* Change `Player.getCurrentCues()` to return `CueGroup` instead of
`List<Cue>`.
Expand Down
4 changes: 2 additions & 2 deletions constants.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
project.ext {
releaseVersion = '1.0.0-beta03'
releaseVersionCode = 1_000_000_1_03
releaseVersion = '1.0.0-rc01'
releaseVersionCode = 1_000_000_2_01
minSdkVersion = 16
appTargetSdkVersion = 33
// API version before restricting local file access.
Expand Down
2 changes: 2 additions & 0 deletions demos/main/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>

<uses-feature android:name="android.software.leanback" android:required="false"/>
<uses-feature android:name="android.hardware.touchscreen" android:required="false"/>
Expand All @@ -35,6 +36,7 @@
android:largeHeap="true"
android:allowBackup="false"
android:requestLegacyExternalStorage="true"
android:supportsRtl="true"
android:name="androidx.multidex.MultiDexApplication"
tools:targetApi="29">

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;

import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
Expand All @@ -41,8 +42,10 @@
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.DoNotInline;
import androidx.annotation.Nullable;
import androidx.annotation.OptIn;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.media3.common.MediaItem;
import androidx.media3.common.MediaItem.ClippingConfiguration;
Expand Down Expand Up @@ -76,13 +79,16 @@ public class SampleChooserActivity extends AppCompatActivity
private static final String TAG = "SampleChooserActivity";
private static final String GROUP_POSITION_PREFERENCE_KEY = "sample_chooser_group_position";
private static final String CHILD_POSITION_PREFERENCE_KEY = "sample_chooser_child_position";
private static final int POST_NOTIFICATION_PERMISSION_REQUEST_CODE = 100;

private String[] uris;
private boolean useExtensionRenderers;
private DownloadTracker downloadTracker;
private SampleAdapter sampleAdapter;
private MenuItem preferExtensionDecodersMenuItem;
private ExpandableListView sampleListView;
@Nullable private MediaItem downloadMediaItemWaitingForNotificationPermission;
private boolean notificationPermissionToastShown;

@Override
public void onCreate(Bundle savedInstanceState) {
Expand Down Expand Up @@ -172,12 +178,34 @@ public void onDownloadsChanged() {
public void onRequestPermissionsResult(
int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == POST_NOTIFICATION_PERMISSION_REQUEST_CODE) {
handlePostNotificationPermissionGrantResults(grantResults);
} else {
handleExternalStoragePermissionGrantResults(grantResults);
}
}

private void handlePostNotificationPermissionGrantResults(int[] grantResults) {
if (!notificationPermissionToastShown
&& (grantResults.length == 0 || grantResults[0] != PackageManager.PERMISSION_GRANTED)) {
Toast.makeText(
getApplicationContext(), R.string.post_notification_not_granted, Toast.LENGTH_LONG)
.show();
notificationPermissionToastShown = true;
}
if (downloadMediaItemWaitingForNotificationPermission != null) {
// Download with or without permission to post notifications.
toggleDownload(downloadMediaItemWaitingForNotificationPermission);
downloadMediaItemWaitingForNotificationPermission = null;
}
}

private void handleExternalStoragePermissionGrantResults(int[] grantResults) {
if (grantResults.length == 0) {
// Empty results are triggered if a permission is requested while another request was already
// pending and can be safely ignored in this case.
return;
}
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
} else if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
loadSample();
} else {
Toast.makeText(getApplicationContext(), R.string.sample_list_load_error, Toast.LENGTH_LONG)
Expand Down Expand Up @@ -244,15 +272,26 @@ private void onSampleDownloadButtonClicked(PlaylistHolder playlistHolder) {
if (downloadUnsupportedStringId != 0) {
Toast.makeText(getApplicationContext(), downloadUnsupportedStringId, Toast.LENGTH_LONG)
.show();
} else if (!notificationPermissionToastShown
&& Util.SDK_INT >= 33
&& checkSelfPermission(Api33.getPostNotificationPermissionString())
!= PackageManager.PERMISSION_GRANTED) {
downloadMediaItemWaitingForNotificationPermission = playlistHolder.mediaItems.get(0);
requestPermissions(
new String[] {Api33.getPostNotificationPermissionString()},
/* requestCode= */ POST_NOTIFICATION_PERMISSION_REQUEST_CODE);
} else {
RenderersFactory renderersFactory =
DemoUtil.buildRenderersFactory(
/* context= */ this, isNonNullAndChecked(preferExtensionDecodersMenuItem));
downloadTracker.toggleDownload(
getSupportFragmentManager(), playlistHolder.mediaItems.get(0), renderersFactory);
toggleDownload(playlistHolder.mediaItems.get(0));
}
}

private void toggleDownload(MediaItem mediaItem) {
RenderersFactory renderersFactory =
DemoUtil.buildRenderersFactory(
/* context= */ this, isNonNullAndChecked(preferExtensionDecodersMenuItem));
downloadTracker.toggleDownload(getSupportFragmentManager(), mediaItem, renderersFactory);
}

private int getDownloadUnsupportedStringId(PlaylistHolder playlistHolder) {
if (playlistHolder.mediaItems.size() > 1) {
return R.string.download_playlist_unsupported;
Expand Down Expand Up @@ -630,4 +669,13 @@ public PlaylistGroup(String title) {
this.playlists = new ArrayList<>();
}
}

@RequiresApi(33)
private static class Api33 {

@DoNotInline
public static String getPostNotificationPermissionString() {
return Manifest.permission.POST_NOTIFICATIONS;
}
}
}
2 changes: 2 additions & 0 deletions demos/main/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@

<string name="sample_list_load_error">One or more sample lists failed to load</string>

<string name="post_notification_not_granted">Notifications suppressed. Grant permission to see download notifications.</string>

<string name="download_start_error">Failed to start download</string>

<string name="download_start_error_offline_license">Failed to obtain offline license</string>
Expand Down
2 changes: 1 addition & 1 deletion demos/session/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ android {
versionName project.ext.releaseVersion
versionCode project.ext.releaseVersionCode
minSdkVersion project.ext.minSdkVersion
targetSdkVersion project.ext.targetSdkVersion
targetSdkVersion project.ext.appTargetSdkVersion
multiDexEnabled true
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import com.google.common.util.concurrent.ListenableFuture
class MainActivity : AppCompatActivity() {
private lateinit var browserFuture: ListenableFuture<MediaBrowser>
private val browser: MediaBrowser?
get() = if (browserFuture.isDone) browserFuture.get() else null
get() = if (browserFuture.isDone && !browserFuture.isCancelled) browserFuture.get() else null

private lateinit var mediaListAdapter: FolderMediaItemArrayAdapter
private lateinit var mediaListView: ListView
Expand Down
Loading

0 comments on commit f17e846

Please sign in to comment.